From 8ccff1ff2ffd0331fdcc38d6f3b4473d9dbbbf67 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 16 Feb 2017 13:27:09 +0100 Subject: [PATCH 1/9] permissions: introduce utility to convert string map of permissions into AccountPermission --- permission/types/util.go | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 permission/types/util.go 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 +} From 14ddd4d4eb237111d3da6023773cb131117da052 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Sun, 19 Feb 2017 00:57:38 +0100 Subject: [PATCH 2/9] genesis: add GenesisPrivateValidator and constructors for GenesisAccount and GenesisValidator --- genesis/maker.go | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ genesis/types.go | 13 +++++++++ 2 files changed, 86 insertions(+) create mode 100644 genesis/maker.go diff --git a/genesis/maker.go b/genesis/maker.go new file mode 100644 index 000000000..e913a115f --- /dev/null +++ b/genesis/maker.go @@ -0,0 +1,73 @@ +// 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" +) + +// 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) { + var publicKey crypto.PubKey + // convert the key bytes into a typed fixed size byte array + switch keyType { + case "ed25519": + // TODO: [ben] functionality and checks need to be inherit in the type + if len(publicKeyBytes) != 32 { + return nil, fmt.Errorf("Invalid length provided for ed25519 public key (len %v)", + len(publicKeyBytes)) + } + publicKey := crypto.PubKeyEd25519{} + copy(publicKey[:], publicKeyBytes[:32]) + case "secp256k1": + if len(publicKeyBytes) != 64 { + return nil, fmt.Errorf("Invalid length provided for secp256k1 public key (len %v)", + len(publicKeyBytes)) + } + publicKey := crypto.PubKeySecp256k1{} + copy(publicKey[:], publicKeyBytes[:64]) + default: + return nil, fmt.Errorf("Unsupported key type (%s)", keyType) + } + + // ability to unbond to multiple accounts currently unused + var unbondTo []BasicAccount + + return &GenesisValidator{ + PubKey: publicKey, + Amount: amount, + Name: name, + UnbondTo: append(unbondTo, BasicAccount{ + Address: unbondToAddress, + Amount: unbondAmount, + }), + }, nil +} diff --git a/genesis/types.go b/genesis/types.go index d03e61976..3469684bc 100644 --- a/genesis/types.go +++ b/genesis/types.go @@ -37,6 +37,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 []byte `json:"address"` + PubKey crypto.PubKey `json:"pub_key"` + PrivKey crypto.PrivKey `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"` } From 3270d0c56189187f3609c468f3da98dfde6d387a Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 30 Jan 2017 14:19:53 +0100 Subject: [PATCH 3/9] genesis: rework genesis --- genesis/gen_test.go | 15 +++++++ genesis/genesis.go | 75 +++++++++++++++++++++++++++++++++ genesis/genesis_test.go | 28 ++++++++++++ genesis/types.go | 69 ++++++++++++++++++++++++++++++ permission/types/permissions.go | 15 +++++++ 5 files changed, 202 insertions(+) create mode 100644 genesis/genesis.go create mode 100644 genesis/genesis_test.go 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..a33386a1b --- /dev/null +++ b/genesis/genesis.go @@ -0,0 +1,75 @@ +// 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 GenesisAccount, +// and a slice of 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 slices of validators and accounts + accountsCopy := make([]GenesisAccount, len(accounts)) + copy(accountsCopy, accounts) + + 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: accounts, + Validators: validators, + } + 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 + + buffer, n, err := new(bytes.Buffer), new(int), new(error) + // write JSON with go-wire type-bytes (for public keys); deprecate + 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/genesis_test.go b/genesis/genesis_test.go new file mode 100644 index 000000000..269c28f83 --- /dev/null +++ b/genesis/genesis_test.go @@ -0,0 +1,28 @@ +// 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" + "io/ioutil" + "os" + "path/filepath" + "testing" +) + +func TestGenesisFileBytes(t *testing.T) { + +} diff --git a/genesis/types.go b/genesis/types.go index 3469684bc..2e25f32a2 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 ( @@ -78,3 +93,57 @@ 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 { + // clone the public key + + // clone the account permissions + accountPermissionsClone := genesisAccount.Permissions.Clone() + return GenesisAccount{ + Address: addressClone, + Amount: genesisAccount.amount, + Name: genesisAccount.Name, + Permissions: &accountPermissionsClone, + } +} + +//------------------------------------------------------------ +// 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 GenesisAccount{ + Address: addressClone, + Amount: basicAccount.Amount, + } +} \ No newline at end of file diff --git a/permission/types/permissions.go b/permission/types/permissions.go index 15706c9f8..d20908a0c 100644 --- a/permission/types/permissions.go +++ b/permission/types/permissions.go @@ -162,6 +162,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 From aaf27e9b1102ed114dfb8fddd667134400e23673 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 20 Feb 2017 15:56:57 +0100 Subject: [PATCH 4/9] eris-mint: remove lingering genesis/types --- manager/eris-mint/state/genesis_test.go | 2 +- manager/eris-mint/state/types/genesis.go | 63 ------------------------ 2 files changed, 1 insertion(+), 64 deletions(-) delete mode 100644 manager/eris-mint/state/types/genesis.go 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 -} From 804cadcff9d639b24d642d38a63e80d7e5e42e43 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 20 Feb 2017 16:59:01 +0100 Subject: [PATCH 5/9] genesis: MakeGenesisDocFromAccountsAndValidators --- genesis/genesis.go | 34 ++++++++++++++++++---------- genesis/genesis_test.go | 28 ----------------------- genesis/types.go | 36 ++++++++++++++++++------------ rpc/tendermint/test/shared.go | 6 ++--- test/testdata/testdata/testdata.go | 4 ++-- 5 files changed, 49 insertions(+), 59 deletions(-) delete mode 100644 genesis/genesis_test.go diff --git a/genesis/genesis.go b/genesis/genesis.go index a33386a1b..85bc3a831 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -24,12 +24,12 @@ import ( wire "github.com/tendermint/go-wire" ) -// MakeGenesisDocFromAccounts takes a chainName and a slice of GenesisAccount, -// and a slice of GenesisValidator to construct a GenesisDoc, or returns an error on +// 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) { +func MakeGenesisDocFromAccounts(chainName string, accounts []*GenesisAccount, + validators []*GenesisValidator) (GenesisDoc, error) { // TODO: assert valid accounts and validators // TODO: [ben] expose setting global permissions @@ -37,18 +37,28 @@ func MakeGenesisDocFromAccounts(chainName string, accounts []*GenesisAccount, va genesisParameters := &GenesisParams{ GlobalPermissions: &globalPermissions, } - // copy slices of validators and accounts + // copy slice of pointers to accounts into slice of accounts accountsCopy := make([]GenesisAccount, len(accounts)) - copy(accountsCopy, accounts) - + for _, genesisAccount := range accounts { + accountsCopy = append(accountsCopy, genesisAccount.Clone()) + } + // copy slice of pointers to validators into slice of validators + validatorsCopy := make([]GenesisValidator, len(validators)) + for _, genesisValidator := range validators { + genesisValidatorCopy, err := genesisValidator.Clone() + if err != nil { + return GenesisDoc{}, err + } + validatorsCopy = append(validatorsCopy, 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: accounts, - Validators: validators, + Accounts: accountsCopy, + Validators: validatorsCopy, } return genesisDoc, nil } @@ -59,9 +69,9 @@ func MakeGenesisDocFromAccounts(chainName string, accounts []*GenesisAccount, va func GetGenesisFileBytes(genesisDoc *GenesisDoc) ([]byte, error) { // TODO: write JSON in canonical order - - buffer, n, err := new(bytes.Buffer), new(int), new(error) - // write JSON with go-wire type-bytes (for public keys); deprecate + 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 diff --git a/genesis/genesis_test.go b/genesis/genesis_test.go deleted file mode 100644 index 269c28f83..000000000 --- a/genesis/genesis_test.go +++ /dev/null @@ -1,28 +0,0 @@ -// 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" - "io/ioutil" - "os" - "path/filepath" - "testing" -) - -func TestGenesisFileBytes(t *testing.T) { - -} diff --git a/genesis/types.go b/genesis/types.go index 2e25f32a2..292c48510 100644 --- a/genesis/types.go +++ b/genesis/types.go @@ -21,6 +21,7 @@ import ( "time" ptypes "github.com/eris-ltd/eris-db/permission/types" + "github.com/tendermint/go-crypto" "github.com/tendermint/go-wire" ) @@ -121,17 +122,24 @@ func (genesisAccount *GenesisAccount) Clone() GenesisAccount { // GenesisValidator methods // Clone clones the genesis validator -func (genesisValidator *GenesisValidator) Clone() GenesisValidator { - // clone the public key - - // clone the account permissions - accountPermissionsClone := genesisAccount.Permissions.Clone() - return GenesisAccount{ - Address: addressClone, - Amount: genesisAccount.amount, - Name: genesisAccount.Name, - Permissions: &accountPermissionsClone, +func (genesisValidator *GenesisValidator) Clone() (GenesisValidator, error) { + // clone the public key by writing and reading over go-wire serialisation + // TODO! write unit test to see whether this is correct + publicKeyClone, err := crypto.PubKeyFromBytes(genesisValidator.PubKey.Bytes()) + if err != nil { + return GenesisValidator{}, err + } + // clone the addresses to unbond to + unbondToClone := make([]BasicAccount, len(genesisValidator.UnbondTo)) + for _, basicAccount := range genesisValidator.UnbondTo { + unbondToClone = append(unbondToClone, basicAccount.Clone()) } + return GenesisValidator{ + PubKey: publicKeyClone, + Amount: genesisValidator.Amount, + Name: genesisValidator.Name, + UnbondTo: unbondToClone, + }, nil } //------------------------------------------------------------ @@ -142,8 +150,8 @@ func (basicAccount *BasicAccount) Clone() BasicAccount { // clone the address addressClone := make([]byte, len(basicAccount.Address)) copy(addressClone, basicAccount.Address) - return GenesisAccount{ - Address: addressClone, - Amount: basicAccount.Amount, + return BasicAccount{ + Address: addressClone, + Amount: basicAccount.Amount, } -} \ No newline at end of file +} 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 { From 1e71bd481c150c241e71ede16229331f965e15ec Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 20 Feb 2017 19:15:17 +0100 Subject: [PATCH 6/9] genesis: add GenerateGenesisFileBytes() --- genesis/make_genesis_file.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) 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 From 4c1951d90388a29dccbf0aba16955edb53e8d8cf Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 21 Feb 2017 16:19:21 +0100 Subject: [PATCH 7/9] genesis: corrections to clone and other minor fixes --- genesis/genesis.go | 8 ++++---- genesis/maker.go | 23 +++++++++++++++-------- genesis/types.go | 23 +++++++++++++++-------- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/genesis/genesis.go b/genesis/genesis.go index 85bc3a831..fb348693f 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -39,17 +39,17 @@ func MakeGenesisDocFromAccounts(chainName string, accounts []*GenesisAccount, } // copy slice of pointers to accounts into slice of accounts accountsCopy := make([]GenesisAccount, len(accounts)) - for _, genesisAccount := range accounts { - accountsCopy = append(accountsCopy, genesisAccount.Clone()) + 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 _, genesisValidator := range validators { + for i, genesisValidator := range validators { genesisValidatorCopy, err := genesisValidator.Clone() if err != nil { return GenesisDoc{}, err } - validatorsCopy = append(validatorsCopy, genesisValidatorCopy) + validatorsCopy[i] = genesisValidatorCopy } genesisDoc := GenesisDoc{ GenesisTime: time.Now(), diff --git a/genesis/maker.go b/genesis/maker.go index e913a115f..184be977b 100644 --- a/genesis/maker.go +++ b/genesis/maker.go @@ -36,8 +36,8 @@ func NewGenesisAccount(address []byte, amount int64, name string, func NewGenesisValidator(amount int64, name string, unbondToAddress []byte, unbondAmount int64, keyType string, publicKeyBytes []byte) (*GenesisValidator, error) { - var publicKey crypto.PubKey // 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 @@ -45,25 +45,32 @@ func NewGenesisValidator(amount int64, name string, unbondToAddress []byte, return nil, fmt.Errorf("Invalid length provided for ed25519 public key (len %v)", len(publicKeyBytes)) } - publicKey := crypto.PubKeyEd25519{} - copy(publicKey[:], publicKeyBytes[:32]) + // ed25519 has type byte 0x01 + typedPublicKeyBytes = make([]byte, 33) + // prepend type byte to public key + typedPublicKeyBytes = append([]byte{crypto.PubKeyTypeEd25519}, publicKeyBytes...) case "secp256k1": if len(publicKeyBytes) != 64 { return nil, fmt.Errorf("Invalid length provided for secp256k1 public key (len %v)", len(publicKeyBytes)) } - publicKey := crypto.PubKeySecp256k1{} - copy(publicKey[:], publicKeyBytes[:64]) + // secp256k1 has type byte 0x02 + typedPublicKeyBytes = make([]byte, 65) + // 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: publicKey, - Amount: amount, + PubKey: newPublicKey, + Amount: unbondAmount, Name: name, UnbondTo: append(unbondTo, BasicAccount{ Address: unbondToAddress, diff --git a/genesis/types.go b/genesis/types.go index 292c48510..5b60154f3 100644 --- a/genesis/types.go +++ b/genesis/types.go @@ -58,12 +58,12 @@ type GenesisValidator struct { // is defined in genesis and not under consensus, where // PrivateValidator (currently inherited from Tendermint) is. type GenesisPrivateValidator struct { - Address []byte `json:"address"` - PubKey crypto.PubKey `json:"pub_key"` - PrivKey crypto.PrivKey `json:"priv_key"` - LastHeight int64 `json:"last_height"` - LastRound int64 `json:"last_round"` - LastStep int64 `json:"last_step"` + 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 { @@ -123,6 +123,13 @@ func (genesisAccount *GenesisAccount) Clone() GenesisAccount { // 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 public key by writing and reading over go-wire serialisation // TODO! write unit test to see whether this is correct publicKeyClone, err := crypto.PubKeyFromBytes(genesisValidator.PubKey.Bytes()) @@ -131,8 +138,8 @@ func (genesisValidator *GenesisValidator) Clone() (GenesisValidator, error) { } // clone the addresses to unbond to unbondToClone := make([]BasicAccount, len(genesisValidator.UnbondTo)) - for _, basicAccount := range genesisValidator.UnbondTo { - unbondToClone = append(unbondToClone, basicAccount.Clone()) + for i, basicAccount := range genesisValidator.UnbondTo { + unbondToClone[i] = basicAccount.Clone() } return GenesisValidator{ PubKey: publicKeyClone, From 441c1a6db5b3d679b94df5bd0335ee32f5d9697e Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 21 Feb 2017 22:11:59 +0100 Subject: [PATCH 8/9] genesis: add const for public key length --- genesis/maker.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/genesis/maker.go b/genesis/maker.go index 184be977b..b9a403726 100644 --- a/genesis/maker.go +++ b/genesis/maker.go @@ -23,6 +23,11 @@ import ( "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 { @@ -41,21 +46,21 @@ func NewGenesisValidator(amount int64, name string, unbondToAddress []byte, switch keyType { case "ed25519": // TODO: [ben] functionality and checks need to be inherit in the type - if len(publicKeyBytes) != 32 { + 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, 33) + typedPublicKeyBytes = make([]byte, PublicKeyEd25519ByteLength+1) // prepend type byte to public key typedPublicKeyBytes = append([]byte{crypto.PubKeyTypeEd25519}, publicKeyBytes...) case "secp256k1": - if len(publicKeyBytes) != 64 { + 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, 65) + typedPublicKeyBytes = make([]byte, PublicKeySecp256k1ByteLength+1) // prepend type byte to public key typedPublicKeyBytes = append([]byte{crypto.PubKeyTypeSecp256k1}, publicKeyBytes...) default: From 578e43441e11f64a66bdf8bd9174adebe0b4e387 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Tue, 21 Feb 2017 23:13:48 +0100 Subject: [PATCH 9/9] genesis: remove redundant copy of public key bytes on clone - thx to Silas --- genesis/types.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/genesis/types.go b/genesis/types.go index 5b60154f3..40395fb79 100644 --- a/genesis/types.go +++ b/genesis/types.go @@ -130,19 +130,13 @@ func (genesisValidator *GenesisValidator) Clone() (GenesisValidator, error) { return GenesisValidator{}, fmt.Errorf("Invalid GenesisValidator %s with nil public key.", genesisValidator.Name) } - // clone the public key by writing and reading over go-wire serialisation - // TODO! write unit test to see whether this is correct - publicKeyClone, err := crypto.PubKeyFromBytes(genesisValidator.PubKey.Bytes()) - if err != nil { - return GenesisValidator{}, err - } // 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: publicKeyClone, + PubKey: genesisValidator.PubKey, Amount: genesisValidator.Amount, Name: genesisValidator.Name, UnbondTo: unbondToClone,