diff --git a/alphabet/alphabet_contract.go b/alphabet/alphabet_contract.go index de8bdb3..78c1c62 100644 --- a/alphabet/alphabet_contract.go +++ b/alphabet/alphabet_contract.go @@ -200,9 +200,7 @@ func Vote(epoch int, candidates []interop.PublicKey) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("invalid invoker") - } + common.CheckAlphabetWitness(multiaddr) } curEpoch := currentEpoch(ctx) diff --git a/balance/balance_contract.go b/balance/balance_contract.go index b970e4d..c5adc66 100644 --- a/balance/balance_contract.go +++ b/balance/balance_contract.go @@ -166,9 +166,7 @@ func TransferX(from, to interop.Hash160, amount int, details []byte) { ) } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked from inner ring") - } + common.CheckAlphabetWitness(multiaddr) } if notaryDisabled && !indirectCall { @@ -216,9 +214,7 @@ func Lock(txDetails []byte, from, to interop.Hash160, amount, until int) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked from inner ring") - } + common.CheckAlphabetWitness(multiaddr) } details := common.LockTransferDetails(txDetails) @@ -273,9 +269,7 @@ func NewEpoch(epochNum int) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked from inner ring") - } + common.CheckAlphabetWitness(multiaddr) } it := storage.Find(ctx, []byte{}, storage.KeysOnly) @@ -324,9 +318,7 @@ func Mint(to interop.Hash160, amount int, txDetails []byte) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked from inner ring") - } + common.CheckAlphabetWitness(multiaddr) } details := common.MintTransferDetails(txDetails) @@ -383,9 +375,7 @@ func Burn(from interop.Hash160, amount int, txDetails []byte) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked from inner ring") - } + common.CheckAlphabetWitness(multiaddr) } details := common.BurnTransferDetails(txDetails) diff --git a/common/witness.go b/common/witness.go new file mode 100644 index 0000000..dfcdde6 --- /dev/null +++ b/common/witness.go @@ -0,0 +1,39 @@ +package common + +import "github.com/nspcc-dev/neo-go/pkg/interop/runtime" + +var ( + // ErrAlphabetWitnessFailed appears when method must be + // called by Alphabet but was not. + ErrAlphabetWitnessFailed = "alphabet witness check failed" + // ErrOwnerWitnessFailed appears when method must be called + // by owner of some assets but was not. + ErrOwnerWitnessFailed = "owner witness check failed" + // ErrWitnessFailed appears when method must be called + // using certain public key but was not. + ErrWitnessFailed = "witness check failed" +) + +// CheckAlphabetWitness checks witness of the passed caller. +// Panics with ErrAlphabetWitnessFailed message on fail. +func CheckAlphabetWitness(caller []byte) { + checkWitnessWithPanic(caller, ErrAlphabetWitnessFailed) +} + +// CheckOwnerWitness checks witness of the passed caller. +// Panics with ErrOwnerWitnessFailed message on fail. +func CheckOwnerWitness(caller []byte) { + checkWitnessWithPanic(caller, ErrOwnerWitnessFailed) +} + +// CheckWitness checks witness of the passed caller. +// Panics with ErrWitnessFailed message on fail. +func CheckWitness(caller []byte) { + checkWitnessWithPanic(caller, ErrWitnessFailed) +} + +func checkWitnessWithPanic(caller []byte, panicMsg string) { + if !runtime.CheckWitness(caller) { + panic(panicMsg) + } +} diff --git a/container/container_contract.go b/container/container_contract.go index 1c323f5..9a00a5a 100644 --- a/container/container_contract.go +++ b/container/container_contract.go @@ -226,9 +226,7 @@ func PutNamed(container []byte, signature interop.Signature, common.RemoveVotes(ctx, id) } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("alphabet witness check failed") - } + common.CheckAlphabetWitness(multiaddr) } // todo: check if new container with unique container id @@ -333,9 +331,7 @@ func Delete(containerID []byte, signature interop.Signature, token []byte) { common.RemoveVotes(ctx, id) } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("alphabet witness check failed") - } + common.CheckAlphabetWitness(multiaddr) } key := append([]byte(nnsHasAliasKey), containerID...) @@ -445,9 +441,7 @@ func SetEACL(eACL []byte, signature interop.Signature, publicKey interop.PublicK common.RemoveVotes(ctx, id) } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("alphabet witness check failed") - } + common.CheckAlphabetWitness(multiaddr) } rule := ExtendedACL{ @@ -492,9 +486,7 @@ func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.Public panic(NotFoundError) } - if !runtime.CheckWitness(pubKey) { - panic("invalid witness of container size estimation") - } + common.CheckWitness(pubKey) if !isStorageNode(ctx, pubKey) { panic("method must be invoked by storage node from network map") @@ -580,9 +572,7 @@ func NewEpoch(epochNum int) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("method must be invoked by inner ring") - } + common.CheckAlphabetWitness(multiaddr) } candidates := keysToDelete(ctx, epochNum) @@ -610,9 +600,7 @@ func StartContainerEstimation(epoch int) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("method must be invoked by inner ring") - } + common.CheckAlphabetWitness(multiaddr) } if notaryDisabled { @@ -650,9 +638,7 @@ func StopContainerEstimation(epoch int) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("method must be invoked by inner ring") - } + common.CheckAlphabetWitness(multiaddr) } if notaryDisabled { diff --git a/neofs/neofs_contract.go b/neofs/neofs_contract.go index 155a3de..7b10522 100644 --- a/neofs/neofs_contract.go +++ b/neofs/neofs_contract.go @@ -112,9 +112,7 @@ func Update(script []byte, manifest []byte, data interface{}) { alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight)) alphabetCommittee := common.Multiaddress(alphabetKeys, true) - if !runtime.CheckWitness(alphabetCommittee) { - panic("only side chain committee can update contract") - } + common.CheckAlphabetWitness(alphabetCommittee) contract.Call(interop.Hash160(management.Hash), "update", contract.All, script, manifest, common.AppendVersion(data)) @@ -208,9 +206,7 @@ func InnerRingCandidateRemove(key interop.PublicKey) { func InnerRingCandidateAdd(key interop.PublicKey) { ctx := storage.GetContext() - if !runtime.CheckWitness(key) { - panic("this method must be invoked by candidate") - } + common.CheckWitness(key) c := common.IRNode{PublicKey: key} candidates := getNodes(ctx, candidatesKey) @@ -342,9 +338,7 @@ func Cheque(id []byte, user interop.Hash160, amount int, lockAcc []byte) { } } else { multiaddr := AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked by alphabet") - } + common.CheckAlphabetWitness(multiaddr) } from := runtime.GetExecutingScriptHash() @@ -435,9 +429,7 @@ func AlphabetUpdate(id []byte, args []interop.PublicKey) { } } else { multiaddr := AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked by alphabet") - } + common.CheckAlphabetWitness(multiaddr) } newAlphabet := []common.IRNode{} @@ -496,9 +488,7 @@ func SetConfig(id, key, val []byte) { } } else { multiaddr := AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked by alphabet") - } + common.CheckAlphabetWitness(multiaddr) } if notaryDisabled { diff --git a/neofsid/neofsid_contract.go b/neofsid/neofsid_contract.go index eba5f7e..3427ee7 100644 --- a/neofsid/neofsid_contract.go +++ b/neofsid/neofsid_contract.go @@ -113,9 +113,7 @@ func AddKey(owner []byte, keys []interop.PublicKey) { ) } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("invocation from non inner ring node") - } + common.CheckAlphabetWitness(multiaddr) } for i := range keys { @@ -172,9 +170,7 @@ func RemoveKey(owner []byte, keys []interop.PublicKey) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("invocation from non inner ring node") - } + common.CheckAlphabetWitness(multiaddr) } for i := range keys { diff --git a/netmap/netmap_contract.go b/netmap/netmap_contract.go index 07da829..ce127ff 100644 --- a/netmap/netmap_contract.go +++ b/netmap/netmap_contract.go @@ -161,9 +161,7 @@ func UpdateInnerRing(keys []interop.PublicKey) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked by alphabet nodes") - } + common.CheckAlphabetWitness(multiaddr) } var irList []common.IRNode @@ -218,9 +216,8 @@ func AddPeer(nodeInfo []byte) { if !alphabetCall { // V2 format publicKey := nodeInfo[2:35] // offset:2, len:33 - if !runtime.CheckWitness(publicKey) { - panic("witness check failed") - } + common.CheckWitness(publicKey) + runtime.Notify("AddPeer", nodeInfo) return } @@ -270,9 +267,8 @@ func UpdateState(state int, publicKey interop.PublicKey) { alphabet = common.AlphabetNodes() nodeKey = common.InnerRingInvoker(alphabet) if len(nodeKey) == 0 { - if !runtime.CheckWitness(publicKey) { - panic("witness check failed") - } + common.CheckWitness(publicKey) + runtime.Notify("UpdateState", state, publicKey) return } @@ -288,12 +284,8 @@ func UpdateState(state int, publicKey interop.PublicKey) { common.RemoveVotes(ctx, id) } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(publicKey) { - panic("witness check failed") - } - if !runtime.CheckWitness(multiaddr) { - panic("alphabet witness check failed") - } + common.CheckWitness(publicKey) + common.CheckAlphabetWitness(multiaddr) } switch nodeState(state) { @@ -331,9 +323,7 @@ func NewEpoch(epochNum int) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("this method must be invoked by inner ring nodes") - } + common.CheckAlphabetWitness(multiaddr) } if notaryDisabled { @@ -463,9 +453,7 @@ func SetConfig(id, key, val []byte) { } } else { multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("invoked by non inner ring node") - } + common.CheckAlphabetWitness(multiaddr) } if notaryDisabled { diff --git a/nns/nns_contract.go b/nns/nns_contract.go index 3f86690..d44470c 100644 --- a/nns/nns_contract.go +++ b/nns/nns_contract.go @@ -303,9 +303,7 @@ func Register(name string, owner interop.Hash160, email string, refresh, retry, if !isValid(owner) { panic("invalid owner") } - if !runtime.CheckWitness(owner) { - panic("not witnessed by owner") - } + common.CheckOwnerWitness(owner) runtime.BurnGas(GetPrice()) var ( tokenKey = getTokenKey([]byte(name)) @@ -368,9 +366,7 @@ func SetAdmin(name string, admin interop.Hash160) { } ctx := storage.GetContext() ns := getNameState(ctx, []byte(name)) - if !runtime.CheckWitness(ns.Owner) { - panic("not witnessed by owner") - } + common.CheckOwnerWitness(ns.Owner) ns.Admin = admin putNameState(ctx, ns) } diff --git a/subnet/subnet_contract.go b/subnet/subnet_contract.go index 088dbc7..2743c17 100644 --- a/subnet/subnet_contract.go +++ b/subnet/subnet_contract.go @@ -37,8 +37,6 @@ const ( ErrUserNotExist = "user not found" // ErrAccessDenied is thrown when operation is denied for caller. ErrAccessDenied = "access denied" - - errCheckWitnessFailed = "owner witness check failed" ) const ( @@ -103,9 +101,7 @@ func Put(id []byte, ownerKey interop.PublicKey, info []byte) { alphabet := common.AlphabetNodes() nodeKey := common.InnerRingInvoker(alphabet) if len(nodeKey) == 0 { - if !runtime.CheckWitness(ownerKey) { - panic("witness check failed") - } + common.CheckWitness(ownerKey) runtime.Notify("Put", id, ownerKey, info) return } @@ -119,14 +115,10 @@ func Put(id []byte, ownerKey interop.PublicKey, info []byte) { common.RemoveVotes(ctx, id) } else { - if !runtime.CheckWitness(ownerKey) { - panic(errCheckWitnessFailed) - } + common.CheckOwnerWitness(ownerKey) multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - panic("alphabet witness check failed") - } + common.CheckAlphabetWitness(multiaddr) } storage.Put(ctx, stKey, ownerKey) @@ -165,9 +157,7 @@ func Delete(id []byte) { } owner := raw.([]byte) - if !runtime.CheckWitness(owner) { - panic(errCheckWitnessFailed) - } + common.CheckOwnerWitness(owner) storage.Delete(ctx, key) @@ -210,9 +200,7 @@ func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) { } owner := rawOwner.([]byte) - if !runtime.CheckWitness(owner) { - panic(errCheckWitnessFailed) - } + common.CheckOwnerWitness(owner) stKey[0] = nodeAdminPrefix @@ -245,9 +233,7 @@ func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) { } owner := rawOwner.([]byte) - if !runtime.CheckWitness(owner) { - panic(errCheckWitnessFailed) - } + common.CheckOwnerWitness(owner) stKey[0] = nodeAdminPrefix @@ -391,9 +377,7 @@ func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.Publ } owner := rawOwner.([]byte) - if !runtime.CheckWitness(owner) { - panic(errCheckWitnessFailed) - } + common.CheckOwnerWitness(owner) stKey[0] = clientAdminPrefix stKey = append(stKey, groupID...) @@ -433,9 +417,7 @@ func RemoveClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.P } owner := rawOwner.([]byte) - if !runtime.CheckWitness(owner) { - panic(errCheckWitnessFailed) - } + common.CheckOwnerWitness(owner) stKey[0] = clientAdminPrefix stKey = append(stKey, groupID...) diff --git a/tests/container_test.go b/tests/container_test.go index 39a1172..084b1ea 100644 --- a/tests/container_test.go +++ b/tests/container_test.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/neotest" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neofs-contract/common" "github.com/nspcc-dev/neofs-contract/container" "github.com/nspcc-dev/neofs-contract/nns" ) @@ -88,7 +89,7 @@ func TestContainerPut(t *testing.T) { balanceMint(t, cBal, acc, containerFee*1, []byte{}) cAcc := c.WithSigners(acc) - cAcc.InvokeFail(t, "alphabet witness check failed", "put", putArgs...) + cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "put", putArgs...) c.Invoke(t, stackitem.Null{}, "put", putArgs...) @@ -161,7 +162,7 @@ func TestContainerDelete(t *testing.T) { c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token) cAcc := c.WithSigners(acc) - cAcc.InvokeFail(t, "alphabet witness check failed", "delete", + cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "delete", cnt.id[:], cnt.sig, cnt.token) c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.token) @@ -256,7 +257,7 @@ func TestContainerSetEACL(t *testing.T) { e := dummyEACL(cnt.id) setArgs := []interface{}{e.value, e.sig, e.pub, e.token} cAcc := c.WithSigners(acc) - cAcc.InvokeFail(t, "alphabet witness check failed", "setEACL", setArgs...) + cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "setEACL", setArgs...) c.Invoke(t, stackitem.Null{}, "setEACL", setArgs...) diff --git a/tests/netmap_test.go b/tests/netmap_test.go index 3cf6073..3f8001a 100644 --- a/tests/netmap_test.go +++ b/tests/netmap_test.go @@ -11,6 +11,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" + "github.com/nspcc-dev/neofs-contract/common" "github.com/nspcc-dev/neofs-contract/container" "github.com/stretchr/testify/require" ) @@ -73,7 +74,7 @@ func TestAddPeer(t *testing.T) { acc1 := c.NewAccount(t) cAcc1 := c.WithSigners(acc1) - cAcc1.InvokeFail(t, "witness check failed", "addPeer", dummyInfo) + cAcc1.InvokeFail(t, common.ErrWitnessFailed, "addPeer", dummyInfo) h := cAcc.Invoke(t, stackitem.Null{}, "addPeer", dummyInfo) aer := cAcc.CheckHalt(t, h) @@ -105,9 +106,9 @@ func TestUpdateState(t *testing.T) { require.True(t, ok) t.Run("missing witness", func(t *testing.T) { - cAcc.InvokeFail(t, "alphabet witness check failed", + cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "updateState", int64(2), pub) - e.InvokeFail(t, "witness check failed", + e.InvokeFail(t, common.ErrWitnessFailed, "updateState", int64(2), pub) }) diff --git a/tests/subnet_test.go b/tests/subnet_test.go index b44dfc0..fa4d6a3 100644 --- a/tests/subnet_test.go +++ b/tests/subnet_test.go @@ -45,10 +45,10 @@ func TestSubnet_Put(t *testing.T) { binary.LittleEndian.PutUint32(id, 123) info := randomBytes(10) - e.InvokeFail(t, "witness check failed", "put", id, pub, info) + e.InvokeFail(t, common.ErrWitnessFailed, "put", id, pub, info) cAcc := e.WithSigners(acc) - cAcc.InvokeFail(t, "alphabet witness check failed", "put", id, pub, info) + cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "put", id, pub, info) cBoth := e.WithSigners(e.Committee, acc) cBoth.InvokeFail(t, subnet.ErrInvalidSubnetID, "put", []byte{1, 2, 3}, pub, info) @@ -63,7 +63,7 @@ func TestSubnet_Delete(t *testing.T) { id, owner := createSubnet(t, e) - e.InvokeFail(t, "witness check failed", "delete", id) + e.InvokeFail(t, common.ErrWitnessFailed, "delete", id) cAcc := e.WithSigners(owner) cAcc.InvokeFail(t, subnet.ErrInvalidSubnetID, "delete", []byte{1, 1, 1, 1}) @@ -88,7 +88,7 @@ func TestSubnet_AddNodeAdmin(t *testing.T) { e.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, admPub) cAdm := e.WithSigners(adm) - cAdm.InvokeFail(t, "owner witness check failed", method, id, admPub) + cAdm.InvokeFail(t, common.ErrOwnerWitnessFailed, method, id, admPub) cOwner := e.WithSigners(owner) cOwner.Invoke(t, stackitem.Null{}, method, id, admPub) @@ -112,7 +112,7 @@ func TestSubnet_RemoveNodeAdmin(t *testing.T) { e.InvokeFail(t, subnet.ErrNotExist, method, []byte{0, 0, 0, 0, 0}, admPub) cAdm := e.WithSigners(adm) - cAdm.InvokeFail(t, "owner witness check failed", method, id, admPub) + cAdm.InvokeFail(t, common.ErrOwnerWitnessFailed, method, id, admPub) cOwner := e.WithSigners(owner)