-
Notifications
You must be signed in to change notification settings - Fork 346
Release 0.16 - alignment with consolidated tooling wrt chain making #501
Changes from all commits
8ccff1f
14ddd4d
3270d0c
aaf27e9
804cadc
1e71bd4
4c1951d
441c1a6
578e434
fa0ed7e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <http://www.gnu.org/licenses/>. | ||
|
||
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 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar to other comment, if it's convenient to pass There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in tooling there is a usage of passing slices of pointers; which is justified there because they are passed around a lot during construction; this is why i deliberately gave tooling an interface that respects the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thought that might be the case. Makes sense. |
||
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 | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <http://www.gnu.org/licenses/>. | ||
|
||
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 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary
DefaultAccountPermissions
is a struct value so it's copied on assignment.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, but is a struct
AccountPermissions
of a structBasePermissions
and a slice ofstrings
; I believe - but not sure - that the structBasePermissions
is treated as a pointer essentially; but definitely theRoles []string
is an effective pointer;secondly, genesis is currently constructed with
Params
as a pointer to aGenesisParams
which is a pointer to anAccountPermissions
; I dont particularly like this construction; but I didnt want to end up with aGenesisDoc
that didnt own its own data;Arguably this does read very defensive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The inner struct is just another value, the memory is copied in a single pass. See: https://play.golang.org/p/Ut_7gZ3TyJ
Yeah the slice does give you mutable access. But this is go, I think we need to choose our battles. I'd rather we were passing immutable sequences of values but we're not. And in the event we are not writing back to the roles, and that would be a weird thing to do.