From a8d55d9166666c3ca0d53b39516ce9ca334ce94e Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Mon, 7 Dec 2020 15:53:11 +0300 Subject: [PATCH] [#19] alphabet: Check epoch value in Vote method Signed-off-by: Alex Vanin --- alphabet/alphabet.tpl | 36 ++++++++++++++----------- alphabet/az/az_contract.go | 40 ++++++++++++++++------------ alphabet/buky/buky_contract.go | 40 ++++++++++++++++------------ alphabet/dobro/dobro_contract.go | 40 ++++++++++++++++------------ alphabet/glagoli/glagoli_contract.go | 40 ++++++++++++++++------------ alphabet/jest/jest_contract.go | 40 ++++++++++++++++------------ alphabet/vedi/vedi_contract.go | 40 ++++++++++++++++------------ alphabet/zhivete/zhivete_contract.go | 40 ++++++++++++++++------------ 8 files changed, 182 insertions(+), 134 deletions(-) diff --git a/alphabet/alphabet.tpl b/alphabet/alphabet.tpl index 963b04d..0753850 100644 --- a/alphabet/alphabet.tpl +++ b/alphabet/alphabet.tpl @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,8 +34,6 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } diff --git a/alphabet/az/az_contract.go b/alphabet/az/az_contract.go index 32d9d22..5fabb17 100644 --- a/alphabet/az/az_contract.go +++ b/alphabet/az/az_contract.go @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,9 +34,7 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - - threshold = totalAlphabetContracts*2/3 + 1 + threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" totalAlphabetContracts = 7 @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } @@ -259,7 +265,7 @@ func bytesEqual(a []byte, b []byte) bool { func voteID(epoch interface{}, args [][]byte) []byte { var ( - result []byte + result []byte epochBytes = epoch.([]byte) ) diff --git a/alphabet/buky/buky_contract.go b/alphabet/buky/buky_contract.go index 0bd270d..5fb1974 100644 --- a/alphabet/buky/buky_contract.go +++ b/alphabet/buky/buky_contract.go @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,9 +34,7 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - - threshold = totalAlphabetContracts*2/3 + 1 + threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" totalAlphabetContracts = 7 @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } @@ -259,7 +265,7 @@ func bytesEqual(a []byte, b []byte) bool { func voteID(epoch interface{}, args [][]byte) []byte { var ( - result []byte + result []byte epochBytes = epoch.([]byte) ) diff --git a/alphabet/dobro/dobro_contract.go b/alphabet/dobro/dobro_contract.go index aaa72df..91bd198 100644 --- a/alphabet/dobro/dobro_contract.go +++ b/alphabet/dobro/dobro_contract.go @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,9 +34,7 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - - threshold = totalAlphabetContracts*2/3 + 1 + threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" totalAlphabetContracts = 7 @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } @@ -259,7 +265,7 @@ func bytesEqual(a []byte, b []byte) bool { func voteID(epoch interface{}, args [][]byte) []byte { var ( - result []byte + result []byte epochBytes = epoch.([]byte) ) diff --git a/alphabet/glagoli/glagoli_contract.go b/alphabet/glagoli/glagoli_contract.go index 377f70a..0ec7c33 100644 --- a/alphabet/glagoli/glagoli_contract.go +++ b/alphabet/glagoli/glagoli_contract.go @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,9 +34,7 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - - threshold = totalAlphabetContracts*2/3 + 1 + threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" totalAlphabetContracts = 7 @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } @@ -259,7 +265,7 @@ func bytesEqual(a []byte, b []byte) bool { func voteID(epoch interface{}, args [][]byte) []byte { var ( - result []byte + result []byte epochBytes = epoch.([]byte) ) diff --git a/alphabet/jest/jest_contract.go b/alphabet/jest/jest_contract.go index 2415477..3e9b8fa 100644 --- a/alphabet/jest/jest_contract.go +++ b/alphabet/jest/jest_contract.go @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,9 +34,7 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - - threshold = totalAlphabetContracts*2/3 + 1 + threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" totalAlphabetContracts = 7 @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } @@ -259,7 +265,7 @@ func bytesEqual(a []byte, b []byte) bool { func voteID(epoch interface{}, args [][]byte) []byte { var ( - result []byte + result []byte epochBytes = epoch.([]byte) ) diff --git a/alphabet/vedi/vedi_contract.go b/alphabet/vedi/vedi_contract.go index 565e820..9ad5311 100644 --- a/alphabet/vedi/vedi_contract.go +++ b/alphabet/vedi/vedi_contract.go @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,9 +34,7 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - - threshold = totalAlphabetContracts*2/3 + 1 + threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" totalAlphabetContracts = 7 @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } @@ -259,7 +265,7 @@ func bytesEqual(a []byte, b []byte) bool { func voteID(epoch interface{}, args [][]byte) []byte { var ( - result []byte + result []byte epochBytes = epoch.([]byte) ) diff --git a/alphabet/zhivete/zhivete_contract.go b/alphabet/zhivete/zhivete_contract.go index 4480b52..d7d9dd6 100644 --- a/alphabet/zhivete/zhivete_contract.go +++ b/alphabet/zhivete/zhivete_contract.go @@ -2,7 +2,6 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop/binary" - "github.com/nspcc-dev/neo-go/pkg/interop/blockchain" "github.com/nspcc-dev/neo-go/pkg/interop/contract" "github.com/nspcc-dev/neo-go/pkg/interop/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/engine" @@ -17,9 +16,9 @@ type ( } ballot struct { - id []byte // id of the voting decision - n [][]byte // already voted inner ring nodes - block int // block with the last vote + id []byte // hash of validators list + n [][]byte // already voted inner ring nodes + height int // height is an neofs epoch when ballot was registered } ) @@ -35,9 +34,7 @@ const ( netmapContractKey = "netmapScriptHash" - blockDiff = 20 // amount of blocks when ballot get discarded - - threshold = totalAlphabetContracts*2/3 + 1 + threshold = totalAlphabetContracts * 2 / 3 + 1 voteKey = "ballots" totalAlphabetContracts = 7 @@ -91,6 +88,11 @@ func irList() []irNode { return engine.AppCall(netmapContractAddr, "innerRingList").([]irNode) } +func currentEpoch() int { + netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) + return engine.AppCall(netmapContractAddr, "epoch").(int) +} + func checkPermission(ir []irNode) bool { if len(ir) <= index { return false @@ -153,8 +155,13 @@ func Vote(epoch int, candidates [][]byte) { panic("invalid invoker") } + curEpoch := currentEpoch() + if epoch != curEpoch { + panic("invalid epoch") + } + id := voteID(epoch, candidates) - n := vote(ctx, id, key) + n := vote(ctx, curEpoch, id, key) if n >= threshold { candidate := candidates[index%len(candidates)] @@ -178,12 +185,11 @@ func Name() string { return name } -func vote(ctx storage.Context, id, from []byte) int { +func vote(ctx storage.Context, epoch int, id, from []byte) int { var ( newCandidates []ballot candidates = getBallots(ctx) found = -1 - blockHeight = blockchain.GetHeight() ) for i := 0; i < len(candidates); i++ { @@ -198,12 +204,12 @@ func vote(ctx storage.Context, id, from []byte) int { } voters = append(voters, from) - cnd = ballot{id: id, n: voters, block: blockHeight} + cnd = ballot{id: id, n: voters, height: epoch} found = len(voters) } - // do not add old ballots, they are invalid - if blockHeight-cnd.block <= blockDiff { + // add only valid ballots with current epochs + if cnd.height == epoch { newCandidates = append(newCandidates, cnd) } } @@ -211,9 +217,9 @@ 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}) + id: id, + n: voters, + height: epoch}) found = 1 } @@ -259,7 +265,7 @@ func bytesEqual(a []byte, b []byte) bool { func voteID(epoch interface{}, args [][]byte) []byte { var ( - result []byte + result []byte epochBytes = epoch.([]byte) )