[#74] netmap: Support notary disabled work flow
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
c0073266de
commit
2672e663a0
1 changed files with 161 additions and 14 deletions
|
@ -4,6 +4,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
"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/contract"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/crypto"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/management"
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/management"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
|
"github.com/nspcc-dev/neo-go/pkg/interop/native/std"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
@ -121,10 +122,24 @@ func InnerRingList() []common.IRNode {
|
||||||
|
|
||||||
func UpdateInnerRing(keys []interop.PublicKey) bool {
|
func UpdateInnerRing(keys []interop.PublicKey) bool {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
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("updateInnerRing: this method must be invoked by alphabet nodes")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
panic("updateInnerRing: this method must be invoked by alpahbet nodes")
|
panic("updateInnerRing: this method must be invoked by alphabet nodes")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var irList []common.IRNode
|
var irList []common.IRNode
|
||||||
|
@ -134,6 +149,18 @@ func UpdateInnerRing(keys []interop.PublicKey) bool {
|
||||||
irList = append(irList, common.IRNode{PublicKey: key})
|
irList = append(irList, common.IRNode{PublicKey: key})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
id := keysID(keys, []byte("updateIR"))
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
runtime.Log("updateInnerRing: inner ring list updated")
|
runtime.Log("updateInnerRing: inner ring list updated")
|
||||||
common.SetSerialized(ctx, innerRingKey, irList)
|
common.SetSerialized(ctx, innerRingKey, irList)
|
||||||
|
|
||||||
|
@ -142,9 +169,24 @@ func UpdateInnerRing(keys []interop.PublicKey) bool {
|
||||||
|
|
||||||
func AddPeer(nodeInfo []byte) bool {
|
func AddPeer(nodeInfo []byte) bool {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
var ( // for invocation collection without notary
|
||||||
|
alphabet []common.IRNode
|
||||||
|
nodeKey []byte
|
||||||
|
alphabetCall bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
alphabet = common.AlphabetNodes()
|
||||||
|
nodeKey = common.InnerRingInvoker(alphabet)
|
||||||
|
alphabetCall = len(nodeKey) != 0
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
alphabetCall = runtime.CheckWitness(multiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !alphabetCall {
|
||||||
publicKey := nodeInfo[2:35] // offset:2, len:33
|
publicKey := nodeInfo[2:35] // offset:2, len:33
|
||||||
if !runtime.CheckWitness(publicKey) {
|
if !runtime.CheckWitness(publicKey) {
|
||||||
panic("addPeer: witness check failed")
|
panic("addPeer: witness check failed")
|
||||||
|
@ -159,6 +201,19 @@ func AddPeer(nodeInfo []byte) bool {
|
||||||
|
|
||||||
nm := addToNetmap(ctx, candidate)
|
nm := addToNetmap(ctx, candidate)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
rawCandidate := std.Serialize(candidate)
|
||||||
|
id := crypto.Sha256(rawCandidate)
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
if nm == nil {
|
if nm == nil {
|
||||||
runtime.Log("addPeer: storage node already in the netmap")
|
runtime.Log("addPeer: storage node already in the netmap")
|
||||||
} else {
|
} else {
|
||||||
|
@ -175,9 +230,24 @@ func UpdateState(state int, publicKey interop.PublicKey) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
var ( // for invocation collection without notary
|
||||||
|
alphabet []common.IRNode
|
||||||
|
nodeKey []byte
|
||||||
|
alphabetCall bool
|
||||||
|
)
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
alphabet = common.AlphabetNodes()
|
||||||
|
nodeKey = common.InnerRingInvoker(alphabet)
|
||||||
|
alphabetCall = len(nodeKey) != 0
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
alphabetCall = runtime.CheckWitness(multiaddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !alphabetCall {
|
||||||
if !runtime.CheckWitness(publicKey) {
|
if !runtime.CheckWitness(publicKey) {
|
||||||
panic("updateState: witness check failed")
|
panic("updateState: witness check failed")
|
||||||
}
|
}
|
||||||
|
@ -187,6 +257,18 @@ func UpdateState(state int, publicKey interop.PublicKey) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
id := common.InvokeID([]interface{}{state, publicKey}, []byte("update"))
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
switch nodeState(state) {
|
switch nodeState(state) {
|
||||||
case offlineState:
|
case offlineState:
|
||||||
newNetmap := removeFromNetmap(ctx, publicKey)
|
newNetmap := removeFromNetmap(ctx, publicKey)
|
||||||
|
@ -201,11 +283,37 @@ func UpdateState(state int, publicKey interop.PublicKey) bool {
|
||||||
|
|
||||||
func NewEpoch(epochNum int) bool {
|
func NewEpoch(epochNum int) bool {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
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("newEpoch: this method must be invoked by inner ring nodes")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
panic("newEpoch: this method must be invoked by inner ring nodes")
|
panic("newEpoch: this method must be invoked by inner ring nodes")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
id := common.InvokeID([]interface{}{epochNum}, []byte("epoch"))
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
currentEpoch := storage.Get(ctx, snapshotEpoch).(int)
|
currentEpoch := storage.Get(ctx, snapshotEpoch).(int)
|
||||||
if epochNum <= currentEpoch {
|
if epochNum <= currentEpoch {
|
||||||
|
@ -273,12 +381,37 @@ func Config(key []byte) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetConfig(id, key, val []byte) bool {
|
func SetConfig(id, key, val []byte) bool {
|
||||||
|
ctx := storage.GetContext()
|
||||||
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
|
||||||
|
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("setConfig: invoked by non inner ring node")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
multiaddr := common.AlphabetAddress()
|
multiaddr := common.AlphabetAddress()
|
||||||
if !runtime.CheckWitness(multiaddr) {
|
if !runtime.CheckWitness(multiaddr) {
|
||||||
panic("setConfig: invoked by non inner ring node")
|
panic("setConfig: invoked by non inner ring node")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx := storage.GetContext()
|
if notaryDisabled {
|
||||||
|
threshold := len(alphabet)*2/3 + 1
|
||||||
|
|
||||||
|
n := common.Vote(ctx, id, nodeKey)
|
||||||
|
if n < threshold {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
common.RemoveVotes(ctx, id)
|
||||||
|
}
|
||||||
|
|
||||||
setConfig(ctx, key, val)
|
setConfig(ctx, key, val)
|
||||||
|
|
||||||
|
@ -443,3 +576,17 @@ func getIRNodes(ctx storage.Context) []common.IRNode {
|
||||||
|
|
||||||
return []common.IRNode{}
|
return []common.IRNode{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func keysID(args []interop.PublicKey, prefix []byte) []byte {
|
||||||
|
var (
|
||||||
|
result []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
result = append(result, prefix...)
|
||||||
|
|
||||||
|
for i := range args {
|
||||||
|
result = append(result, args[i]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return crypto.Sha256(result)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue