-
Notifications
You must be signed in to change notification settings - Fork 80
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cluster: refactor base64 fields to base58 #851
Merged
Merged
Changes from 4 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
3707947
cluster: upgrade hash and signature formats
corverroos 58706c1
cleanup
corverroos be3f80c
cleanup
corverroos 0a64514
cleanup
corverroos 7c8d95c
Update cluster/definition.go
corverroos ecf8049
cleanup
corverroos ea973d3
cleanup
corverroos c6a4f35
cleanup
corverroos File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,13 +30,18 @@ import ( | |
) | ||
|
||
const ( | ||
definitionVersion = "v1.1.0" | ||
dkgAlgo = "default" | ||
currentVersion = v1_1 | ||
dkgAlgo = "default" | ||
|
||
v1_2 = "v1.2.0" // WIP | ||
v1_1 = "v1.1.0" | ||
v1_0 = "v1.0.0" | ||
) | ||
|
||
var supportedDefVersions = map[string]bool{ | ||
definitionVersion: true, | ||
"v1.0.0": true, | ||
var supportedVersions = map[string]bool{ | ||
v1_2: true, | ||
v1_1: true, | ||
v1_0: true, | ||
} | ||
|
||
// NodeIdx represents the index of a node/peer/share in the cluster as operator order in cluster definition. | ||
|
@@ -59,7 +64,7 @@ func NewDefinition( | |
random io.Reader, | ||
) Definition { | ||
s := Definition{ | ||
Version: definitionVersion, | ||
Version: currentVersion, | ||
Name: name, | ||
UUID: uuid(random), | ||
Timestamp: time.Now().Format(time.RFC3339), | ||
|
@@ -87,7 +92,7 @@ type Definition struct { | |
Version string | ||
|
||
// Timestamp is the human readable timestamp of this definition. | ||
// Note this was added in v1.0.1, so may be empty for older versions. | ||
// Note this was added in v1.1.0, so may be empty for older versions. | ||
corverroos marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Timestamp string | ||
|
||
// NumValidators is the number of DVs (n*32ETH) to be created in the cluster lock file. | ||
|
@@ -223,8 +228,8 @@ func (d Definition) HashTreeRootWith(hh *ssz.Hasher) error { | |
hh.MerkleizeWithMixin(subIndx, num, num) | ||
} | ||
|
||
// Field (10) 'timestamp' (optional for backwards compatibility) | ||
if d.Timestamp != "" { | ||
// Field (10) 'timestamp' (optional only added from v1.1.0) | ||
if d.Version != v1_0 { | ||
hh.PutBytes([]byte(d.Timestamp)) | ||
} | ||
|
||
|
@@ -233,6 +238,40 @@ func (d Definition) HashTreeRootWith(hh *ssz.Hasher) error { | |
return nil | ||
} | ||
|
||
// Peers returns the operators as a slice of p2p peers. | ||
func (d Definition) Peers() ([]p2p.Peer, error) { | ||
var resp []p2p.Peer | ||
for i, operator := range d.Operators { | ||
record, err := p2p.DecodeENR(operator.ENR) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
p, err := p2p.NewPeer(record, i) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
resp = append(resp, p) | ||
} | ||
|
||
return resp, nil | ||
} | ||
|
||
// PeerIDs is a convenience function that returns the operators p2p peer IDs. | ||
func (d Definition) PeerIDs() ([]peer.ID, error) { | ||
peers, err := d.Peers() | ||
if err != nil { | ||
return nil, err | ||
} | ||
var resp []peer.ID | ||
for _, p := range peers { | ||
resp = append(resp, p.ID) | ||
} | ||
|
||
return resp, nil | ||
} | ||
|
||
func (d Definition) MarshalJSON() ([]byte, error) { | ||
// Marshal config hash | ||
configHash, err := d.ConfigHash() | ||
|
@@ -246,27 +285,51 @@ func (d Definition) MarshalJSON() ([]byte, error) { | |
return nil, errors.Wrap(err, "definition hash") | ||
} | ||
|
||
// Marshal json version of lock | ||
resp, err := json.Marshal(definitionJSON{ | ||
Name: d.Name, | ||
UUID: d.UUID, | ||
Version: d.Version, | ||
Timestamp: d.Timestamp, | ||
NumValidators: d.NumValidators, | ||
Threshold: d.Threshold, | ||
FeeRecipientAddress: d.FeeRecipientAddress, | ||
WithdrawalAddress: d.WithdrawalAddress, | ||
DKGAlgorithm: d.DKGAlgorithm, | ||
ForkVersion: d.ForkVersion, | ||
Operators: d.Operators, | ||
ConfigHash: configHash[:], | ||
DefinitionHash: defHash[:], | ||
}) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "marshal lock") | ||
} | ||
if isJSONv1x1(d.Version) { | ||
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. switch case would be more cleaner + readable imo 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. fair |
||
resp, err := json.Marshal(definitionJSONv1x1{ | ||
Name: d.Name, | ||
UUID: d.UUID, | ||
Version: d.Version, | ||
Timestamp: d.Timestamp, | ||
NumValidators: d.NumValidators, | ||
Threshold: d.Threshold, | ||
FeeRecipientAddress: d.FeeRecipientAddress, | ||
WithdrawalAddress: d.WithdrawalAddress, | ||
DKGAlgorithm: d.DKGAlgorithm, | ||
ForkVersion: d.ForkVersion, | ||
Operators: operatorsToV1x1(d.Operators), | ||
ConfigHash: configHash[:], | ||
DefinitionHash: defHash[:], | ||
}) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "marshal definition") | ||
} | ||
|
||
return resp, nil | ||
return resp, nil | ||
} else if isJSONv1x2(d.Version) { | ||
resp, err := json.Marshal(definitionJSONv1x2{ | ||
Name: d.Name, | ||
UUID: d.UUID, | ||
Version: d.Version, | ||
Timestamp: d.Timestamp, | ||
NumValidators: d.NumValidators, | ||
Threshold: d.Threshold, | ||
FeeRecipientAddress: d.FeeRecipientAddress, | ||
WithdrawalAddress: d.WithdrawalAddress, | ||
DKGAlgorithm: d.DKGAlgorithm, | ||
ForkVersion: d.ForkVersion, | ||
Operators: operatorsToV1x2(d.Operators), | ||
ConfigHash: configHash[:], | ||
DefinitionHash: defHash[:], | ||
}) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "marshal definition") | ||
} | ||
|
||
return resp, nil | ||
} else { | ||
return nil, errors.New("unsupported version") | ||
} | ||
} | ||
|
||
func (d *Definition) UnmarshalJSON(data []byte) error { | ||
|
@@ -276,16 +339,26 @@ func (d *Definition) UnmarshalJSON(data []byte) error { | |
}{} | ||
if err := json.Unmarshal(data, &version); err != nil { | ||
return errors.Wrap(err, "unmarshal version") | ||
} else if !supportedDefVersions[version.Version] { | ||
} else if !supportedVersions[version.Version] { | ||
return errors.New("unsupported definition version", | ||
z.Str("version", version.Version), | ||
z.Any("supported", supportedDefVersions), | ||
z.Any("supported", supportedVersions), | ||
) | ||
} | ||
|
||
var defJSON definitionJSON | ||
if isJSONv1x1(version.Version) { | ||
return d.unmarshalV1x1(data) | ||
} else if isJSONv1x2(version.Version) { | ||
return d.unmarshalV1x2(data) | ||
} else { | ||
return errors.New("unsupported version") | ||
} | ||
} | ||
|
||
func (d *Definition) unmarshalV1x1(data []byte) error { | ||
var defJSON definitionJSONv1x1 | ||
if err := json.Unmarshal(data, &defJSON); err != nil { | ||
return errors.Wrap(err, "unmarshal definition") | ||
return errors.Wrap(err, "unmarshal definition v1_1") | ||
} | ||
|
||
def := Definition{ | ||
|
@@ -299,7 +372,7 @@ func (d *Definition) UnmarshalJSON(data []byte) error { | |
WithdrawalAddress: defJSON.WithdrawalAddress, | ||
DKGAlgorithm: defJSON.DKGAlgorithm, | ||
ForkVersion: defJSON.ForkVersion, | ||
Operators: defJSON.Operators, | ||
Operators: operatorsFromV1x1(defJSON.Operators), | ||
} | ||
|
||
// Verify config_hash | ||
|
@@ -327,53 +400,89 @@ func (d *Definition) UnmarshalJSON(data []byte) error { | |
return nil | ||
} | ||
|
||
// Peers returns the operators as a slice of p2p peers. | ||
func (d Definition) Peers() ([]p2p.Peer, error) { | ||
var resp []p2p.Peer | ||
for i, operator := range d.Operators { | ||
record, err := p2p.DecodeENR(operator.ENR) | ||
if err != nil { | ||
return nil, err | ||
} | ||
func (d *Definition) unmarshalV1x2(data []byte) error { | ||
var defJSON definitionJSONv1x2 | ||
if err := json.Unmarshal(data, &defJSON); err != nil { | ||
return errors.Wrap(err, "unmarshal definition v1v2") | ||
} | ||
|
||
p, err := p2p.NewPeer(record, i) | ||
if err != nil { | ||
return nil, err | ||
} | ||
def := Definition{ | ||
Name: defJSON.Name, | ||
UUID: defJSON.UUID, | ||
Version: defJSON.Version, | ||
Timestamp: defJSON.Timestamp, | ||
NumValidators: defJSON.NumValidators, | ||
Threshold: defJSON.Threshold, | ||
FeeRecipientAddress: defJSON.FeeRecipientAddress, | ||
WithdrawalAddress: defJSON.WithdrawalAddress, | ||
DKGAlgorithm: defJSON.DKGAlgorithm, | ||
ForkVersion: defJSON.ForkVersion, | ||
Operators: operatorsFromV1x2(defJSON.Operators), | ||
} | ||
|
||
resp = append(resp, p) | ||
// Verify config_hash | ||
configHash, err := def.ConfigHash() | ||
if err != nil { | ||
return errors.Wrap(err, "config hash") | ||
} | ||
|
||
return resp, nil | ||
} | ||
if !bytes.Equal(defJSON.ConfigHash, configHash[:]) { | ||
return errors.New("invalid config hash") | ||
} | ||
|
||
// PeerIDs is a convenience function that returns the operators p2p peer IDs. | ||
func (d Definition) PeerIDs() ([]peer.ID, error) { | ||
peers, err := d.Peers() | ||
// Verify definition_hash | ||
defHash, err := def.HashTreeRoot() | ||
if err != nil { | ||
return nil, err | ||
return errors.Wrap(err, "definition hash") | ||
} | ||
var resp []peer.ID | ||
for _, p := range peers { | ||
resp = append(resp, p.ID) | ||
|
||
if !bytes.Equal(defJSON.DefinitionHash, defHash[:]) { | ||
return errors.New("invalid definition hash") | ||
} | ||
|
||
return resp, nil | ||
*d = def | ||
|
||
return nil | ||
} | ||
|
||
// definitionJSONv1x1 is the json formatter of Definition for versions v1.0.0 and v1.1.1. | ||
type definitionJSONv1x1 struct { | ||
Name string `json:"name,omitempty"` | ||
Operators []operatorJSONv1x1 `json:"operators"` | ||
UUID string `json:"uuid"` | ||
Version string `json:"version"` | ||
Timestamp string `json:"timestamp,omitempty"` | ||
NumValidators int `json:"num_validators"` | ||
Threshold int `json:"threshold"` | ||
FeeRecipientAddress string `json:"fee_recipient_address,omitempty"` | ||
WithdrawalAddress string `json:"withdrawal_address,omitempty"` | ||
DKGAlgorithm string `json:"dkg_algorithm"` | ||
ForkVersion string `json:"fork_version"` | ||
ConfigHash []byte `json:"config_hash"` | ||
DefinitionHash []byte `json:"definition_hash"` | ||
} | ||
|
||
// definitionJSONv1x2 is the json formatter of Definition for versions v1.2.0 and later. | ||
type definitionJSONv1x2 struct { | ||
Name string `json:"name,omitempty"` | ||
Operators []operatorJSONv1x2 `json:"operators"` | ||
UUID string `json:"uuid"` | ||
Version string `json:"version"` | ||
Timestamp string `json:"timestamp,omitempty"` | ||
NumValidators int `json:"num_validators"` | ||
Threshold int `json:"threshold"` | ||
FeeRecipientAddress string `json:"fee_recipient_address,omitempty"` | ||
WithdrawalAddress string `json:"withdrawal_address,omitempty"` | ||
DKGAlgorithm string `json:"dkg_algorithm"` | ||
ForkVersion string `json:"fork_version"` | ||
ConfigHash base58 `json:"config_hash"` | ||
DefinitionHash base58 `json:"definition_hash"` | ||
} | ||
|
||
func isJSONv1x1(version string) bool { | ||
return version == v1_0 || version == v1_1 | ||
} | ||
|
||
// definitionJSON is the json formatter of Definition. | ||
type definitionJSON struct { | ||
Name string `json:"name,omitempty"` | ||
Operators []Operator `json:"operators"` | ||
UUID string `json:"uuid"` | ||
Version string `json:"version"` | ||
Timestamp string `json:"timestamp"` | ||
NumValidators int `json:"num_validators"` | ||
Threshold int `json:"threshold"` | ||
FeeRecipientAddress string `json:"fee_recipient_address,omitempty"` | ||
WithdrawalAddress string `json:"withdrawal_address,omitempty"` | ||
DKGAlgorithm string `json:"dkg_algorithm"` | ||
ForkVersion string `json:"fork_version"` | ||
ConfigHash []byte `json:"config_hash"` | ||
DefinitionHash []byte `json:"definition_hash"` | ||
func isJSONv1x2(version string) bool { | ||
return version == v1_2 | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
add enum for these versions, which would work as order of priority of versions at the time of comparison, which can be generated by go generate like we have in tracker as component enum
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.
It will also make it easy to add versions in future with enum approach
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.
yeah, good idea
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.
actually not sure this is going to work, since we need to do string comparison, which doesn't work nice with enums.