From 5e224267680143576a5b659ca856a705356c8e37 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Thu, 29 Apr 2021 16:06:34 +0300 Subject: [PATCH] [#74] alphabet: Support notary disabled work flow Signed-off-by: Alex Vanin --- alphabet/alphabet_contract.go | 61 ++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/alphabet/alphabet_contract.go b/alphabet/alphabet_contract.go index 4724409..d796fdd 100644 --- a/alphabet/alphabet_contract.go +++ b/alphabet/alphabet_contract.go @@ -3,6 +3,7 @@ package alphabetcontract import ( "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/interop/contract" + "github.com/nspcc-dev/neo-go/pkg/interop/native/crypto" "github.com/nspcc-dev/neo-go/pkg/interop/native/gas" "github.com/nspcc-dev/neo-go/pkg/interop/native/management" "github.com/nspcc-dev/neo-go/pkg/interop/native/neo" @@ -112,6 +113,7 @@ func checkPermission(ir []common.IRNode) bool { func Emit() bool { ctx := storage.GetReadOnlyContext() + notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool) alphabet := common.AlphabetNodes() if !checkPermission(alphabet) { @@ -134,7 +136,15 @@ func Emit() bool { gas.Transfer(contractHash, proxyAddr, proxyGas, nil) runtime.Log("utility token has been emitted to proxy contract") - innerRing := common.InnerRingNodes() + var innerRing []common.IRNode + + if notaryDisabled { + netmapContract := storage.Get(ctx, netmapKey).(interop.Hash160) + innerRing = common.InnerRingNodesFromNetmap(netmapContract) + } else { + innerRing = common.InnerRingNodes() + } + gasPerNode := gasBalance / 2 * 7 / 8 / len(innerRing) if gasPerNode != 0 { @@ -150,13 +160,27 @@ func Emit() bool { } func Vote(epoch int, candidates []interop.PublicKey) { - ctx := storage.GetReadOnlyContext() + ctx := storage.GetContext() + notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool) index := index(ctx) name := name(ctx) - multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("invalid invoker") + var ( // for invocation collection without notary + alphabet []common.IRNode + nodeKey []byte + ) + + if notaryDisabled { + alphabet = common.AlphabetNodes() + nodeKey = common.InnerRingInvoker(alphabet) + if len(nodeKey) == 0 { + panic("invalid invoker") + } + } else { + multiaddr := common.AlphabetAddress() + if !runtime.CheckWitness(multiaddr) { + panic("invalid invoker") + } } curEpoch := currentEpoch(ctx) @@ -167,6 +191,18 @@ func Vote(epoch int, candidates []interop.PublicKey) { candidate := candidates[index%len(candidates)] address := runtime.GetExecutingScriptHash() + if notaryDisabled { + threshold := len(alphabet)*2/3 + 1 + id := voteID(epoch, candidates) + + n := common.Vote(ctx, id, nodeKey) + if n < threshold { + return + } + + common.RemoveVotes(ctx, id) + } + ok := neo.Vote(address, candidate) if ok { runtime.Log(name + ": successfully voted for validator") @@ -177,6 +213,21 @@ func Vote(epoch int, candidates []interop.PublicKey) { return } +func voteID(epoch interface{}, args []interop.PublicKey) []byte { + var ( + result []byte + epochBytes = epoch.([]byte) + ) + + result = append(result, epochBytes...) + + for i := range args { + result = append(result, args[i]...) + } + + return crypto.Sha256(result) +} + func Name() string { ctx := storage.GetReadOnlyContext() return name(ctx)