From f9f2a030786e19a1a328ba309c2d1d0e11c4ebf6 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 2 Feb 2021 19:39:16 +0300 Subject: [PATCH] [#42] Share ballot structure between contracts Create common package. Define Ballot struct in common package. Use new type in all contracts with ballots. Signed-off-by: Leonard Lyubich --- alphabet/alphabet_contract.go | 37 ++++++++++++++------------------- balance/balance_contract.go | 35 +++++++++++++------------------ common/ballot.go | 12 +++++++++++ container/container_contract.go | 35 +++++++++++++------------------ neofs/neofs_contract.go | 37 ++++++++++++++------------------- neofsid/neofsid_contract.go | 35 +++++++++++++------------------ netmap/netmap_contract.go | 37 ++++++++++++++------------------- 7 files changed, 105 insertions(+), 123 deletions(-) create mode 100644 common/ballot.go diff --git a/alphabet/alphabet_contract.go b/alphabet/alphabet_contract.go index c3bc445..e33cf81 100644 --- a/alphabet/alphabet_contract.go +++ b/alphabet/alphabet_contract.go @@ -8,18 +8,13 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neofs-contract/common" ) type ( irNode struct { key []byte } - - ballot struct { - id []byte // hash of validators list - n [][]byte // already voted inner ring nodes - height int // height is an neofs epoch when ballot was registered - } ) const ( @@ -70,7 +65,7 @@ func Init(addrNetmap []byte, name string, index, total int) { storage.Put(ctx, indexKey, index) storage.Put(ctx, totalKey, total) - setSerialized(ctx, voteKey, []ballot{}) + setSerialized(ctx, voteKey, []common.Ballot{}) runtime.Log(name + " contract initialized") } @@ -213,15 +208,15 @@ func Name() string { func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) found = -1 ) for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if bytesEqual(cnd.id, id) { - voters := cnd.n + if bytesEqual(cnd.ID, id) { + voters := cnd.Voters for j := range voters { if bytesEqual(voters[j], from) { @@ -230,22 +225,22 @@ func vote(ctx storage.Context, epoch int, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, height: epoch} + cnd = common.Ballot{ID: id, Voters: voters, Height: epoch} found = len(voters) } // add only valid ballots with current epochs - if cnd.height == epoch { + if cnd.Height == epoch { newCandidates = append(newCandidates, cnd) } } if found < 0 { voters := [][]byte{from} - newCandidates = append(newCandidates, ballot{ - id: id, - n: voters, - height: epoch}) + newCandidates = append(newCandidates, common.Ballot{ + ID: id, + Voters: voters, + Height: epoch}) found = 1 } @@ -256,13 +251,13 @@ func vote(ctx storage.Context, epoch int, id, from []byte) int { func removeVotes(ctx storage.Context, id []byte) { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) ) for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if !bytesEqual(cnd.id, id) { + if !bytesEqual(cnd.ID, id) { newCandidates = append(newCandidates, cnd) } } @@ -270,13 +265,13 @@ func removeVotes(ctx storage.Context, id []byte) { setSerialized(ctx, voteKey, newCandidates) } -func getBallots(ctx storage.Context) []ballot { +func getBallots(ctx storage.Context) []common.Ballot { data := storage.Get(ctx, voteKey) if data != nil { - return binary.Deserialize(data.([]byte)).([]ballot) + return binary.Deserialize(data.([]byte)).([]common.Ballot) } - return []ballot{} + return []common.Ballot{} } func setSerialized(ctx storage.Context, key interface{}, value interface{}) { diff --git a/balance/balance_contract.go b/balance/balance_contract.go index a5cdad2..9b08fd2 100644 --- a/balance/balance_contract.go +++ b/balance/balance_contract.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neofs-contract/common" ) type ( @@ -17,12 +18,6 @@ type ( key []byte } - ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote - } - // Token holds all token info. Token struct { // Ticker symbol @@ -405,7 +400,7 @@ func innerRingInvoker(ir []irNode) []byte { func vote(ctx storage.Context, id, from []byte) int { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) found = -1 blockHeight = blockchain.GetHeight() @@ -414,12 +409,12 @@ func vote(ctx storage.Context, id, from []byte) int { for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if blockHeight-cnd.block > blockDiff { + if blockHeight-cnd.Height > blockDiff { continue } - if bytesEqual(cnd.id, id) { - voters := cnd.n + if bytesEqual(cnd.ID, id) { + voters := cnd.Voters for j := range voters { if bytesEqual(voters[j], from) { @@ -428,7 +423,7 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = common.Ballot{ID: id, Voters: voters, Height: blockHeight} found = len(voters) } @@ -437,10 +432,10 @@ func vote(ctx storage.Context, id, from []byte) int { if found < 0 { voters := [][]byte{from} - newCandidates = append(newCandidates, ballot{ - id: id, - n: voters, - block: blockHeight}) + newCandidates = append(newCandidates, common.Ballot{ + ID: id, + Voters: voters, + Height: blockHeight}) found = 1 } @@ -451,13 +446,13 @@ func vote(ctx storage.Context, id, from []byte) int { func removeVotes(ctx storage.Context, id []byte) { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) ) for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if !bytesEqual(cnd.id, id) { + if !bytesEqual(cnd.ID, id) { newCandidates = append(newCandidates, cnd) } } @@ -465,13 +460,13 @@ func removeVotes(ctx storage.Context, id []byte) { setSerialized(ctx, voteKey, newCandidates) } -func getBallots(ctx storage.Context) []ballot { +func getBallots(ctx storage.Context) []common.Ballot { data := storage.Get(ctx, voteKey) if data != nil { - return binary.Deserialize(data.([]byte)).([]ballot) + return binary.Deserialize(data.([]byte)).([]common.Ballot) } - return []ballot{} + return []common.Ballot{} } func setSerialized(ctx storage.Context, key interface{}, value interface{}) { diff --git a/common/ballot.go b/common/ballot.go new file mode 100644 index 0000000..0abbfd3 --- /dev/null +++ b/common/ballot.go @@ -0,0 +1,12 @@ +package common + +type Ballot struct { + // ID of the voting decision. + ID []byte + + // Public keys of already voted inner ring nodes. + Voters [][]byte + + // Height of block with the last vote. + Height int +} diff --git a/container/container_contract.go b/container/container_contract.go index b684f6b..ac64894 100644 --- a/container/container_contract.go +++ b/container/container_contract.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neofs-contract/common" ) type ( @@ -21,12 +22,6 @@ type ( info []byte } - ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote - } - extendedACL struct { val []byte sig []byte @@ -494,7 +489,7 @@ func innerRingInvoker(ir []irNode) []byte { func vote(ctx storage.Context, id, from []byte) int { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) found = -1 blockHeight = blockchain.GetHeight() @@ -503,12 +498,12 @@ func vote(ctx storage.Context, id, from []byte) int { for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if blockHeight-cnd.block > blockDiff { + if blockHeight-cnd.Height > blockDiff { continue } - if bytesEqual(cnd.id, id) { - voters := cnd.n + if bytesEqual(cnd.ID, id) { + voters := cnd.Voters for j := range voters { if bytesEqual(voters[j], from) { @@ -517,7 +512,7 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = common.Ballot{ID: id, Voters: voters, Height: blockHeight} found = len(voters) } @@ -526,10 +521,10 @@ func vote(ctx storage.Context, id, from []byte) int { if found < 0 { voters := [][]byte{from} - newCandidates = append(newCandidates, ballot{ - id: id, - n: voters, - block: blockHeight}) + newCandidates = append(newCandidates, common.Ballot{ + ID: id, + Voters: voters, + Height: blockHeight}) found = 1 } @@ -540,13 +535,13 @@ func vote(ctx storage.Context, id, from []byte) int { func removeVotes(ctx storage.Context, id []byte) { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) ) for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if !bytesEqual(cnd.id, id) { + if !bytesEqual(cnd.ID, id) { newCandidates = append(newCandidates, cnd) } } @@ -577,13 +572,13 @@ func getAllContainers(ctx storage.Context) [][]byte { return list } -func getBallots(ctx storage.Context) []ballot { +func getBallots(ctx storage.Context) []common.Ballot { data := storage.Get(ctx, voteKey) if data != nil { - return binary.Deserialize(data.([]byte)).([]ballot) + return binary.Deserialize(data.([]byte)).([]common.Ballot) } - return []ballot{} + return []common.Ballot{} } func getEACL(ctx storage.Context, cid []byte) extendedACL { diff --git a/neofs/neofs_contract.go b/neofs/neofs_contract.go index 223f4ad..cc25a6d 100644 --- a/neofs/neofs_contract.go +++ b/neofs/neofs_contract.go @@ -41,15 +41,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neofs-contract/common" ) type ( - ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote - } - node struct { pub []byte } @@ -127,7 +122,7 @@ func Init(args [][]byte) bool { // initialize all storage slices setSerialized(ctx, innerRingKey, irList) - setSerialized(ctx, voteKey, []ballot{}) + setSerialized(ctx, voteKey, []common.Ballot{}) setSerialized(ctx, candidatesKey, []node{}) setSerialized(ctx, cashedChequesKey, []cheque{}) @@ -548,7 +543,7 @@ func innerRingInvoker(ir []node) []byte { // on unique voters for that decision. func vote(ctx storage.Context, id, from []byte) int { var ( - newCandidates = []ballot{} // it is explicit declaration of empty slice, not nil + newCandidates = []common.Ballot{} // it is explicit declaration of empty slice, not nil candidates = getBallots(ctx) found = -1 blockHeight = blockchain.GetHeight() @@ -557,12 +552,12 @@ func vote(ctx storage.Context, id, from []byte) int { for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if blockHeight-cnd.block > blockDiff { + if blockHeight-cnd.Height > blockDiff { continue } - if bytesEqual(cnd.id, id) { - voters := cnd.n + if bytesEqual(cnd.ID, id) { + voters := cnd.Voters for j := range voters { if bytesEqual(voters[j], from) { @@ -571,7 +566,7 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = common.Ballot{ID: id, Voters: voters, Height: blockHeight} found = len(voters) } @@ -582,10 +577,10 @@ func vote(ctx storage.Context, id, from []byte) int { found = 1 voters := [][]byte{from} - newCandidates = append(newCandidates, ballot{ - id: id, - n: voters, - block: blockHeight}) + newCandidates = append(newCandidates, common.Ballot{ + ID: id, + Voters: voters, + Height: blockHeight}) } setSerialized(ctx, voteKey, newCandidates) @@ -597,13 +592,13 @@ func vote(ctx storage.Context, id, from []byte) int { // inner ring nodes. func removeVotes(ctx storage.Context, id []byte) { var ( - newCandidates = []ballot{} // it is explicit declaration of empty slice, not nil + newCandidates = []common.Ballot{} // it is explicit declaration of empty slice, not nil candidates = getBallots(ctx) ) for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if !bytesEqual(cnd.id, id) { + if !bytesEqual(cnd.ID, id) { newCandidates = append(newCandidates, cnd) } } @@ -638,13 +633,13 @@ func getCashedCheques(ctx storage.Context) []cheque { } // getInnerRingNodes returns deserialized slice of vote ballots. -func getBallots(ctx storage.Context) []ballot { +func getBallots(ctx storage.Context) []common.Ballot { data := storage.Get(ctx, voteKey) if data != nil { - return binary.Deserialize(data.([]byte)).([]ballot) + return binary.Deserialize(data.([]byte)).([]common.Ballot) } - return []ballot{} + return []common.Ballot{} } // getConfig returns installed neofs configuration value or nil if it is not set. diff --git a/neofsid/neofsid_contract.go b/neofsid/neofsid_contract.go index ce44de6..a60a545 100644 --- a/neofsid/neofsid_contract.go +++ b/neofsid/neofsid_contract.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neofs-contract/common" ) type ( @@ -15,12 +16,6 @@ type ( key []byte } - ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote - } - UserInfo struct { Keys [][]byte } @@ -196,13 +191,13 @@ func getUserInfo(ctx storage.Context, key interface{}) UserInfo { return UserInfo{Keys: [][]byte{}} } -func getBallots(ctx storage.Context) []ballot { +func getBallots(ctx storage.Context) []common.Ballot { data := storage.Get(ctx, voteKey) if data != nil { - return binary.Deserialize(data.([]byte)).([]ballot) + return binary.Deserialize(data.([]byte)).([]common.Ballot) } - return []ballot{} + return []common.Ballot{} } func setSerialized(ctx storage.Context, key interface{}, value interface{}) { @@ -223,7 +218,7 @@ func innerRingInvoker(ir []irNode) []byte { func vote(ctx storage.Context, id, from []byte) int { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) found = -1 blockHeight = blockchain.GetHeight() @@ -232,12 +227,12 @@ func vote(ctx storage.Context, id, from []byte) int { for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if blockHeight-cnd.block > blockDiff { + if blockHeight-cnd.Height > blockDiff { continue } - if bytesEqual(cnd.id, id) { - voters := cnd.n + if bytesEqual(cnd.ID, id) { + voters := cnd.Voters for j := range voters { if bytesEqual(voters[j], from) { @@ -246,7 +241,7 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = common.Ballot{ID: id, Voters: voters, Height: blockHeight} found = len(voters) } @@ -255,10 +250,10 @@ func vote(ctx storage.Context, id, from []byte) int { if found < 0 { voters := [][]byte{from} - newCandidates = append(newCandidates, ballot{ - id: id, - n: voters, - block: blockHeight}) + newCandidates = append(newCandidates, common.Ballot{ + ID: id, + Voters: voters, + Height: blockHeight}) found = 1 } @@ -269,13 +264,13 @@ func vote(ctx storage.Context, id, from []byte) int { func removeVotes(ctx storage.Context, id []byte) { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) ) for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if !bytesEqual(cnd.id, id) { + if !bytesEqual(cnd.ID, id) { newCandidates = append(newCandidates, cnd) } } diff --git a/netmap/netmap_contract.go b/netmap/netmap_contract.go index 5cc9b21..5c31794 100644 --- a/netmap/netmap_contract.go +++ b/netmap/netmap_contract.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/runtime" "github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/util" + "github.com/nspcc-dev/neofs-contract/common" ) type ( @@ -19,12 +20,6 @@ type ( info []byte } - ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote - } - netmapNode struct { node storageNode state nodeState @@ -95,7 +90,7 @@ func Init(keys [][]byte) { setSerialized(ctx, netmapKey, []netmapNode{}) setSerialized(ctx, snapshot0Key, []netmapNode{}) setSerialized(ctx, snapshot1Key, []netmapNode{}) - setSerialized(ctx, voteKey, []ballot{}) + setSerialized(ctx, voteKey, []common.Ballot{}) runtime.Log("netmap contract initialized") } @@ -423,7 +418,7 @@ func filterNetmap(ctx storage.Context, st nodeState) []storageNode { func vote(ctx storage.Context, id, from []byte) int { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) found = -1 blockHeight = blockchain.GetHeight() @@ -432,12 +427,12 @@ func vote(ctx storage.Context, id, from []byte) int { for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if blockHeight-cnd.block > blockDiff { + if blockHeight-cnd.Height > blockDiff { continue } - if bytesEqual(cnd.id, id) { - voters := cnd.n + if bytesEqual(cnd.ID, id) { + voters := cnd.Voters for j := range voters { if bytesEqual(voters[j], from) { @@ -446,7 +441,7 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = common.Ballot{ID: id, Voters: voters, Height: blockHeight} found = len(voters) } @@ -455,10 +450,10 @@ func vote(ctx storage.Context, id, from []byte) int { if found < 0 { voters := [][]byte{from} - newCandidates = append(newCandidates, ballot{ - id: id, - n: voters, - block: blockHeight}) + newCandidates = append(newCandidates, common.Ballot{ + ID: id, + Voters: voters, + Height: blockHeight}) found = 1 } @@ -469,13 +464,13 @@ func vote(ctx storage.Context, id, from []byte) int { func removeVotes(ctx storage.Context, id []byte) { var ( - newCandidates []ballot + newCandidates []common.Ballot candidates = getBallots(ctx) ) for i := 0; i < len(candidates); i++ { cnd := candidates[i] - if !bytesEqual(cnd.id, id) { + if !bytesEqual(cnd.ID, id) { newCandidates = append(newCandidates, cnd) } } @@ -510,13 +505,13 @@ func getSnapshot(ctx storage.Context, key string) []storageNode { return []storageNode{} } -func getBallots(ctx storage.Context) []ballot { +func getBallots(ctx storage.Context) []common.Ballot { data := storage.Get(ctx, voteKey) if data != nil { - return binary.Deserialize(data.([]byte)).([]ballot) + return binary.Deserialize(data.([]byte)).([]common.Ballot) } - return []ballot{} + return []common.Ballot{} } func setSerialized(ctx storage.Context, key interface{}, value interface{}) {