[#49] Support contract migration
At initialization contract saves master script hash that allows to re-initialize or migrate contract. Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
a4a9a49a76
commit
88c738b736
11 changed files with 186 additions and 28 deletions
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
|
||||
"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/native/neo"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
|
@ -34,15 +35,16 @@ func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
|||
}
|
||||
}
|
||||
|
||||
func Init(addrNetmap []byte, name string, index, total int) {
|
||||
if storage.Get(ctx, netmapKey) != nil {
|
||||
panic("contract already deployed")
|
||||
func Init(owner interop.Hash160, addrNetmap []byte, name string, index, total int) {
|
||||
if !common.HasUpdateAccess(ctx) {
|
||||
panic("only owner can reinitialize contract")
|
||||
}
|
||||
|
||||
if len(addrNetmap) != 20 {
|
||||
panic("incorrect length of contract script hash")
|
||||
}
|
||||
|
||||
storage.Put(ctx, common.OwnerKey, owner)
|
||||
storage.Put(ctx, netmapKey, addrNetmap)
|
||||
storage.Put(ctx, nameKey, name)
|
||||
storage.Put(ctx, indexKey, index)
|
||||
|
@ -53,6 +55,18 @@ func Init(addrNetmap []byte, name string, index, total int) {
|
|||
runtime.Log(name + " 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("alphabet contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func Gas() int {
|
||||
return gas.BalanceOf(runtime.GetExecutingScriptHash())
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||
"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"
|
||||
|
@ -37,7 +38,6 @@ const (
|
|||
version = 1
|
||||
|
||||
netmapContractKey = "netmapScriptHash"
|
||||
netmapContractKeyLn = len(netmapContractKey)
|
||||
)
|
||||
|
||||
var ctx storage.Context
|
||||
|
@ -46,20 +46,33 @@ func init() {
|
|||
ctx = storage.GetContext()
|
||||
}
|
||||
|
||||
func Init(addrNetmap interop.Hash160) {
|
||||
if storage.Get(ctx, netmapContractKey) != nil {
|
||||
panic("init: contract already deployed")
|
||||
func Init(owner interop.Hash160, addrNetmap interop.Hash160) {
|
||||
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("audit 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("audit contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func Put(rawAuditResult []byte) bool {
|
||||
innerRing := common.InnerRingListViaStorage(ctx, netmapContractKey)
|
||||
|
||||
|
@ -126,10 +139,18 @@ func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte {
|
|||
func list(it iterator.Iterator) [][]byte {
|
||||
var result [][]byte
|
||||
|
||||
ignore := [][]byte{
|
||||
[]byte(netmapContractKey),
|
||||
[]byte(common.OwnerKey),
|
||||
}
|
||||
|
||||
loop:
|
||||
for iterator.Next(it) {
|
||||
key := iterator.Value(it).([]byte) // iterator MUST BE `storage.KeysOnly`
|
||||
if len(key) == netmapContractKeyLn {
|
||||
continue
|
||||
for _, ignoreKey := range ignore {
|
||||
if common.BytesEqual(key, ignoreKey) {
|
||||
continue loop
|
||||
}
|
||||
}
|
||||
|
||||
result = append(result, key)
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||
"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"
|
||||
|
@ -63,21 +64,34 @@ func init() {
|
|||
token = CreateToken()
|
||||
}
|
||||
|
||||
func Init(addrNetmap, addrContainer []byte) {
|
||||
if storage.Get(ctx, netmapContractKey) != nil {
|
||||
panic("init: contract already deployed")
|
||||
func Init(owner interop.Hash160, addrNetmap, addrContainer []byte) {
|
||||
if !common.HasUpdateAccess(ctx) {
|
||||
panic("only owner can reinitialize contract")
|
||||
}
|
||||
|
||||
if len(addrNetmap) != 20 || len(addrContainer) != 20 {
|
||||
panic("init: incorrect length of contract script hash")
|
||||
}
|
||||
|
||||
storage.Put(ctx, common.OwnerKey, owner)
|
||||
storage.Put(ctx, netmapContractKey, addrNetmap)
|
||||
storage.Put(ctx, containerContractKey, addrContainer)
|
||||
|
||||
runtime.Log("balance 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("balance contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func Symbol() string {
|
||||
return token.Symbol
|
||||
}
|
||||
|
|
22
common/update.go
Normal file
22
common/update.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
||||
)
|
||||
|
||||
const OwnerKey = "contractOwner"
|
||||
|
||||
// HasUpdateAccess returns true if contract can be initialized, re-initialized
|
||||
// or migrated.
|
||||
func HasUpdateAccess(ctx storage.Context) bool {
|
||||
data := storage.Get(ctx, OwnerKey)
|
||||
if data == nil { // contract has not been initialized yet, return true
|
||||
return true
|
||||
}
|
||||
|
||||
owner := data.(interop.Hash160)
|
||||
|
||||
return runtime.CheckWitness(owner)
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||
"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"
|
||||
|
@ -59,17 +60,16 @@ func init() {
|
|||
ctx = storage.GetContext()
|
||||
}
|
||||
|
||||
func Init(addrNetmap, addrBalance, addrID []byte) {
|
||||
if storage.Get(ctx, netmapContractKey) != nil &&
|
||||
storage.Get(ctx, balanceContractKey) != nil &&
|
||||
storage.Get(ctx, neofsIDContractKey) != nil {
|
||||
panic("init: contract already deployed")
|
||||
func Init(owner interop.Hash160, addrNetmap, addrBalance, addrID []byte) {
|
||||
if !common.HasUpdateAccess(ctx) {
|
||||
panic("only owner can reinitialize contract")
|
||||
}
|
||||
|
||||
if len(addrNetmap) != 20 || len(addrBalance) != 20 || len(addrID) != 20 {
|
||||
panic("init: incorrect length of contract script hash")
|
||||
}
|
||||
|
||||
storage.Put(ctx, common.OwnerKey, owner)
|
||||
storage.Put(ctx, netmapContractKey, addrNetmap)
|
||||
storage.Put(ctx, balanceContractKey, addrBalance)
|
||||
storage.Put(ctx, neofsIDContractKey, addrID)
|
||||
|
@ -77,6 +77,18 @@ func Init(addrNetmap, addrBalance, addrID []byte) {
|
|||
runtime.Log("container 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("container contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func Put(container, signature, publicKey []byte) bool {
|
||||
netmapContractAddr := storage.Get(ctx, netmapContractKey).([]byte)
|
||||
innerRing := common.InnerRingList(netmapContractAddr)
|
||||
|
|
2
go.mod
2
go.mod
|
@ -2,4 +2,4 @@ module github.com/nspcc-dev/neofs-contract
|
|||
|
||||
go 1.13
|
||||
|
||||
require github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210211114309-2ee755e09fcd
|
||||
require github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210212114643-94672d4d83b7
|
||||
|
|
4
go.sum
4
go.sum
|
@ -139,6 +139,8 @@ github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210208141009-71494e6ae449 h1:gfsr6+g
|
|||
github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210208141009-71494e6ae449/go.mod h1:6D4NY4Bs1OTan3VdLvAuy9kGt460/2dsfHcthQGS+QU=
|
||||
github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210211114309-2ee755e09fcd h1:4zMEQ+xVaa6oEnzzHOlRwwRQMdze/so7YpjjE8bfkPI=
|
||||
github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210211114309-2ee755e09fcd/go.mod h1:6D4NY4Bs1OTan3VdLvAuy9kGt460/2dsfHcthQGS+QU=
|
||||
github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210212114643-94672d4d83b7 h1:4DPdZM6M1idOhkpMlZsoNjNTuj0Y4I5EyVxe5FA5jmY=
|
||||
github.com/nspcc-dev/neo-go v0.93.0-pre.0.20210212114643-94672d4d83b7/go.mod h1:6tixfAd+d8TIm05DA874j6t898G/fyqA2fHVJxkJCXQ=
|
||||
github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA=
|
||||
github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw=
|
||||
github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso=
|
||||
|
@ -239,6 +241,8 @@ golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20180318012157-96caea41033d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
|
@ -38,6 +38,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||
"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"
|
||||
|
@ -84,9 +85,9 @@ func init() {
|
|||
}
|
||||
|
||||
// Init set up initial inner ring node keys.
|
||||
func Init(args [][]byte) bool {
|
||||
if storage.Get(ctx, innerRingKey) != nil {
|
||||
panic("neofs: contract already deployed")
|
||||
func Init(owner interop.PublicKey, args [][]byte) bool {
|
||||
if !common.HasUpdateAccess(ctx) {
|
||||
panic("only owner can reinitialize contract")
|
||||
}
|
||||
|
||||
var irList []common.IRNode
|
||||
|
@ -109,11 +110,26 @@ func Init(args [][]byte) bool {
|
|||
common.SetSerialized(ctx, candidatesKey, []common.IRNode{})
|
||||
common.SetSerialized(ctx, cashedChequesKey, []cheque{})
|
||||
|
||||
storage.Put(ctx, common.OwnerKey, owner)
|
||||
|
||||
runtime.Log("neofs: contract initialized")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Migrate updates smart contract execution script and manifest.
|
||||
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("neofs contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// InnerRingList returns array of inner ring node keys.
|
||||
func InnerRingList() []common.IRNode {
|
||||
return getInnerRingNodes(ctx, innerRingKey)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package neofsidcontract
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
|
||||
"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"
|
||||
|
@ -27,21 +29,34 @@ func init() {
|
|||
ctx = storage.GetContext()
|
||||
}
|
||||
|
||||
func Init(addrNetmap, addrContainer []byte) {
|
||||
if storage.Get(ctx, netmapContractKey) != nil {
|
||||
panic("init: contract already deployed")
|
||||
func Init(owner interop.Hash160, addrNetmap, addrContainer []byte) {
|
||||
if !common.HasUpdateAccess(ctx) {
|
||||
panic("only owner can reinitialize contract")
|
||||
}
|
||||
|
||||
if len(addrNetmap) != 20 || len(addrContainer) != 20 {
|
||||
panic("init: incorrect length of contract script hash")
|
||||
}
|
||||
|
||||
storage.Put(ctx, common.OwnerKey, owner)
|
||||
storage.Put(ctx, netmapContractKey, addrNetmap)
|
||||
storage.Put(ctx, containerContractKey, addrContainer)
|
||||
|
||||
runtime.Log("neofsid 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("neofsid contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func AddKey(owner []byte, keys [][]byte) bool {
|
||||
var (
|
||||
n int // number of votes for inner ring invoke
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package netmapcontract
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/binary"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/crypto"
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
|
||||
"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"
|
||||
|
@ -57,9 +59,9 @@ func init() {
|
|||
|
||||
// Init function sets up initial list of inner ring public keys and should
|
||||
// be invoked once at neofs infrastructure setup.
|
||||
func Init(keys [][]byte) {
|
||||
if storage.Get(ctx, innerRingKey) != nil {
|
||||
panic("netmap: contract already initialized")
|
||||
func Init(owner interop.Hash160, keys [][]byte) {
|
||||
if !common.HasUpdateAccess(ctx) {
|
||||
panic("only owner can reinitialize contract")
|
||||
}
|
||||
|
||||
var irList []common.IRNode
|
||||
|
@ -69,6 +71,8 @@ func Init(keys [][]byte) {
|
|||
irList = append(irList, common.IRNode{PublicKey: key})
|
||||
}
|
||||
|
||||
storage.Put(ctx, common.OwnerKey, owner)
|
||||
|
||||
common.SetSerialized(ctx, innerRingKey, irList)
|
||||
|
||||
// epoch number is a little endian int, it doesn't need to be serialized
|
||||
|
@ -83,6 +87,18 @@ func Init(keys [][]byte) {
|
|||
runtime.Log("netmap 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("netmap contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func InnerRingList() []common.IRNode {
|
||||
return getIRNodes(ctx)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package reputationcontract
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
"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"
|
||||
|
@ -28,6 +30,28 @@ func init() {
|
|||
ctx = storage.GetContext()
|
||||
}
|
||||
|
||||
func Init(owner interop.Hash160) {
|
||||
if !common.HasUpdateAccess(ctx) {
|
||||
panic("only owner can reinitialize contract")
|
||||
}
|
||||
|
||||
storage.Put(ctx, common.OwnerKey, owner)
|
||||
|
||||
runtime.Log("reputation 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("reputation contract updated")
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func Put(manager, epoch, typ []byte, newTrustList [][]byte) bool {
|
||||
if !runtime.CheckWitness(manager) {
|
||||
panic("put: incorrect manager key")
|
||||
|
|
Loading…
Reference in a new issue