diff --git a/genesis/gen_test.go b/genesis/gen_test.go
index 18ff69a77..403da98ed 100644
--- a/genesis/gen_test.go
+++ b/genesis/gen_test.go
@@ -1,3 +1,18 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax. If not, see .
+
package genesis
import (
diff --git a/genesis/genesis.go b/genesis/genesis.go
new file mode 100644
index 000000000..fb348693f
--- /dev/null
+++ b/genesis/genesis.go
@@ -0,0 +1,85 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax. If not, see .
+
+package genesis
+
+import (
+ "bytes"
+ "encoding/json"
+ "time"
+
+ ptypes "github.com/eris-ltd/eris-db/permission/types"
+ wire "github.com/tendermint/go-wire"
+)
+
+// MakeGenesisDocFromAccounts takes a chainName and a slice of pointers to GenesisAccount,
+// and a slice of pointers to GenesisValidator to construct a GenesisDoc, or returns an error on
+// failure. In particular MakeGenesisDocFromAccount uses the local time as a
+// timestamp for the GenesisDoc.
+func MakeGenesisDocFromAccounts(chainName string, accounts []*GenesisAccount,
+ validators []*GenesisValidator) (GenesisDoc, error) {
+
+ // TODO: assert valid accounts and validators
+ // TODO: [ben] expose setting global permissions
+ globalPermissions := ptypes.DefaultAccountPermissions.Clone()
+ genesisParameters := &GenesisParams{
+ GlobalPermissions: &globalPermissions,
+ }
+ // copy slice of pointers to accounts into slice of accounts
+ accountsCopy := make([]GenesisAccount, len(accounts))
+ for i, genesisAccount := range accounts {
+ accountsCopy[i] = genesisAccount.Clone()
+ }
+ // copy slice of pointers to validators into slice of validators
+ validatorsCopy := make([]GenesisValidator, len(validators))
+ for i, genesisValidator := range validators {
+ genesisValidatorCopy, err := genesisValidator.Clone()
+ if err != nil {
+ return GenesisDoc{}, err
+ }
+ validatorsCopy[i] = genesisValidatorCopy
+ }
+ genesisDoc := GenesisDoc{
+ GenesisTime: time.Now(),
+ // TODO: this needs to be corrected for ChainName, and ChainId
+ // is the derived hash from the GenesisDoc serialised bytes
+ ChainID: chainName,
+ Params: genesisParameters,
+ Accounts: accountsCopy,
+ Validators: validatorsCopy,
+ }
+ return genesisDoc, nil
+}
+
+// GetGenesisFileBytes returns the JSON (not-yet) canonical bytes for a given
+// GenesisDoc or an error. In a first rewrite, rely on go-wire
+// for the JSON serialisation with type-bytes.
+func GetGenesisFileBytes(genesisDoc *GenesisDoc) ([]byte, error) {
+
+ // TODO: write JSON in canonical order
+ var err error
+ buffer, n := new(bytes.Buffer), new(int)
+ // write JSON with go-wire type-bytes (for public keys)
+ wire.WriteJSON(genesisDoc, buffer, n, &err)
+ if err != nil {
+ return nil, err
+ }
+ // rewrite buffer with indentation
+ indentedBuffer := new(bytes.Buffer)
+ if err := json.Indent(indentedBuffer, buffer.Bytes(), "", "\t"); err != nil {
+ return nil, err
+ }
+ return indentedBuffer.Bytes(), nil
+}
diff --git a/genesis/make_genesis_file.go b/genesis/make_genesis_file.go
index f67a86d87..4fffd203d 100644
--- a/genesis/make_genesis_file.go
+++ b/genesis/make_genesis_file.go
@@ -27,6 +27,25 @@ func GenerateKnown(chainID, accountsPathCSV, validatorsPathCSV string) (string,
time.Now())
}
+//------------------------------------------------------------------------------------
+// interface functions that are consumed by monax tooling
+
+func GenerateGenesisFileBytes(chainName string, genesisAccounts []*GenesisAccount,
+ genesisValidators []*GenesisValidator) ([]byte, error) {
+ genesisDoc, err := MakeGenesisDocFromAccounts(chainName, genesisAccounts, genesisValidators)
+
+ buf, buf2, n := new(bytes.Buffer), new(bytes.Buffer), new(int)
+ wire.WriteJSON(genesisDoc, buf, n, &err)
+ if err != nil {
+ return nil, err
+ }
+ if err := json.Indent(buf2, buf.Bytes(), "", "\t"); err != nil {
+ return nil, err
+ }
+
+ return buf2.Bytes(), nil
+}
+
//------------------------------------------------------------------------------------
// core functions that provide functionality for monax tooling in v0.16
diff --git a/genesis/maker.go b/genesis/maker.go
new file mode 100644
index 000000000..b9a403726
--- /dev/null
+++ b/genesis/maker.go
@@ -0,0 +1,85 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax. If not, see .
+
+package genesis
+
+import (
+ "fmt"
+
+ ptypes "github.com/eris-ltd/eris-db/permission/types"
+
+ "github.com/tendermint/go-crypto"
+)
+
+const (
+ PublicKeyEd25519ByteLength int = 32
+ PublicKeySecp256k1ByteLength int = 64
+)
+
+// NewGenesisAccount returns a new GenesisAccount
+func NewGenesisAccount(address []byte, amount int64, name string,
+ permissions *ptypes.AccountPermissions) *GenesisAccount {
+ return &GenesisAccount{
+ Address: address,
+ Amount: amount,
+ Name: name,
+ Permissions: permissions,
+ }
+}
+
+func NewGenesisValidator(amount int64, name string, unbondToAddress []byte,
+ unbondAmount int64, keyType string, publicKeyBytes []byte) (*GenesisValidator, error) {
+ // convert the key bytes into a typed fixed size byte array
+ var typedPublicKeyBytes []byte
+ switch keyType {
+ case "ed25519":
+ // TODO: [ben] functionality and checks need to be inherit in the type
+ if len(publicKeyBytes) != PublicKeyEd25519ByteLength {
+ return nil, fmt.Errorf("Invalid length provided for ed25519 public key (len %v)",
+ len(publicKeyBytes))
+ }
+ // ed25519 has type byte 0x01
+ typedPublicKeyBytes = make([]byte, PublicKeyEd25519ByteLength+1)
+ // prepend type byte to public key
+ typedPublicKeyBytes = append([]byte{crypto.PubKeyTypeEd25519}, publicKeyBytes...)
+ case "secp256k1":
+ if len(publicKeyBytes) != PublicKeySecp256k1ByteLength {
+ return nil, fmt.Errorf("Invalid length provided for secp256k1 public key (len %v)",
+ len(publicKeyBytes))
+ }
+ // secp256k1 has type byte 0x02
+ typedPublicKeyBytes = make([]byte, PublicKeySecp256k1ByteLength+1)
+ // prepend type byte to public key
+ typedPublicKeyBytes = append([]byte{crypto.PubKeyTypeSecp256k1}, publicKeyBytes...)
+ default:
+ return nil, fmt.Errorf("Unsupported key type (%s)", keyType)
+ }
+ newPublicKey, err := crypto.PubKeyFromBytes(typedPublicKeyBytes)
+ if err != nil {
+ return nil, err
+ }
+ // ability to unbond to multiple accounts currently unused
+ var unbondTo []BasicAccount
+
+ return &GenesisValidator{
+ PubKey: newPublicKey,
+ Amount: unbondAmount,
+ Name: name,
+ UnbondTo: append(unbondTo, BasicAccount{
+ Address: unbondToAddress,
+ Amount: unbondAmount,
+ }),
+ }, nil
+}
diff --git a/genesis/types.go b/genesis/types.go
index d03e61976..40395fb79 100644
--- a/genesis/types.go
+++ b/genesis/types.go
@@ -1,3 +1,18 @@
+// Copyright 2015-2017 Monax Industries Limited.
+// This file is part of the Monax platform (Monax)
+
+// Monax is free software: you can use, redistribute it and/or modify
+// it only under the terms of the GNU General Public License, version
+// 3, as published by the Free Software Foundation.
+
+// Monax is distributed WITHOUT ANY WARRANTY pursuant to
+// the terms of the Gnu General Public Licence, version 3, including
+// (but not limited to) Clause 15 thereof. See the text of the
+// GNU General Public License, version 3 for full terms.
+
+// You should have received a copy of the GNU General Public License,
+// version 3, with Monax. If not, see .
+
package genesis
import (
@@ -6,6 +21,7 @@ import (
"time"
ptypes "github.com/eris-ltd/eris-db/permission/types"
+
"github.com/tendermint/go-crypto"
"github.com/tendermint/go-wire"
)
@@ -37,6 +53,19 @@ type GenesisValidator struct {
UnbondTo []BasicAccount `json:"unbond_to"`
}
+// GenesisPrivateValidator marshals the state of the private
+// validator for the purpose of Genesis creation; and hence
+// is defined in genesis and not under consensus, where
+// PrivateValidator (currently inherited from Tendermint) is.
+type GenesisPrivateValidator struct {
+ Address string `json:"address"`
+ PubKey []interface{} `json:"pub_key"`
+ PrivKey []interface{} `json:"priv_key"`
+ LastHeight int64 `json:"last_height"`
+ LastRound int64 `json:"last_round"`
+ LastStep int64 `json:"last_step"`
+}
+
type GenesisParams struct {
GlobalPermissions *ptypes.AccountPermissions `json:"global_permissions"`
}
@@ -65,3 +94,65 @@ func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
}
return
}
+
+//------------------------------------------------------------
+// Methods for genesis types
+// NOTE: breaks formatting convention
+// TODO: split each genesis type in its own file definition
+
+//------------------------------------------------------------
+// GenesisAccount methods
+
+// Clone clones the genesis account
+func (genesisAccount *GenesisAccount) Clone() GenesisAccount {
+ // clone the address
+ addressClone := make([]byte, len(genesisAccount.Address))
+ copy(addressClone, genesisAccount.Address)
+ // clone the account permissions
+ accountPermissionsClone := genesisAccount.Permissions.Clone()
+ return GenesisAccount{
+ Address: addressClone,
+ Amount: genesisAccount.Amount,
+ Name: genesisAccount.Name,
+ Permissions: &accountPermissionsClone,
+ }
+}
+
+//------------------------------------------------------------
+// GenesisValidator methods
+
+// Clone clones the genesis validator
+func (genesisValidator *GenesisValidator) Clone() (GenesisValidator, error) {
+ if genesisValidator == nil {
+ return GenesisValidator{}, fmt.Errorf("Cannot clone nil GenesisValidator.")
+ }
+ if genesisValidator.PubKey == nil {
+ return GenesisValidator{}, fmt.Errorf("Invalid GenesisValidator %s with nil public key.",
+ genesisValidator.Name)
+ }
+ // clone the addresses to unbond to
+ unbondToClone := make([]BasicAccount, len(genesisValidator.UnbondTo))
+ for i, basicAccount := range genesisValidator.UnbondTo {
+ unbondToClone[i] = basicAccount.Clone()
+ }
+ return GenesisValidator{
+ PubKey: genesisValidator.PubKey,
+ Amount: genesisValidator.Amount,
+ Name: genesisValidator.Name,
+ UnbondTo: unbondToClone,
+ }, nil
+}
+
+//------------------------------------------------------------
+// BasicAccount methods
+
+// Clone clones the basic account
+func (basicAccount *BasicAccount) Clone() BasicAccount {
+ // clone the address
+ addressClone := make([]byte, len(basicAccount.Address))
+ copy(addressClone, basicAccount.Address)
+ return BasicAccount{
+ Address: addressClone,
+ Amount: basicAccount.Amount,
+ }
+}
diff --git a/manager/eris-mint/state/genesis_test.go b/manager/eris-mint/state/genesis_test.go
index c9305ed4b..47541d931 100644
--- a/manager/eris-mint/state/genesis_test.go
+++ b/manager/eris-mint/state/genesis_test.go
@@ -31,7 +31,7 @@ var g1 = fmt.Sprintf(`
{
"address": "%X",
"amount": %d,
- "name": "%s",
+ "name": "%s",
"permissions": {
"base": {
"perms": %d,
diff --git a/manager/eris-mint/state/types/genesis.go b/manager/eris-mint/state/types/genesis.go
deleted file mode 100644
index 90d54cf72..000000000
--- a/manager/eris-mint/state/types/genesis.go
+++ /dev/null
@@ -1,63 +0,0 @@
-package types
-
-import (
- "fmt"
- "time"
-
- "github.com/eris-ltd/eris-db/common/sanity"
- ptypes "github.com/eris-ltd/eris-db/permission/types"
-
- "github.com/tendermint/go-crypto"
- "github.com/tendermint/go-wire"
-)
-
-//------------------------------------------------------------
-// we store the gendoc in the db
-
-var GenDocKey = []byte("GenDocKey")
-
-//------------------------------------------------------------
-// core types for a genesis definition
-
-type BasicAccount struct {
- Address []byte `json:"address"`
- Amount int64 `json:"amount"`
-}
-
-type GenesisAccount struct {
- Address []byte `json:"address"`
- Amount int64 `json:"amount"`
- Name string `json:"name"`
- Permissions *ptypes.AccountPermissions `json:"permissions"`
-}
-
-type GenesisValidator struct {
- PubKey crypto.PubKey `json:"pub_key"`
- Amount int64 `json:"amount"`
- Name string `json:"name"`
- UnbondTo []BasicAccount `json:"unbond_to"`
-}
-
-type GenesisParams struct {
- GlobalPermissions *ptypes.AccountPermissions `json:"global_permissions"`
-}
-
-type GenesisDoc struct {
- GenesisTime time.Time `json:"genesis_time"`
- ChainID string `json:"chain_id"`
- Params *GenesisParams `json:"params"`
- Accounts []GenesisAccount `json:"accounts"`
- Validators []GenesisValidator `json:"validators"`
-}
-
-//------------------------------------------------------------
-// Make genesis state from file
-
-func GenesisDocFromJSON(jsonBlob []byte) (genState *GenesisDoc) {
- var err error
- wire.ReadJSONPtr(&genState, jsonBlob, &err)
- if err != nil {
- sanity.PanicCrisis(fmt.Sprintf("Couldn't read GenesisDoc: %v", err))
- }
- return
-}
diff --git a/permission/types/permissions.go b/permission/types/permissions.go
index 03ff4b6ba..c6ebd5847 100644
--- a/permission/types/permissions.go
+++ b/permission/types/permissions.go
@@ -168,6 +168,21 @@ func (aP *AccountPermissions) RmRole(role string) bool {
return false
}
+// Clone clones the account permissions
+func (accountPermissions *AccountPermissions) Clone() AccountPermissions {
+ // clone base permissions
+ basePermissionsClone := accountPermissions.Base
+ // clone roles []string
+ rolesClone := make([]string, len(accountPermissions.Roles))
+ // strings are immutable so copy suffices
+ copy(rolesClone, accountPermissions.Roles)
+
+ return AccountPermissions{
+ Base: basePermissionsClone,
+ Roles: rolesClone,
+ }
+}
+
//--------------------------------------------------------------------------------
// string utilities
diff --git a/permission/types/util.go b/permission/types/util.go
new file mode 100644
index 000000000..15a377ef9
--- /dev/null
+++ b/permission/types/util.go
@@ -0,0 +1,35 @@
+package types
+
+// ConvertMapStringIntToPermissions converts a map of string-integer pairs and a slice of
+// strings for the roles to an AccountPermissions type. The integer needs to be greater
+// than zero to set the permission. For all unmentioned permissions the ZeroBasePermissions
+// is defaulted to.
+// TODO: [ben] re-evaluate the use of int for setting the permission.
+func ConvertPermissionsMapAndRolesToAccountPermissions(permissions map[string]int, roles []string) (*AccountPermissions, error) {
+ var err error
+ accountPermissions := &AccountPermissions{}
+ accountPermissions.Base, err = convertPermissionsMapStringIntToBasePermissions(permissions)
+ if err != nil {
+ return nil, err
+ }
+ accountPermissions.Roles = roles
+ return accountPermissions, nil
+}
+
+// convertPermissionsMapStringIntToBasePermissions converts a map of string-integer pairs to
+// BasePermissions.
+func convertPermissionsMapStringIntToBasePermissions(permissions map[string]int) (BasePermissions, error) {
+ // initialise basePermissions as ZeroBasePermissions
+ basePermissions := ZeroBasePermissions
+
+ for permissionName, value := range permissions {
+ permissionsFlag, err := PermStringToFlag(permissionName)
+ if err != nil {
+ return basePermissions, err
+ }
+ // sets the permissions bitflag and the setbit flag for the permission.
+ basePermissions.Set(permissionsFlag, value > 0)
+ }
+
+ return basePermissions, nil
+}
diff --git a/rpc/tendermint/test/shared.go b/rpc/tendermint/test/shared.go
index a3d0310cc..0d75ea279 100644
--- a/rpc/tendermint/test/shared.go
+++ b/rpc/tendermint/test/shared.go
@@ -19,7 +19,7 @@ import (
"github.com/eris-ltd/eris-db/txs"
"github.com/eris-ltd/eris-db/word256"
- state_types "github.com/eris-ltd/eris-db/manager/eris-mint/state/types"
+ genesis "github.com/eris-ltd/eris-db/genesis"
"github.com/spf13/viper"
"github.com/tendermint/go-crypto"
rpcclient "github.com/tendermint/go-rpc/client"
@@ -33,7 +33,7 @@ var (
mempoolCount = 0
chainID string
websocketAddr string
- genesisDoc *state_types.GenesisDoc
+ genesisDoc *genesis.GenesisDoc
websocketEndpoint string
user = makeUsers(5) // make keys
jsonRpcClient rpcclient.Client
@@ -48,7 +48,7 @@ func initGlobalVariables(ffs *fixtures.FileFixtures) error {
rootWorkDir = ffs.AddDir("rootWorkDir")
rootDataDir := ffs.AddDir("rootDataDir")
genesisFile := ffs.AddFile("rootWorkDir/genesis.json", defaultGenesis)
- genesisDoc = state_types.GenesisDocFromJSON([]byte(defaultGenesis))
+ genesisDoc = genesis.GenesisDocFromJSON([]byte(defaultGenesis))
if ffs.Error != nil {
return ffs.Error
diff --git a/test/testdata/testdata/testdata.go b/test/testdata/testdata/testdata.go
index 5fd2be000..11120bb90 100644
--- a/test/testdata/testdata/testdata.go
+++ b/test/testdata/testdata/testdata.go
@@ -5,7 +5,7 @@ import (
consensus_types "github.com/eris-ltd/eris-db/consensus/types"
core_types "github.com/eris-ltd/eris-db/core/types"
event "github.com/eris-ltd/eris-db/event"
- stypes "github.com/eris-ltd/eris-db/manager/eris-mint/state/types"
+ genesis "github.com/eris-ltd/eris-db/genesis"
rpc_v0 "github.com/eris-ltd/eris-db/rpc/v0"
"github.com/eris-ltd/eris-db/rpc/v0/shared"
transaction "github.com/eris-ltd/eris-db/txs"
@@ -540,7 +540,7 @@ var serverDuration uint = 100
type (
ChainData struct {
PrivValidator *mintTypes.PrivValidator `json:"priv_validator"`
- Genesis *stypes.GenesisDoc `json:"genesis"`
+ Genesis *genesis.GenesisDoc `json:"genesis"`
}
GetAccountData struct {