diff --git a/alphabet/alphabet_contract.go b/alphabet/alphabet_contract.go index e31ff2a..15b7e7c 100644 --- a/alphabet/alphabet_contract.go +++ b/alphabet/alphabet_contract.go @@ -10,12 +10,6 @@ import ( "github.com/nspcc-dev/neofs-contract/common" ) -type ( - irNode struct { - key []byte - } -) - const ( // native gas token script hash gasHash = "\xfb\xed\xfe\x2e\xd2\x22\x65\x92\xb6\x48\xc4\xda\x97\xb9\xc9\xcd\x5d\xc1\xa6\xa6" @@ -84,9 +78,9 @@ func balance(hash string, addr []byte) int { return balance.(int) } -func irList() []irNode { +func irList() []common.IRNode { netmapContractAddr := storage.Get(ctx, netmapKey).([]byte) - return contract.Call(netmapContractAddr, "innerRingList").([]irNode) + return contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) } func currentEpoch() int { @@ -106,7 +100,7 @@ func total() int { return storage.Get(ctx, totalKey).(int) } -func checkPermission(ir []irNode) bool { +func checkPermission(ir []common.IRNode) bool { index := index() // read from contract memory if len(ir) <= index { @@ -114,24 +108,7 @@ func checkPermission(ir []irNode) bool { } node := ir[index] - return runtime.CheckWitness(node.key) -} - -func innerRingInvoker(ir []irNode) []byte { - amountOfContracts := total() // read from contract memory - - for i := 0; i < len(ir); i++ { - if i >= amountOfContracts { - return nil - } - - node := ir[i] - if runtime.CheckWitness(node.key) { - return node.key - } - } - - return nil + return runtime.CheckWitness(node.PublicKey) } func Emit() bool { @@ -155,7 +132,7 @@ func Emit() bool { for i := range innerRingKeys { node := innerRingKeys[i] - address := contract.CreateStandardAccount(node.key) + address := contract.CreateStandardAccount(node.PublicKey) _ = contract.Call([]byte(gasHash), "transfer", contractHash, address, gasPerNode, nil) } @@ -170,7 +147,7 @@ func Vote(epoch int, candidates [][]byte) { index := index() name := name() - key := innerRingInvoker(innerRingKeys) + key := common.InnerRingInvoker(innerRingKeys) if len(key) == 0 { panic("invalid invoker") } diff --git a/balance/balance_contract.go b/balance/balance_contract.go index ac7b1ce..c4c515f 100644 --- a/balance/balance_contract.go +++ b/balance/balance_contract.go @@ -11,10 +11,6 @@ import ( ) type ( - irNode struct { - key []byte - } - // Token holds all token info. Token struct { // Ticker symbol @@ -114,10 +110,10 @@ func TransferX(from, to interop.Hash160, amount int, details []byte) bool { ) netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("transferX: this method must be invoked from inner ring") } @@ -150,10 +146,10 @@ func TransferX(from, to interop.Hash160, amount int, details []byte) bool { func Lock(txID []byte, from, to interop.Hash160, amount, until int) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("lock: this method must be invoked from inner ring") } @@ -188,10 +184,10 @@ func Lock(txID []byte, from, to interop.Hash160, amount, until int) bool { func NewEpoch(epochNum int) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("epochNum: this method must be invoked from inner ring") } @@ -227,10 +223,10 @@ func NewEpoch(epochNum int) bool { func Mint(to interop.Hash160, amount int, details []byte) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("burn: this method must be invoked from inner ring") } @@ -258,10 +254,10 @@ func Mint(to interop.Hash160, amount int, details []byte) bool { func Burn(from interop.Hash160, amount int, details []byte) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("burn: this method must be invoked from inner ring") } @@ -381,17 +377,6 @@ func isUsableAddress(addr interop.Hash160) bool { return false } -func innerRingInvoker(ir []irNode) []byte { - for i := 0; i < len(ir); i++ { - node := ir[i] - if runtime.CheckWitness(node.key) { - return node.key - } - } - - return nil -} - func getAccount(ctx storage.Context, key interface{}) Account { data := storage.Get(ctx, key) if data != nil { diff --git a/common/invoke.go b/common/invoke.go index 6dfe0fd..7369193 100644 --- a/common/invoke.go +++ b/common/invoke.go @@ -1,6 +1,9 @@ package common -import "github.com/nspcc-dev/neo-go/pkg/interop/crypto" +import ( + "github.com/nspcc-dev/neo-go/pkg/interop/crypto" + "github.com/nspcc-dev/neo-go/pkg/interop/runtime" +) func InvokeID(args []interface{}, prefix []byte) []byte { for i := range args { @@ -10,3 +13,19 @@ func InvokeID(args []interface{}, prefix []byte) []byte { return crypto.SHA256(prefix) } + +type IRNode struct { + PublicKey []byte +} + +// InnerRingInvoker returns public key of inner ring node that invoked contract. +func InnerRingInvoker(ir []IRNode) []byte { + for i := 0; i < len(ir); i++ { + node := ir[i] + if runtime.CheckWitness(node.PublicKey) { + return node.PublicKey + } + } + + return nil +} diff --git a/container/container_contract.go b/container/container_contract.go index 186bc63..58abaa5 100644 --- a/container/container_contract.go +++ b/container/container_contract.go @@ -12,10 +12,6 @@ import ( ) type ( - irNode struct { - key []byte - } - storageNode struct { info []byte } @@ -87,7 +83,7 @@ func Init(addrNetmap, addrBalance, addrID []byte) { func Put(container, signature, publicKey []byte) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 offset := int(container[1]) @@ -98,7 +94,7 @@ func Put(container, signature, publicKey []byte) bool { // If invoked from storage node, ignore it. // Inner ring will find tx, validate it and send it again. - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { // check provided key if !isSignedByOwnerKey(container, signature, ownerID, publicKey) { @@ -126,7 +122,7 @@ func Put(container, signature, publicKey []byte) bool { for i := 0; i < len(innerRing); i++ { node := innerRing[i] - to := contract.CreateStandardAccount(node.key) + to := contract.CreateStandardAccount(node.PublicKey) tx := contract.Call(balanceContractAddr, "transferX", from, @@ -154,7 +150,7 @@ func Put(container, signature, publicKey []byte) bool { func Delete(containerID, signature []byte) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 ownerID := getOwnerByID(ctx, containerID) @@ -164,7 +160,7 @@ func Delete(containerID, signature []byte) bool { // If invoked from storage node, ignore it. // Inner ring will find tx, validate it and send it again. - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { // check provided key neofsIDContractAddr := storage.Get(ctx, neofsIDContractKey).([]byte) @@ -341,10 +337,10 @@ func ListContainerSizes(epoch int) [][]byte { func ProcessEpoch(epochNum int) { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("processEpoch: this method must be invoked from inner ring") } @@ -365,10 +361,10 @@ func ProcessEpoch(epochNum int) { func StartContainerEstimation(epoch int) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("startEstimation: only inner ring nodes can invoke this") } @@ -389,10 +385,10 @@ func StartContainerEstimation(epoch int) bool { func StopContainerEstimation(epoch int) bool { netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("stopEstimation: only inner ring nodes can invoke this") } @@ -472,17 +468,6 @@ func remove(ctx storage.Context, key interface{}, value []byte) int { return ln } -func innerRingInvoker(ir []irNode) []byte { - for i := 0; i < len(ir); i++ { - node := ir[i] - if runtime.CheckWitness(node.key) { - return node.key - } - } - - return nil -} - func getList(ctx storage.Context, key interface{}) [][]byte { data := storage.Get(ctx, key) if data != nil { diff --git a/neofs/neofs_contract.go b/neofs/neofs_contract.go index e2178a7..3eb9569 100644 --- a/neofs/neofs_contract.go +++ b/neofs/neofs_contract.go @@ -43,10 +43,6 @@ import ( ) type ( - node struct { - pub []byte - } - cheque struct { id []byte } @@ -102,7 +98,7 @@ func Init(args [][]byte) bool { panic("neofs: contract already deployed") } - var irList []node + var irList []common.IRNode if len(args) < 3 { panic("neofs: at least three inner ring keys must be provided") @@ -113,13 +109,13 @@ func Init(args [][]byte) bool { if len(pub) != publicKeySize { panic("neofs: incorrect public key length") } - irList = append(irList, node{pub: pub}) + irList = append(irList, common.IRNode{PublicKey: pub}) } // initialize all storage slices common.SetSerialized(ctx, innerRingKey, irList) common.InitVote(ctx) - common.SetSerialized(ctx, candidatesKey, []node{}) + common.SetSerialized(ctx, candidatesKey, []common.IRNode{}) common.SetSerialized(ctx, cashedChequesKey, []cheque{}) runtime.Log("neofs: contract initialized") @@ -128,12 +124,12 @@ func Init(args [][]byte) bool { } // InnerRingList returns array of inner ring node keys. -func InnerRingList() []node { +func InnerRingList() []common.IRNode { return getInnerRingNodes(ctx, innerRingKey) } // InnerRingCandidates returns array of inner ring candidate node keys. -func InnerRingCandidates() []node { +func InnerRingCandidates() []common.IRNode { return getInnerRingNodes(ctx, candidatesKey) } @@ -143,12 +139,12 @@ func InnerRingCandidateRemove(key []byte) bool { panic("irCandidateRemove: you should be the owner of the public key") } - nodes := []node{} // it is explicit declaration of empty slice, not nil + nodes := []common.IRNode{} // it is explicit declaration of empty slice, not nil candidates := getInnerRingNodes(ctx, candidatesKey) for i := range candidates { c := candidates[i] - if !common.BytesEqual(c.pub, key) { + if !common.BytesEqual(c.PublicKey, key) { nodes = append(nodes, c) } else { runtime.Log("irCandidateRemove: candidate has been removed") @@ -166,7 +162,7 @@ func InnerRingCandidateAdd(key []byte) bool { panic("irCandidateAdd: you should be the owner of the public key") } - c := node{pub: key} + c := common.IRNode{PublicKey: key} candidates := getInnerRingNodes(ctx, candidatesKey) list, ok := addNode(candidates, c) @@ -274,7 +270,7 @@ func Cheque(id, user []byte, amount int, lockAcc []byte) bool { cashedCheques := getCashedCheques(ctx) hashID := crypto.SHA256(id) - irKey := innerRingInvoker(irList) + irKey := common.InnerRingInvoker(irList) if len(irKey) == 0 { panic("cheque: invoked by non inner ring node") } @@ -353,7 +349,7 @@ func InnerRingUpdate(chequeID []byte, args [][]byte) bool { irList := getInnerRingNodes(ctx, innerRingKey) threshold := len(irList)/3*2 + 1 - irKey := innerRingInvoker(irList) + irKey := common.InnerRingInvoker(irList) if len(irKey) == 0 { panic("innerRingUpdate: invoked by non inner ring node") } @@ -369,7 +365,7 @@ func InnerRingUpdate(chequeID []byte, args [][]byte) bool { oldNodes := 0 candidates := getInnerRingNodes(ctx, candidatesKey) - newIR := []node{} + newIR := []common.IRNode{} loop: for i := 0; i < len(args); i++ { @@ -381,7 +377,7 @@ loop: // find key in actual inner ring list for j := 0; j < len(irList); j++ { n := irList[j] - if common.BytesEqual(n.pub, key) { + if common.BytesEqual(n.PublicKey, key) { newIR = append(newIR, n) oldNodes++ @@ -427,7 +423,7 @@ func IsInnerRing(key []byte) bool { for i := range irList { node := irList[i] - if common.BytesEqual(node.pub, key) { + if common.BytesEqual(node.PublicKey, key) { return true } } @@ -446,7 +442,7 @@ func SetConfig(id, key, val []byte) bool { irList := getInnerRingNodes(ctx, innerRingKey) threshold := len(irList)/3*2 + 1 - irKey := innerRingInvoker(irList) + irKey := common.InnerRingInvoker(irList) if len(irKey) == 0 { panic("setConfig: invoked by non inner ring node") } @@ -523,26 +519,14 @@ func Version() int { return version } -// innerRingInvoker returns public key of inner ring node that invoked contract. -func innerRingInvoker(ir []node) []byte { - for i := 0; i < len(ir); i++ { - node := ir[i] - if runtime.CheckWitness(node.pub) { - return node.pub - } - } - - return nil -} - // getInnerRingNodes returns deserialized slice of inner ring nodes from storage. -func getInnerRingNodes(ctx storage.Context, key string) []node { +func getInnerRingNodes(ctx storage.Context, key string) []common.IRNode { data := storage.Get(ctx, key) if data != nil { - return binary.Deserialize(data.([]byte)).([]node) + return binary.Deserialize(data.([]byte)).([]common.IRNode) } - return []node{} + return []common.IRNode{} } // getInnerRingNodes returns deserialized slice of used cheques. @@ -587,9 +571,9 @@ func addCheque(lst []cheque, c cheque) ([]cheque, bool) { // addNode returns slice of nodes with appended node 'n' and bool flag // that set to false if node 'n' is already presented in the slice 'lst'. -func addNode(lst []node, n node) ([]node, bool) { +func addNode(lst []common.IRNode, n common.IRNode) ([]common.IRNode, bool) { for i := 0; i < len(lst); i++ { - if common.BytesEqual(n.pub, lst[i].pub) { + if common.BytesEqual(n.PublicKey, lst[i].PublicKey) { return nil, false } } @@ -602,14 +586,14 @@ func addNode(lst []node, n node) ([]node, bool) { // rmNodeByKey returns slice of nodes without node with key 'k', // slices of nodes 'add' with node with key 'k' and bool flag, // that set to false if node with a key 'k' does not exists in the slice 'lst'. -func rmNodeByKey(lst, add []node, k []byte) ([]node, []node, bool) { +func rmNodeByKey(lst, add []common.IRNode, k []byte) ([]common.IRNode, []common.IRNode, bool) { var ( flag bool - newLst = []node{} // it is explicit declaration of empty slice, not nil + newLst = []common.IRNode{} // it is explicit declaration of empty slice, not nil ) for i := 0; i < len(lst); i++ { - if common.BytesEqual(k, lst[i].pub) { + if common.BytesEqual(k, lst[i].PublicKey) { add = append(add, lst[i]) flag = true } else { diff --git a/neofsid/neofsid_contract.go b/neofsid/neofsid_contract.go index c12e84f..6088c85 100644 --- a/neofsid/neofsid_contract.go +++ b/neofsid/neofsid_contract.go @@ -10,10 +10,6 @@ import ( ) type ( - irNode struct { - key []byte - } - UserInfo struct { Keys [][]byte } @@ -64,10 +60,10 @@ func AddKey(owner []byte, keys [][]byte) bool { } netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("addKey: invocation from non inner ring node") } @@ -118,10 +114,10 @@ func RemoveKey(owner []byte, keys [][]byte) bool { } netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte) - innerRing := contract.Call(netmapContractAddr, "innerRingList").([]irNode) + innerRing := contract.Call(netmapContractAddr, "innerRingList").([]common.IRNode) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("removeKey: invocation from non inner ring node") } @@ -186,17 +182,6 @@ func getUserInfo(ctx storage.Context, key interface{}) UserInfo { return UserInfo{Keys: [][]byte{}} } -func innerRingInvoker(ir []irNode) []byte { - for i := 0; i < len(ir); i++ { - node := ir[i] - if runtime.CheckWitness(node.key) { - return node.key - } - } - - return nil -} - func invokeIDKeys(owner []byte, keys [][]byte, prefix []byte) []byte { prefix = append(prefix, owner...) for i := range keys { diff --git a/netmap/netmap_contract.go b/netmap/netmap_contract.go index 10e1f4e..65ac7af 100644 --- a/netmap/netmap_contract.go +++ b/netmap/netmap_contract.go @@ -10,10 +10,6 @@ import ( ) type ( - irNode struct { - key []byte - } - storageNode struct { info []byte } @@ -70,11 +66,11 @@ func Init(keys [][]byte) { panic("netmap: contract already initialized") } - var irList []irNode + var irList []common.IRNode for i := 0; i < len(keys); i++ { key := keys[i] - irList = append(irList, irNode{key: key}) + irList = append(irList, common.IRNode{PublicKey: key}) } common.SetSerialized(ctx, innerRingKey, irList) @@ -91,7 +87,7 @@ func Init(keys [][]byte) { runtime.Log("netmap contract initialized") } -func InnerRingList() []irNode { +func InnerRingList() []common.IRNode { return getIRNodes(ctx) } @@ -99,16 +95,16 @@ func UpdateInnerRing(keys [][]byte) bool { innerRing := getIRNodes(ctx) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("updateInnerRing: this method must be invoked by inner ring nodes") } - var irList []irNode + var irList []common.IRNode for i := 0; i < len(keys); i++ { key := keys[i] - irList = append(irList, irNode{key: key}) + irList = append(irList, common.IRNode{PublicKey: key}) } rawIRList := binary.Serialize(irList) @@ -130,7 +126,7 @@ func AddPeer(nodeInfo []byte) bool { innerRing := getIRNodes(ctx) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { publicKey := nodeInfo[2:35] // offset:2, len:33 if !runtime.CheckWitness(publicKey) { @@ -172,7 +168,7 @@ func UpdateState(state int, publicKey []byte) bool { innerRing := getIRNodes(ctx) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { if !runtime.CheckWitness(publicKey) { panic("updateState: witness check failed") @@ -205,7 +201,7 @@ func NewEpoch(epochNum int) bool { innerRing := getIRNodes(ctx) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("newEpoch: this method must be invoked by inner ring nodes") } @@ -279,7 +275,7 @@ func SetConfig(id, key, val []byte) bool { innerRing := getIRNodes(ctx) threshold := len(innerRing)/3*2 + 1 - irKey := innerRingInvoker(innerRing) + irKey := common.InnerRingInvoker(innerRing) if len(irKey) == 0 { panic("setConfig: invoked by non inner ring node") } @@ -340,17 +336,6 @@ func Version() int { return version } -func innerRingInvoker(ir []irNode) []byte { - for i := 0; i < len(ir); i++ { - node := ir[i] - if runtime.CheckWitness(node.key) { - return node.key - } - } - - return nil -} - func addToNetmap(ctx storage.Context, n storageNode) []netmapNode { var ( newNode = n.info @@ -412,13 +397,13 @@ func filterNetmap(ctx storage.Context, st nodeState) []storageNode { return result } -func getIRNodes(ctx storage.Context) []irNode { +func getIRNodes(ctx storage.Context) []common.IRNode { data := storage.Get(ctx, innerRingKey) if data != nil { - return binary.Deserialize(data.([]byte)).([]irNode) + return binary.Deserialize(data.([]byte)).([]common.IRNode) } - return []irNode{} + return []common.IRNode{} } func getNetmapNodes(ctx storage.Context) []netmapNode {