[#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 <alexey@nspcc.ru>
This commit is contained in:
Alex Vanin 2021-02-19 17:47:41 +03:00 committed by Alex Vanin
parent e4ba9c6840
commit 7fbf6d73b0
4 changed files with 85 additions and 2 deletions

View file

@ -9,7 +9,7 @@ all: sidechain mainnet
sidechain: alphabet morph sidechain: alphabet morph
alphabet_sc = alphabet alphabet_sc = alphabet
morph_sc = audit balance container neofsid netmap reputation morph_sc = audit balance container neofsid netmap proxy reputation
mainnet_sc = neofs mainnet_sc = neofs
define sc_template define sc_template

View file

@ -7,7 +7,10 @@ import (
"github.com/nspcc-dev/neo-go/pkg/interop/storage" "github.com/nspcc-dev/neo-go/pkg/interop/storage"
) )
const irListMethod = "innerRingList" const (
irListMethod = "innerRingList"
multiaddrMethod = "multiaddress"
)
type IRNode struct { type IRNode struct {
PublicKey []byte PublicKey []byte
@ -39,3 +42,17 @@ func InnerRingListViaStorage(ctx storage.Context, key interface{}) []IRNode {
func InnerRingList(sc interop.Hash160) []IRNode { func InnerRingList(sc interop.Hash160) []IRNode {
return contract.Call(sc, irListMethod, contract.ReadOnly).([]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)
}

1
proxy/config.yml Normal file
View file

@ -0,0 +1 @@
name: "NeoFS Notary Proxy"

65
proxy/proxy_contract.go Normal file
View file

@ -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
}