forked from TrueCloudLab/frostfs-contract
[#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:
parent
e4ba9c6840
commit
7fbf6d73b0
4 changed files with 85 additions and 2 deletions
2
Makefile
2
Makefile
|
@ -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
|
||||||
|
|
19
common/ir.go
19
common/ir.go
|
@ -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
1
proxy/config.yml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
name: "NeoFS Notary Proxy"
|
65
proxy/proxy_contract.go
Normal file
65
proxy/proxy_contract.go
Normal 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
|
||||||
|
}
|
Loading…
Reference in a new issue