From 7fbf6d73b05b064623ba43a01ce6eb01c8cf6135 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Fri, 19 Feb 2021 17:47:41 +0300 Subject: [PATCH] [#51] proxy: Add proxy contract Proxy contract used by notary contract as a main tx payment provider. `Verify` function verifies if main tx contains multisig of 5\7 inner ring nodes. If so, then contract pays for transaction. This is easier than support multisig wallet with GAS assets, because inner ring can change, therefore multisig wallet can change periodically. Signed-off-by: Alex Vanin --- Makefile | 2 +- common/ir.go | 19 +++++++++++- proxy/config.yml | 1 + proxy/proxy_contract.go | 65 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 proxy/config.yml create mode 100644 proxy/proxy_contract.go diff --git a/Makefile b/Makefile index aec885e..e4fe89e 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ all: sidechain mainnet sidechain: alphabet morph alphabet_sc = alphabet -morph_sc = audit balance container neofsid netmap reputation +morph_sc = audit balance container neofsid netmap proxy reputation mainnet_sc = neofs define sc_template diff --git a/common/ir.go b/common/ir.go index b27e476..98c3d0a 100644 --- a/common/ir.go +++ b/common/ir.go @@ -7,7 +7,10 @@ import ( "github.com/nspcc-dev/neo-go/pkg/interop/storage" ) -const irListMethod = "innerRingList" +const ( + irListMethod = "innerRingList" + multiaddrMethod = "multiaddress" +) type IRNode struct { PublicKey []byte @@ -39,3 +42,17 @@ func InnerRingListViaStorage(ctx storage.Context, key interface{}) []IRNode { func InnerRingList(sc interop.Hash160) []IRNode { return contract.Call(sc, irListMethod, contract.ReadOnly).([]IRNode) } + +// InnerRingMultiAddressViaStorage returns multiaddress of inner ring public +// keys by invoking netmap contract, which scripthash stored in the contract +// storage by the key `key`. +func InnerRingMultiAddressViaStorage(ctx storage.Context, key interface{}) []byte { + sc := storage.Get(ctx, key).([]byte) + return InnerRingMultiAddress(sc) +} + +// InnerRingMultiAddress returns multiaddress of inner ring public keys by +// invoking netmap contract. +func InnerRingMultiAddress(sc interop.Hash160) []byte { + return contract.Call(sc, multiaddrMethod, contract.ReadOnly).([]byte) +} diff --git a/proxy/config.yml b/proxy/config.yml new file mode 100644 index 0000000..6b64aa3 --- /dev/null +++ b/proxy/config.yml @@ -0,0 +1 @@ +name: "NeoFS Notary Proxy" diff --git a/proxy/proxy_contract.go b/proxy/proxy_contract.go new file mode 100644 index 0000000..9bceb58 --- /dev/null +++ b/proxy/proxy_contract.go @@ -0,0 +1,65 @@ +package proxycontract + +import ( + "github.com/nspcc-dev/neo-go/pkg/interop" + "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/runtime" + "github.com/nspcc-dev/neo-go/pkg/interop/storage" + "github.com/nspcc-dev/neofs-contract/common" +) + +const ( + version = 1 + + netmapContractKey = "netmapScriptHash" +) + +var ctx storage.Context + +func init() { + ctx = storage.GetContext() +} + +func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) { + caller := runtime.GetCallingScriptHash() + if !common.BytesEqual(caller, []byte(gas.Hash)) { + panic("onNEP17Payment: alphabet contract accepts GAS only") + } +} + +func Init(owner interop.Hash160, addrNetmap []byte) { + if !common.HasUpdateAccess(ctx) { + panic("only owner can reinitialize contract") + } + + if len(addrNetmap) != 20 { + panic("init: incorrect length of contract script hash") + } + + storage.Put(ctx, common.OwnerKey, owner) + storage.Put(ctx, netmapContractKey, addrNetmap) + + runtime.Log("proxy contract initialized") +} + +func Migrate(script []byte, manifest []byte) bool { + if !common.HasUpdateAccess(ctx) { + runtime.Log("only owner can update contract") + return false + } + + management.Update(script, manifest) + runtime.Log("proxy contract updated") + + return true +} + +func Verify() bool { + sig := common.InnerRingMultiAddressViaStorage(ctx, netmapContractKey) + return runtime.CheckWitness(sig) +} + +func Version() int { + return version +}