parent
47af5e3f9c
commit
d38a076920
2 changed files with 151 additions and 48 deletions
95
neofs/doc.go
95
neofs/doc.go
|
@ -1,2 +1,95 @@
|
||||||
// NeoFS contract description.
|
/*
|
||||||
|
NeoFS contract is a contract deployed in NeoFS main chain.
|
||||||
|
|
||||||
|
NeoFS contract is an entry point to NeoFS users. This contract stores all NeoFS
|
||||||
|
related GAS, registers new Inner Ring candidates and produces notifications
|
||||||
|
to control side chain.
|
||||||
|
|
||||||
|
While main chain committee controls list of Alphabet nodes in native
|
||||||
|
RoleManagement contract, NeoFS can't change more than 1\3 keys at a time.
|
||||||
|
NeoFS contract contains actual list of Alphabet nodes in the side chain.
|
||||||
|
|
||||||
|
Network configuration also stored in NeoFS contract. All the changes in
|
||||||
|
configuration are mirrored in side chain with notifications.
|
||||||
|
|
||||||
|
Contract notifications
|
||||||
|
|
||||||
|
Deposit notification. This notification is produced when user transfers native
|
||||||
|
GAS to the NeoFS contract address. The same amount of NEOFS token will be
|
||||||
|
minted in Balance contract in the side chain.
|
||||||
|
|
||||||
|
Deposit:
|
||||||
|
- name: from
|
||||||
|
type: Hash160
|
||||||
|
- name: amount
|
||||||
|
type: Integer
|
||||||
|
- name: receiver
|
||||||
|
type: Hash160
|
||||||
|
- name: txHash
|
||||||
|
type: Hash256
|
||||||
|
|
||||||
|
Withdraw notification. This notification is produced when user wants to
|
||||||
|
withdraw GAS from internal NeoFS balance and has payed fee for that.
|
||||||
|
|
||||||
|
Withdraw:
|
||||||
|
- name: user
|
||||||
|
type: Hash160
|
||||||
|
- name: amount
|
||||||
|
type: Integer
|
||||||
|
- name: txHash
|
||||||
|
type: Hash256
|
||||||
|
|
||||||
|
|
||||||
|
Cheque notification. This notification is produced when NeoFS contract
|
||||||
|
successfully transferred assets back to the user after withdraw.
|
||||||
|
|
||||||
|
Cheque:
|
||||||
|
- name: id
|
||||||
|
type: ByteArray
|
||||||
|
- name: user
|
||||||
|
type: Hash160
|
||||||
|
- name: amount
|
||||||
|
type: Integer
|
||||||
|
- name: lockAccount
|
||||||
|
type: ByteArray
|
||||||
|
|
||||||
|
Bind notification. This notification is produced when user wants to bind
|
||||||
|
public keys with user account (OwnerID). Keys argument is array of ByteArray.
|
||||||
|
|
||||||
|
Bind:
|
||||||
|
- name: user
|
||||||
|
type: ByteArray
|
||||||
|
- name: keys
|
||||||
|
type: Array
|
||||||
|
|
||||||
|
Unbind notification. This notification is produced when user wants to unbind
|
||||||
|
public keys with user account (OwnerID). Keys argument is an array of ByteArray.
|
||||||
|
|
||||||
|
Unbind:
|
||||||
|
- name: user
|
||||||
|
type: ByteArray
|
||||||
|
- name: keys
|
||||||
|
type: Array
|
||||||
|
|
||||||
|
AlphabetUpdate notification. This notification is produced when Alphabet nodes
|
||||||
|
updated it's list in the contract. Alphabet argument is an array of ByteArray. It
|
||||||
|
contains public keys of new alphabet nodes.
|
||||||
|
|
||||||
|
AlphabetUpdate:
|
||||||
|
- name: id
|
||||||
|
type: ByteArray
|
||||||
|
- name: alphabet
|
||||||
|
type: Array
|
||||||
|
|
||||||
|
SetConfig notification. This notification is produced when Alphabet nodes update
|
||||||
|
NeoFS network configuration value.
|
||||||
|
|
||||||
|
SetConfig
|
||||||
|
- name: id
|
||||||
|
type: ByteArray
|
||||||
|
- name: key
|
||||||
|
type: ByteArray
|
||||||
|
- name: value
|
||||||
|
type: ByteArray
|
||||||
|
*/
|
||||||
package neofs
|
package neofs
|
||||||
|
|
|
@ -1,36 +1,5 @@
|
||||||
package neofs
|
package neofs
|
||||||
|
|
||||||
/*
|
|
||||||
NeoFS Smart Contract for NEO3.0.
|
|
||||||
|
|
||||||
Utility methods, executed once in deploy stage:
|
|
||||||
- Init
|
|
||||||
- InitConfig
|
|
||||||
|
|
||||||
User related methods:
|
|
||||||
- Withdraw
|
|
||||||
- Bind
|
|
||||||
- Unbind
|
|
||||||
|
|
||||||
Inner ring list related methods:
|
|
||||||
- AlphabetList
|
|
||||||
- AlphabetAddress
|
|
||||||
- InnerRingCandidates
|
|
||||||
- InnerRingCandidateAdd
|
|
||||||
- InnerRingCandidateRemove
|
|
||||||
- AlphabetUpdate
|
|
||||||
|
|
||||||
Config methods:
|
|
||||||
- Config
|
|
||||||
- ListConfig
|
|
||||||
- SetConfig
|
|
||||||
|
|
||||||
Other utility methods:
|
|
||||||
- Migrate
|
|
||||||
- Version
|
|
||||||
- Cheque
|
|
||||||
*/
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop"
|
"github.com/nspcc-dev/neo-go/pkg/interop"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
|
||||||
|
@ -129,7 +98,8 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("neofs: contract initialized")
|
runtime.Log("neofs: contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate updates smart contract execution script and manifest.
|
// Migrate method updates contract source code and manifest. Can be invoked
|
||||||
|
// only by contract owner.
|
||||||
func Migrate(script []byte, manifest []byte, data interface{}) bool {
|
func Migrate(script []byte, manifest []byte, data interface{}) bool {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -144,25 +114,31 @@ func Migrate(script []byte, manifest []byte, data interface{}) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlphabetList returns array of alphabet node keys.
|
// AlphabetList returns array of alphabet node keys. Use in side chain notary
|
||||||
|
// disabled environment.
|
||||||
func AlphabetList() []common.IRNode {
|
func AlphabetList() []common.IRNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return getNodes(ctx, alphabetKey)
|
return getNodes(ctx, alphabetKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlphabetAddress returns 2\3n+1 multi signature address of alphabet nodes.
|
// AlphabetAddress returns 2\3n+1 multi signature address of alphabet nodes.
|
||||||
|
// Used in side chain notary disabled environment.
|
||||||
func AlphabetAddress() interop.Hash160 {
|
func AlphabetAddress() interop.Hash160 {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return multiaddress(getNodes(ctx, alphabetKey))
|
return multiaddress(getNodes(ctx, alphabetKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingCandidates returns array of inner ring candidate node keys.
|
// InnerRingCandidates returns array of structures that contain Inner Ring
|
||||||
|
// candidate node key.
|
||||||
func InnerRingCandidates() []common.IRNode {
|
func InnerRingCandidates() []common.IRNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return getNodes(ctx, candidatesKey)
|
return getNodes(ctx, candidatesKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingCandidateRemove removes key from the list of inner ring candidates.
|
// InnerRingCandidateRemove removes key from the list of Inner Ring candidates.
|
||||||
|
// Can be invoked by Alphabet nodes or candidate itself.
|
||||||
|
//
|
||||||
|
// Method does not return fee back to the candidate.
|
||||||
func InnerRingCandidateRemove(key interop.PublicKey) {
|
func InnerRingCandidateRemove(key interop.PublicKey) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -217,7 +193,11 @@ func InnerRingCandidateRemove(key interop.PublicKey) {
|
||||||
common.SetSerialized(ctx, candidatesKey, nodes)
|
common.SetSerialized(ctx, candidatesKey, nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingCandidateAdd adds key to the list of inner ring candidates.
|
// InnerRingCandidateAdd adds key to the list of Inner Ring candidates.
|
||||||
|
// Can be invoked only by candidate itself.
|
||||||
|
//
|
||||||
|
// This method transfers fee from candidate to contract account.
|
||||||
|
// Fee value specified in NeoFS network config with the key InnerRingCandidateFee.
|
||||||
func InnerRingCandidateAdd(key interop.PublicKey) {
|
func InnerRingCandidateAdd(key interop.PublicKey) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
|
@ -247,6 +227,9 @@ func InnerRingCandidateAdd(key interop.PublicKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
|
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
|
||||||
|
// It takes no more than 9000.0 GAS. Native GAS has precision 8 and
|
||||||
|
// NeoFS balance contract has precision 12. Values bigger than 9000.0 can
|
||||||
|
// break JSON limits for integers when precision is converted.
|
||||||
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
||||||
rcv := data.(interop.Hash160)
|
rcv := data.(interop.Hash160)
|
||||||
if common.BytesEqual(rcv, []byte(ignoreDepositNotification)) {
|
if common.BytesEqual(rcv, []byte(ignoreDepositNotification)) {
|
||||||
|
@ -278,7 +261,13 @@ func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
||||||
runtime.Notify("Deposit", from, amount, rcv, tx.Hash)
|
runtime.Notify("Deposit", from, amount, rcv, tx.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Withdraw initialize gas asset withdraw from NeoFS balance.
|
// Withdraw initialize gas asset withdraw from NeoFS. Can be invoked only
|
||||||
|
// by the specified user.
|
||||||
|
//
|
||||||
|
// This method produces Withdraw notification to lock assets in side chain and
|
||||||
|
// transfers withdraw fee from user account to each Alphabet node. If notary
|
||||||
|
// is enabled in main chain, fee is transferred to Processing contract.
|
||||||
|
// Fee value specified in NeoFS network config with the key WithdrawFee.
|
||||||
func Withdraw(user interop.Hash160, amount int) {
|
func Withdraw(user interop.Hash160, amount int) {
|
||||||
if !runtime.CheckWitness(user) {
|
if !runtime.CheckWitness(user) {
|
||||||
panic("withdraw: you should be the owner of the wallet")
|
panic("withdraw: you should be the owner of the wallet")
|
||||||
|
@ -324,8 +313,11 @@ func Withdraw(user interop.Hash160, amount int) {
|
||||||
runtime.Notify("Withdraw", user, amount, tx.Hash)
|
runtime.Notify("Withdraw", user, amount, tx.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cheque sends gas assets back to the user if they were successfully
|
// Cheque transfers GAS back to the user from contract account, if assets were
|
||||||
// locked in NeoFS balance contract.
|
// successfully locked in NeoFS balance contract. Can be invoked only by
|
||||||
|
// Alphabet nodes.
|
||||||
|
//
|
||||||
|
// This method produces Cheque notification to burn assets in side chain.
|
||||||
func Cheque(id []byte, user interop.Hash160, amount int, lockAcc []byte) {
|
func Cheque(id []byte, user interop.Hash160, amount int, lockAcc []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -370,7 +362,11 @@ func Cheque(id []byte, user interop.Hash160, amount int, lockAcc []byte) {
|
||||||
runtime.Notify("Cheque", id, user, amount, lockAcc)
|
runtime.Notify("Cheque", id, user, amount, lockAcc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bind public key with user's account to use it in NeoFS requests.
|
// Bind method produces notification to bind specified public keys in NeoFSID
|
||||||
|
// contract in side chain. Can be invoked only by specified user.
|
||||||
|
//
|
||||||
|
// This method produces Bind notification. Method panics if keys are not
|
||||||
|
// 33 byte long. User argument must be valid 20 byte script hash.
|
||||||
func Bind(user []byte, keys []interop.PublicKey) {
|
func Bind(user []byte, keys []interop.PublicKey) {
|
||||||
if !runtime.CheckWitness(user) {
|
if !runtime.CheckWitness(user) {
|
||||||
panic("binding: you should be the owner of the wallet")
|
panic("binding: you should be the owner of the wallet")
|
||||||
|
@ -386,7 +382,11 @@ func Bind(user []byte, keys []interop.PublicKey) {
|
||||||
runtime.Notify("Bind", user, keys)
|
runtime.Notify("Bind", user, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unbind public key from user's account
|
// Unbind method produces notification to unbind specified public keys in NeoFSID
|
||||||
|
// contract in side chain. Can be invoked only by specified user.
|
||||||
|
//
|
||||||
|
// This method produces Unbind notification. Method panics if keys are not
|
||||||
|
// 33 byte long. User argument must be valid 20 byte script hash.
|
||||||
func Unbind(user []byte, keys []interop.PublicKey) {
|
func Unbind(user []byte, keys []interop.PublicKey) {
|
||||||
if !runtime.CheckWitness(user) {
|
if !runtime.CheckWitness(user) {
|
||||||
panic("unbinding: you should be the owner of the wallet")
|
panic("unbinding: you should be the owner of the wallet")
|
||||||
|
@ -403,7 +403,10 @@ func Unbind(user []byte, keys []interop.PublicKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlphabetUpdate updates list of alphabet nodes with provided list of
|
// AlphabetUpdate updates list of alphabet nodes with provided list of
|
||||||
// public keys.
|
// public keys. Can be invoked only by alphabet nodes.
|
||||||
|
//
|
||||||
|
// This method used in notary disabled side chain environment. In this case
|
||||||
|
// actual alphabet list should be stored in the NeoFS contract.
|
||||||
func AlphabetUpdate(id []byte, args []interop.PublicKey) {
|
func AlphabetUpdate(id []byte, args []interop.PublicKey) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -460,13 +463,15 @@ func AlphabetUpdate(id []byte, args []interop.PublicKey) {
|
||||||
runtime.Log("alphabetUpdate: alphabet list has been updated")
|
runtime.Log("alphabetUpdate: alphabet list has been updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config returns value of NeoFS configuration with provided key.
|
// Config returns configuration value of NeoFS configuration. If key does
|
||||||
|
// not exists, returns nil.
|
||||||
func Config(key []byte) interface{} {
|
func Config(key []byte) interface{} {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return getConfig(ctx, key)
|
return getConfig(ctx, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig key-value pair as a NeoFS runtime configuration value.
|
// SetConfig key-value pair as a NeoFS runtime configuration value. Can be invoked
|
||||||
|
// only by Alphabet nodes.
|
||||||
func SetConfig(id, key, val []byte) {
|
func SetConfig(id, key, val []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -506,7 +511,8 @@ func SetConfig(id, key, val []byte) {
|
||||||
runtime.Log("setConfig: configuration has been updated")
|
runtime.Log("setConfig: configuration has been updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListConfig returns array of all key-value pairs of NeoFS configuration.
|
// ListConfig returns array of structures that contain key and value of all
|
||||||
|
// NeoFS configuration records. Key and value are both byte arrays.
|
||||||
func ListConfig() []record {
|
func ListConfig() []record {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -525,7 +531,11 @@ func ListConfig() []record {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitConfig set up initial NeoFS key-value configuration.
|
// InitConfig method sets up initial key-value configuration pair. Can be invoked
|
||||||
|
// only once.
|
||||||
|
//
|
||||||
|
// Arguments should contain even number of byte arrays. First byte array is a
|
||||||
|
// configuration key and the second is configuration value.
|
||||||
func InitConfig(args [][]byte) {
|
func InitConfig(args [][]byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
|
@ -548,7 +558,7 @@ func InitConfig(args [][]byte) {
|
||||||
runtime.Log("neofs: config has been installed")
|
runtime.Log("neofs: config has been installed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version of contract.
|
// Version returns version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return version
|
return version
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue