forked from TrueCloudLab/frostfs-contract
[#240] English Check
Signed-off-by: Elizaveta Chichindaeva <elizaveta@nspcc.ru>
This commit is contained in:
parent
c75315808b
commit
335b04d9a6
30 changed files with 425 additions and 425 deletions
10
README.md
10
README.md
|
@ -11,14 +11,14 @@
|
||||||
|
|
||||||
NeoFS-Contract contains all NeoFS related contracts written for
|
NeoFS-Contract contains all NeoFS related contracts written for
|
||||||
[neo-go](https://github.com/nspcc-dev/neo-go) compiler. These contracts
|
[neo-go](https://github.com/nspcc-dev/neo-go) compiler. These contracts
|
||||||
are deployed both in main chain and side chain.
|
are deployed both in the mainchain and the sidechain.
|
||||||
|
|
||||||
Main chain contracts:
|
Mainchain contracts:
|
||||||
|
|
||||||
- neofs
|
- neofs
|
||||||
- processing
|
- processing
|
||||||
|
|
||||||
Side chain contracts:
|
Sidechain contracts:
|
||||||
|
|
||||||
- alphabet
|
- alphabet
|
||||||
- audit
|
- audit
|
||||||
|
@ -41,7 +41,7 @@ To compile smart contracts you need:
|
||||||
|
|
||||||
## Compilation
|
## Compilation
|
||||||
|
|
||||||
To build and compile smart contract run `make all` command. Compiled contracts
|
To build and compile smart contract, run `make all` command. Compiled contracts
|
||||||
`*_contract.nef` and manifest `config.json` files are placed in the
|
`*_contract.nef` and manifest `config.json` files are placed in the
|
||||||
corresponding directories.
|
corresponding directories.
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ Remove compiled files with `make clean` or `make mr_proper` command.
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
Smartcontract tests reside in `tests/` directory. To execute test suite
|
Smartcontract tests reside in `tests/` directory. To execute test suite
|
||||||
after applying changes simply run `make test`.
|
after applying changes, simply run `make test`.
|
||||||
```
|
```
|
||||||
$ make test
|
$ make test
|
||||||
ok github.com/nspcc-dev/neofs-contract/tests 0.462s
|
ok github.com/nspcc-dev/neofs-contract/tests 0.462s
|
||||||
|
|
|
@ -69,7 +69,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log(args.name + " contract initialized")
|
runtime.Log(args.name + " contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -81,12 +81,12 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("alphabet contract updated")
|
runtime.Log("alphabet contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GAS returns amount of side chain GAS stored in contract account.
|
// GAS returns the amount of the sidechain GAS stored in the contract account.
|
||||||
func Gas() int {
|
func Gas() int {
|
||||||
return gas.BalanceOf(runtime.GetExecutingScriptHash())
|
return gas.BalanceOf(runtime.GetExecutingScriptHash())
|
||||||
}
|
}
|
||||||
|
|
||||||
// NEO returns amount of side chain NEO stored in contract account.
|
// NEO returns the amount of sidechain NEO stored in the contract account.
|
||||||
func Neo() int {
|
func Neo() int {
|
||||||
return neo.BalanceOf(runtime.GetExecutingScriptHash())
|
return neo.BalanceOf(runtime.GetExecutingScriptHash())
|
||||||
}
|
}
|
||||||
|
@ -116,16 +116,16 @@ func checkPermission(ir []interop.PublicKey) bool {
|
||||||
return runtime.CheckWitness(node)
|
return runtime.CheckWitness(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit method produces side chain GAS and distributes it among Inner Ring nodes
|
// Emit method produces sidechain GAS and distributes it among Inner Ring nodes
|
||||||
// and proxy contract. Can be invoked only by Alphabet node of the Inner Ring.
|
// and proxy contract. It can be invoked only by an Alphabet node of the Inner Ring.
|
||||||
//
|
//
|
||||||
// To produce GAS, alphabet contract transfers all available NEO from contract
|
// To produce GAS, an alphabet contract transfers all available NEO from the contract
|
||||||
// account to itself. If notary enabled, then 50% of the GAS in the contract account
|
// account to itself. If notary is enabled, 50% of the GAS in the contract account
|
||||||
// transferred to proxy contract. 43.75% of the GAS are equally distributed
|
// are transferred to proxy contract. 43.75% of the GAS are equally distributed
|
||||||
// among all Inner Ring nodes. Remaining 6.25% of the GAS stays in the contract.
|
// among all Inner Ring nodes. Remaining 6.25% of the GAS stay in the contract.
|
||||||
//
|
//
|
||||||
// If notary disabled, then 87.5% of the GAS are equally distributed among all
|
// If notary is disabled, 87.5% of the GAS are equally distributed among all
|
||||||
// Inner Ring nodes. Remaining 12.5% of the GAS stays in the contract.
|
// Inner Ring nodes. Remaining 12.5% of the GAS stay in the contract.
|
||||||
func Emit() {
|
func Emit() {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -183,13 +183,13 @@ func Emit() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vote method votes for side chain committee. Requires multisignature from
|
// Vote method votes for the sidechain committee. It requires multisignature from
|
||||||
// Alphabet nodes of the Inner Ring.
|
// Alphabet nodes of the Inner Ring.
|
||||||
//
|
//
|
||||||
// This method is used when governance changes list of Alphabet nodes of the
|
// This method is used when governance changes the list of Alphabet nodes of the
|
||||||
// Inner Ring. Alphabet nodes share keys with side chain validators, therefore
|
// Inner Ring. Alphabet nodes share keys with sidechain validators, therefore
|
||||||
// it is required to change them as well. To do that NEO holders, which are
|
// it is required to change them as well. To do that, NEO holders (which are
|
||||||
// alphabet contracts, should vote for new committee.
|
// alphabet contracts) should vote for a new committee.
|
||||||
func Vote(epoch int, candidates []interop.PublicKey) {
|
func Vote(epoch int, candidates []interop.PublicKey) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -255,13 +255,13 @@ func voteID(epoch interface{}, args []interop.PublicKey) []byte {
|
||||||
return crypto.Sha256(result)
|
return crypto.Sha256(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns Glagolitic name of the contract.
|
// Name returns the Glagolitic name of the contract.
|
||||||
func Name() string {
|
func Name() string {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return name(ctx)
|
return name(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
/*
|
/*
|
||||||
Alphabet contract is a contract deployed in NeoFS side chain.
|
Alphabet contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Alphabet contract is designed to support GAS producing and voting for new
|
Alphabet contract is designed to support GAS production and vote for new
|
||||||
validators in the side chain. NEO token is required to produce GAS and vote for
|
validators in the sidechain. NEO token is required to produce GAS and vote for
|
||||||
a new committee. If can be distributed among alphabet nodes of Inner Ring.
|
a new committee. It can be distributed among alphabet nodes of the Inner Ring.
|
||||||
However, some of them may be malicious and some NEO can be lost. It will lead
|
However, some of them may be malicious, and some NEO can be lost. It will destabilize
|
||||||
to side chain economic destabilization. To avoid it, all 100 000 000 NEO are
|
the economic of the sidechain. To avoid it, all 100,000,000 NEO are
|
||||||
distributed among all alphabet contracts.
|
distributed among all alphabet contracts.
|
||||||
|
|
||||||
To identify alphabet contracts, they are named with letters of the Glagolitic.
|
To identify alphabet contracts, they are named with letters of the Glagolitic alphabet.
|
||||||
Names are set at contract deploy. Alphabet nodes of Inner Ring communicate with
|
Names are set at contract deploy. Alphabet nodes of the Inner Ring communicate with
|
||||||
one of the alphabetical contracts to emit GAS. To vote for a new list of side
|
one of the alphabetical contracts to emit GAS. To vote for a new list of side
|
||||||
chain committee, alphabet nodes of Inner Ring create multisignature transactions
|
chain committee, alphabet nodes of the Inner Ring create multisignature transactions
|
||||||
for each alphabet contract.
|
for each alphabet contract.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
|
@ -19,8 +19,8 @@ type (
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Audit key is a combination of epoch, container ID and public key of node that
|
// Audit key is a combination of the epoch, the container ID and the public key of the node that
|
||||||
// executed audit. Together it should be no more than 64 bytes. We can't shrink
|
// has executed the audit. Together, it shouldn't be more than 64 bytes. We can't shrink
|
||||||
// epoch and container ID since we iterate over these values. But we can shrink
|
// epoch and container ID since we iterate over these values. But we can shrink
|
||||||
// public key by using first bytes of the hashed value.
|
// public key by using first bytes of the hashed value.
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("audit contract initialized")
|
runtime.Log("audit contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -82,11 +82,11 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("audit contract updated")
|
runtime.Log("audit contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put method stores stable marshalled `DataAuditResult` structure. Can be
|
// Put method stores a stable marshalled `DataAuditResult` structure. It can be
|
||||||
// invoked only by Inner Ring nodes.
|
// invoked only by Inner Ring nodes.
|
||||||
//
|
//
|
||||||
// Inner Ring nodes perform audit of the containers and produce `DataAuditResult`
|
// Inner Ring nodes perform audit of containers and produce `DataAuditResult`
|
||||||
// structures. They are being stored in audit contract and used for settlements
|
// structures. They are stored in audit contract and used for settlements
|
||||||
// in later epochs.
|
// in later epochs.
|
||||||
func Put(rawAuditResult []byte) {
|
func Put(rawAuditResult []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
@ -122,16 +122,16 @@ func Put(rawAuditResult []byte) {
|
||||||
runtime.Log("audit: result has been saved")
|
runtime.Log("audit: result has been saved")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get method returns stable marshaled DataAuditResult structure.
|
// Get method returns a stable marshaled DataAuditResult structure.
|
||||||
//
|
//
|
||||||
// ID of the DataAuditResult can be obtained from listing methods.
|
// The ID of the DataAuditResult can be obtained from listing methods.
|
||||||
func Get(id []byte) []byte {
|
func Get(id []byte) []byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return storage.Get(ctx, id).([]byte)
|
return storage.Get(ctx, id).([]byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List method returns list of all available DataAuditResult IDs from
|
// List method returns a list of all available DataAuditResult IDs from
|
||||||
// contract storage.
|
// the contract storage.
|
||||||
func List() [][]byte {
|
func List() [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
it := storage.Find(ctx, []byte{}, storage.KeysOnly)
|
it := storage.Find(ctx, []byte{}, storage.KeysOnly)
|
||||||
|
@ -139,8 +139,8 @@ func List() [][]byte {
|
||||||
return list(it)
|
return list(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListByEpoch method returns list of DataAuditResult IDs generated in
|
// ListByEpoch method returns a list of DataAuditResult IDs generated during
|
||||||
// specified epoch.
|
// the specified epoch.
|
||||||
func ListByEpoch(epoch int) [][]byte {
|
func ListByEpoch(epoch int) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
var buf interface{} = epoch
|
var buf interface{} = epoch
|
||||||
|
@ -149,8 +149,8 @@ func ListByEpoch(epoch int) [][]byte {
|
||||||
return list(it)
|
return list(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListByCID method returns list of DataAuditResult IDs generated in
|
// ListByCID method returns a list of DataAuditResult IDs generated during
|
||||||
// specified epoch for specified container.
|
// the specified epoch for the specified container.
|
||||||
func ListByCID(epoch int, cid []byte) [][]byte {
|
func ListByCID(epoch int, cid []byte) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -162,8 +162,8 @@ func ListByCID(epoch int, cid []byte) [][]byte {
|
||||||
return list(it)
|
return list(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListByNode method returns list of DataAuditResult IDs generated in
|
// ListByNode method returns a list of DataAuditResult IDs generated in
|
||||||
// specified epoch for specified container by specified Inner Ring node.
|
// the specified epoch for the specified container by the specified Inner Ring node.
|
||||||
func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte {
|
func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
hdr := auditHeader{
|
hdr := auditHeader{
|
||||||
|
@ -200,12 +200,12 @@ loop:
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
// readNext reads length from first byte and then reads data (max 127 bytes).
|
// readNext reads the length from the first byte, and then reads data (max 127 bytes).
|
||||||
func readNext(input []byte) ([]byte, int) {
|
func readNext(input []byte) ([]byte, int) {
|
||||||
var buf interface{} = input[0]
|
var buf interface{} = input[0]
|
||||||
ln := buf.(int)
|
ln := buf.(int)
|
||||||
|
|
18
audit/doc.go
18
audit/doc.go
|
@ -1,22 +1,22 @@
|
||||||
/*
|
/*
|
||||||
Audit contract is a contract deployed in NeoFS side chain.
|
Audit contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Inner Ring nodes perform an audit of the registered containers in every epoch.
|
Inner Ring nodes perform audit of the registered containers during every epoch.
|
||||||
If container contains StorageGroup objects, then the Inner Ring node initializes
|
If a container contains StorageGroup objects, an Inner Ring node initializes
|
||||||
a series of audit checks. Based on the results of these checks, the Inner Ring
|
a series of audit checks. Based on the results of these checks, the Inner Ring
|
||||||
node creates a DataAuditResult structure for the container. The content of this
|
node creates a DataAuditResult structure for the container. The content of this
|
||||||
structure makes it possible to determine which storage nodes were examined and
|
structure makes it possible to determine which storage nodes have been examined and
|
||||||
the status of these checks. Based on this information, container owner is
|
see the status of these checks. Regarding this information, the container owner is
|
||||||
charged for data storage.
|
charged for data storage.
|
||||||
|
|
||||||
Audit contract is used as reliable and verifiable storage for all
|
Audit contract is used as a reliable and verifiable storage for all
|
||||||
DataAuditResult structures. At the end of the data audit routine, the Inner Ring
|
DataAuditResult structures. At the end of data audit routine, Inner Ring
|
||||||
nodes send a stable marshaled version of the DataAuditResult structure to the
|
nodes send a stable marshaled version of the DataAuditResult structure to the
|
||||||
contract. When Alphabet nodes of the Inner Ring perform settlement operations,
|
contract. When Alphabet nodes of the Inner Ring perform settlement operations,
|
||||||
they list and get these AuditResultStructures from the audit contract.
|
they make a list and get these AuditResultStructures from the audit contract.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
Alphabet contract does not produce notifications to process.
|
Audit contract does not produce notifications to process.
|
||||||
*/
|
*/
|
||||||
package audit
|
package audit
|
||||||
|
|
|
@ -24,7 +24,7 @@ type (
|
||||||
|
|
||||||
// Account structure stores metadata of each NeoFS balance account.
|
// Account structure stores metadata of each NeoFS balance account.
|
||||||
Account struct {
|
Account struct {
|
||||||
// Active balance
|
// Active balance
|
||||||
Balance int
|
Balance int
|
||||||
// Until valid for lock accounts
|
// Until valid for lock accounts
|
||||||
Until int
|
Until int
|
||||||
|
@ -89,7 +89,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("balance contract initialized")
|
runtime.Log("balance contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -113,13 +113,13 @@ func Decimals() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalSupply is a NEP-17 standard method that returns total amount of main
|
// TotalSupply is a NEP-17 standard method that returns total amount of main
|
||||||
// chain GAS in the NeoFS network.
|
// chain GAS in NeoFS network.
|
||||||
func TotalSupply() int {
|
func TotalSupply() int {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return token.getSupply(ctx)
|
return token.getSupply(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BalanceOf is a NEP-17 standard method that returns NeoFS balance of specified
|
// BalanceOf is a NEP-17 standard method that returns NeoFS balance of the specified
|
||||||
// account.
|
// account.
|
||||||
func BalanceOf(account interop.Hash160) int {
|
func BalanceOf(account interop.Hash160) int {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
@ -127,23 +127,23 @@ func BalanceOf(account interop.Hash160) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer is a NEP-17 standard method that transfers NeoFS balance from one
|
// Transfer is a NEP-17 standard method that transfers NeoFS balance from one
|
||||||
// account to other. Can be invoked only by account owner.
|
// account to another. It can be invoked only by the account owner.
|
||||||
//
|
//
|
||||||
// Produces Transfer and TransferX notifications. TransferX notification
|
// It produces Transfer and TransferX notifications. TransferX notification
|
||||||
// will have empty details field.
|
// will have empty details field.
|
||||||
func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
|
func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
return token.transfer(ctx, from, to, amount, false, nil)
|
return token.transfer(ctx, from, to, amount, false, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransferX is a method for NeoFS balance transfers from one account to
|
// TransferX is a method for NeoFS balance to be transferred from one account to
|
||||||
// another. Can be invoked by account owner or by Alphabet nodes.
|
// another. It can be invoked by the account owner or by Alphabet nodes.
|
||||||
//
|
//
|
||||||
// Produces Transfer and TransferX notifications.
|
// It produces Transfer and TransferX notifications.
|
||||||
//
|
//
|
||||||
// TransferX method expands Transfer method by having extra details argument.
|
// TransferX method expands Transfer method by having extra details argument.
|
||||||
// Also TransferX method allows to transfer assets by Alphabet nodes of the
|
// TransferX method also allows to transfer assets by Alphabet nodes of the
|
||||||
// Inner Ring with multi signature.
|
// Inner Ring with multisignature.
|
||||||
func TransferX(from, to interop.Hash160, amount int, details []byte) {
|
func TransferX(from, to interop.Hash160, amount int, details []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -191,14 +191,14 @@ func TransferX(from, to interop.Hash160, amount int, details []byte) {
|
||||||
runtime.Log("successfully transferred assets")
|
runtime.Log("successfully transferred assets")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock is a method that transfers assets from user account to lock account
|
// Lock is a method that transfers assets from a user account to the lock account
|
||||||
// related to the user. Can be invoked only by Alphabet nodes of the Inner Ring.
|
// related to the user. It can be invoked only by Alphabet nodes of the Inner Ring.
|
||||||
//
|
//
|
||||||
// Produces Lock, Transfer and TransferX notifications.
|
// It produces Lock, Transfer and TransferX notifications.
|
||||||
//
|
//
|
||||||
// Lock method invoked by Alphabet nodes of the Inner Ring when they process
|
// Lock method is invoked by Alphabet nodes of the Inner Ring when they process
|
||||||
// Withdraw notification from NeoFS contract. This should transfer assets
|
// Withdraw notification from NeoFS contract. This should transfer assets
|
||||||
// to new lock account that won't be used for anything besides Unlock and Burn.
|
// to a new lock account that won't be used for anything beside Unlock and Burn.
|
||||||
func Lock(txDetails []byte, from, to interop.Hash160, amount, until int) {
|
func Lock(txDetails []byte, from, to interop.Hash160, amount, until int) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -251,11 +251,11 @@ func Lock(txDetails []byte, from, to interop.Hash160, amount, until int) {
|
||||||
runtime.Notify("Lock", txDetails, from, to, amount, until)
|
runtime.Notify("Lock", txDetails, from, to, amount, until)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEpoch is a method that checks timeout on lock accounts and return assets
|
// NewEpoch is a method that checks timeout on lock accounts and returns assets
|
||||||
// if lock is not available anymore. Can be invoked only by NewEpoch method
|
// if lock is not available anymore. It can be invoked only by NewEpoch method
|
||||||
// of Netmap contract.
|
// of Netmap contract.
|
||||||
//
|
//
|
||||||
// Produces Transfer and TransferX notifications.
|
// It produces Transfer and TransferX notifications.
|
||||||
func NewEpoch(epochNum int) {
|
func NewEpoch(epochNum int) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -294,14 +294,14 @@ func NewEpoch(epochNum int) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mint is a method that transfers assets to user account from empty account.
|
// Mint is a method that transfers assets to a user account from an empty account.
|
||||||
// Can be invoked only by Alphabet nodes of the Inner Ring.
|
// It can be invoked only by Alphabet nodes of the Inner Ring.
|
||||||
//
|
//
|
||||||
// Produces Mint, Transfer and TransferX notifications.
|
// It produces Mint, Transfer and TransferX notifications.
|
||||||
//
|
//
|
||||||
// Mint method invoked by Alphabet nodes of the Inner Ring when they process
|
// Mint method is invoked by Alphabet nodes of the Inner Ring when they process
|
||||||
// Deposit notification from NeoFS contract. Before that Alphabet nodes should
|
// Deposit notification from NeoFS contract. Before that, Alphabet nodes should
|
||||||
// synchronize precision of main chain GAS contract and Balance contract.
|
// synchronize precision of mainchain GAS contract and Balance contract.
|
||||||
// Mint increases total supply of NEP-17 compatible NeoFS token.
|
// Mint increases total supply of NEP-17 compatible NeoFS token.
|
||||||
func Mint(to interop.Hash160, amount int, txDetails []byte) {
|
func Mint(to interop.Hash160, amount int, txDetails []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
@ -349,15 +349,15 @@ func Mint(to interop.Hash160, amount int, txDetails []byte) {
|
||||||
runtime.Notify("Mint", to, amount)
|
runtime.Notify("Mint", to, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Burn is a method that transfers assets from user account to empty account.
|
// Burn is a method that transfers assets from a user account to an empty account.
|
||||||
// Can be invoked only by Alphabet nodes of the Inner Ring.
|
// It can be invoked only by Alphabet nodes of the Inner Ring.
|
||||||
//
|
//
|
||||||
// Produces Burn, Transfer and TransferX notifications.
|
// It produces Burn, Transfer and TransferX notifications.
|
||||||
//
|
//
|
||||||
// Burn method invoked by Alphabet nodes of the Inner Ring when they process
|
// Burn method is invoked by Alphabet nodes of the Inner Ring when they process
|
||||||
// Cheque notification from NeoFS contract. It means that locked assets were
|
// Cheque notification from NeoFS contract. It means that locked assets have been
|
||||||
// transferred to user in main chain, therefore lock account should be destroyed.
|
// transferred to the user in the mainchain, therefore the lock account should be destroyed.
|
||||||
// Before that Alphabet nodes should synchronize precision of main chain GAS
|
// Before that, Alphabet nodes should synchronize precision of mainchain GAS
|
||||||
// contract and Balance contract. Burn decreases total supply of NEP-17
|
// contract and Balance contract. Burn decreases total supply of NEP-17
|
||||||
// compatible NeoFS token.
|
// compatible NeoFS token.
|
||||||
func Burn(from interop.Hash160, amount int, txDetails []byte) {
|
func Burn(from interop.Hash160, amount int, txDetails []byte) {
|
||||||
|
@ -410,7 +410,7 @@ func Burn(from interop.Hash160, amount int, txDetails []byte) {
|
||||||
runtime.Notify("Burn", from, amount)
|
runtime.Notify("Burn", from, amount)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
@ -484,7 +484,7 @@ func (t Token) canTransfer(ctx storage.Context, from, to interop.Hash160, amount
|
||||||
return amountFrom, true
|
return amountFrom, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// isUsableAddress checks if the sender is either the correct NEO address or SC address.
|
// isUsableAddress checks if the sender is either a correct NEO address or SC address.
|
||||||
func isUsableAddress(addr interop.Hash160) bool {
|
func isUsableAddress(addr interop.Hash160) bool {
|
||||||
if len(addr) == 20 {
|
if len(addr) == 20 {
|
||||||
if runtime.CheckWitness(addr) {
|
if runtime.CheckWitness(addr) {
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
/*
|
/*
|
||||||
Balance contract is a contract deployed in NeoFS side chain.
|
Balance contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Balance contract stores all NeoFS account balances. It is NEP-17 compatible
|
Balance contract stores all NeoFS account balances. It is a NEP-17 compatible
|
||||||
contract so in can be tracked and controlled by N3 compatible network
|
contract, so it can be tracked and controlled by N3 compatible network
|
||||||
monitors and wallet software.
|
monitors and wallet software.
|
||||||
|
|
||||||
This contract is used to store all micro transactions in the sidechain, such as
|
This contract is used to store all micro transactions in the sidechain, such as
|
||||||
data audit settlements or container fee payments. It is inefficient to make such
|
data audit settlements or container fee payments. It is inefficient to make such
|
||||||
small payment transactions in main chain. To process small transfers, balance
|
small payment transactions in the mainchain. To process small transfers, balance
|
||||||
contract has higher (12) decimal precision than native GAS contract.
|
contract has higher (12) decimal precision than native GAS contract.
|
||||||
|
|
||||||
NeoFS balances are synchronized with main chain operations. Deposit produce
|
NeoFS balances are synchronized with mainchain operations. Deposit produces
|
||||||
minting of NEOFS tokens in Balance contract. Withdraw locks some NEOFS tokens
|
minting of NEOFS tokens in Balance contract. Withdraw locks some NEOFS tokens
|
||||||
in special lock account. When NeoFS contract transfers GAS assets back to the
|
in a special lock account. When NeoFS contract transfers GAS assets back to the
|
||||||
user, lock account is destroyed with burn operation.
|
user, the lock account is destroyed with burn operation.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
Transfer notification. This is NEP-17 standard notification.
|
Transfer notification. This is a NEP-17 standard notification.
|
||||||
|
|
||||||
Transfer:
|
Transfer:
|
||||||
- name: from
|
- name: from
|
||||||
|
@ -27,7 +27,7 @@ Transfer notification. This is NEP-17 standard notification.
|
||||||
- name: amount
|
- name: amount
|
||||||
type: Integer
|
type: Integer
|
||||||
|
|
||||||
TransferX notification. This is enhanced transfer notification with details.
|
TransferX notification. This is an enhanced transfer notification with details.
|
||||||
|
|
||||||
TransferX:
|
TransferX:
|
||||||
- name: from
|
- name: from
|
||||||
|
@ -39,11 +39,11 @@ TransferX notification. This is enhanced transfer notification with details.
|
||||||
- name: details
|
- name: details
|
||||||
type: ByteArray
|
type: ByteArray
|
||||||
|
|
||||||
Lock notification. This notification is produced when Lock account has been
|
Lock notification. This notification is produced when a lock account is
|
||||||
created. It contains information about main chain transaction that produced
|
created. It contains information about the mainchain transaction that has produced
|
||||||
asset lock, address of lock account and NeoFS epoch number until lock account
|
the asset lock, the address of the lock account and the NeoFS epoch number until which the
|
||||||
is valid. Alphabet nodes of the Inner Ring catch notification and initialize
|
lock account is valid. Alphabet nodes of the Inner Ring catch notification and initialize
|
||||||
Cheque method invocation of the NeoFS contract.
|
Cheque method invocation of NeoFS contract.
|
||||||
|
|
||||||
Lock:
|
Lock:
|
||||||
- name: txID
|
- name: txID
|
||||||
|
@ -58,7 +58,7 @@ Cheque method invocation of the NeoFS contract.
|
||||||
type: Integer
|
type: Integer
|
||||||
|
|
||||||
Mint notification. This notification is produced when user balance is
|
Mint notification. This notification is produced when user balance is
|
||||||
replenished from deposit in the main chain.
|
replenished from deposit in the mainchain.
|
||||||
|
|
||||||
Mint:
|
Mint:
|
||||||
- name: to
|
- name: to
|
||||||
|
@ -68,7 +68,7 @@ replenished from deposit in the main chain.
|
||||||
|
|
||||||
|
|
||||||
Burn notification. This notification is produced after user balance is reduced
|
Burn notification. This notification is produced after user balance is reduced
|
||||||
when NeoFS contract transferred GAS assets back to the user.
|
when NeoFS contract has transferred GAS assets back to the user.
|
||||||
|
|
||||||
Burn:
|
Burn:
|
||||||
- name: from
|
- name: from
|
||||||
|
|
14
common/ir.go
14
common/ir.go
|
@ -15,7 +15,7 @@ type IRNode struct {
|
||||||
|
|
||||||
const irListMethod = "innerRingList"
|
const irListMethod = "innerRingList"
|
||||||
|
|
||||||
// InnerRingInvoker returns public key of inner ring node that invoked contract.
|
// InnerRingInvoker returns the public key of the inner ring node that has invoked the contract.
|
||||||
// Work around for environments without notary support.
|
// Work around for environments without notary support.
|
||||||
func InnerRingInvoker(ir []interop.PublicKey) interop.PublicKey {
|
func InnerRingInvoker(ir []interop.PublicKey) interop.PublicKey {
|
||||||
for i := 0; i < len(ir); i++ {
|
for i := 0; i < len(ir); i++ {
|
||||||
|
@ -28,14 +28,14 @@ func InnerRingInvoker(ir []interop.PublicKey) interop.PublicKey {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingNodes return list of inner ring nodes from state validator role
|
// InnerRingNodes return a list of inner ring nodes from state validator role
|
||||||
// in side chain.
|
// in the sidechain.
|
||||||
func InnerRingNodes() []interop.PublicKey {
|
func InnerRingNodes() []interop.PublicKey {
|
||||||
blockHeight := ledger.CurrentIndex()
|
blockHeight := ledger.CurrentIndex()
|
||||||
return roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
return roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingNodesFromNetmap gets list of inner ring through
|
// InnerRingNodesFromNetmap gets a list of inner ring nodes through
|
||||||
// calling "innerRingList" method of smart contract.
|
// calling "innerRingList" method of smart contract.
|
||||||
// Work around for environments without notary support.
|
// Work around for environments without notary support.
|
||||||
func InnerRingNodesFromNetmap(sc interop.Hash160) []interop.PublicKey {
|
func InnerRingNodesFromNetmap(sc interop.Hash160) []interop.PublicKey {
|
||||||
|
@ -47,7 +47,7 @@ func InnerRingNodesFromNetmap(sc interop.Hash160) []interop.PublicKey {
|
||||||
return pubs
|
return pubs
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlphabetNodes return list of alphabet nodes from committee in side chain.
|
// AlphabetNodes returns a list of alphabet nodes from committee in the sidechain.
|
||||||
func AlphabetNodes() []interop.PublicKey {
|
func AlphabetNodes() []interop.PublicKey {
|
||||||
return neo.GetCommittee()
|
return neo.GetCommittee()
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,8 @@ func CommitteeAddress() []byte {
|
||||||
return Multiaddress(committee, true)
|
return Multiaddress(committee, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Multiaddress returns default multi signature account address for N keys.
|
// Multiaddress returns default multisignature account address for N keys.
|
||||||
// If committee set to true, then it is `M = N/2+1` committee account.
|
// If committee set to true, it is `M = N/2+1` committee account.
|
||||||
func Multiaddress(n []interop.PublicKey, committee bool) []byte {
|
func Multiaddress(n []interop.PublicKey, committee bool) []byte {
|
||||||
threshold := len(n)*2/3 + 1
|
threshold := len(n)*2/3 + 1
|
||||||
if committee {
|
if committee {
|
||||||
|
|
|
@ -39,7 +39,7 @@ func ContainerFeeTransferDetails(cid []byte) []byte {
|
||||||
return append(containerFeePrefix, cid...)
|
return append(containerFeePrefix, cid...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AbortWithMessage calls `runtime.Log` with passed message
|
// AbortWithMessage calls `runtime.Log` with the passed message
|
||||||
// and calls `ABORT` opcode.
|
// and calls `ABORT` opcode.
|
||||||
func AbortWithMessage(msg string) {
|
func AbortWithMessage(msg string) {
|
||||||
runtime.Log(msg)
|
runtime.Log(msg)
|
||||||
|
|
|
@ -13,7 +13,7 @@ type Ballot struct {
|
||||||
// ID of the voting decision.
|
// ID of the voting decision.
|
||||||
ID []byte
|
ID []byte
|
||||||
|
|
||||||
// Public keys of already voted inner ring nodes.
|
// Public keys of the already voted inner ring nodes.
|
||||||
Voters []interop.PublicKey
|
Voters []interop.PublicKey
|
||||||
|
|
||||||
// Height of block with the last vote.
|
// Height of block with the last vote.
|
||||||
|
@ -28,8 +28,8 @@ func InitVote(ctx storage.Context) {
|
||||||
SetSerialized(ctx, voteKey, []Ballot{})
|
SetSerialized(ctx, voteKey, []Ballot{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vote adds ballot for the decision with specific 'id' and returns amount
|
// Vote adds ballot for the decision with a specific 'id' and returns the amount
|
||||||
// on unique voters for that decision.
|
// of unique voters for that decision.
|
||||||
func Vote(ctx storage.Context, id, from []byte) int {
|
func Vote(ctx storage.Context, id, from []byte) int {
|
||||||
var (
|
var (
|
||||||
newCandidates []Ballot
|
newCandidates []Ballot
|
||||||
|
@ -96,7 +96,7 @@ func RemoveVotes(ctx storage.Context, id []byte) {
|
||||||
SetSerialized(ctx, voteKey, candidates)
|
SetSerialized(ctx, voteKey, candidates)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getBallots returns deserialized slice of vote ballots.
|
// getBallots returns a deserialized slice of vote ballots.
|
||||||
func getBallots(ctx storage.Context) []Ballot {
|
func getBallots(ctx storage.Context) []Ballot {
|
||||||
data := storage.Get(ctx, voteKey)
|
data := storage.Get(ctx, voteKey)
|
||||||
if data != nil {
|
if data != nil {
|
||||||
|
@ -106,13 +106,13 @@ func getBallots(ctx storage.Context) []Ballot {
|
||||||
return []Ballot{}
|
return []Ballot{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BytesEqual compares two slice of bytes by wrapping them into strings,
|
// BytesEqual compares two slices of bytes by wrapping them into strings,
|
||||||
// which is necessary with new util.Equal interop behaviour, see neo-go#1176.
|
// which is necessary with new util.Equals interop behaviour, see neo-go#1176.
|
||||||
func BytesEqual(a []byte, b []byte) bool {
|
func BytesEqual(a []byte, b []byte) bool {
|
||||||
return util.Equals(string(a), string(b))
|
return util.Equals(string(a), string(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
// InvokeID returns hashed value of prefix and args concatenation. Used to
|
// InvokeID returns hashed value of prefix and args concatenation. Iy is used to
|
||||||
// identify different ballots.
|
// identify different ballots.
|
||||||
func InvokeID(args []interface{}, prefix []byte) []byte {
|
func InvokeID(args []interface{}, prefix []byte) []byte {
|
||||||
for i := range args {
|
for i := range args {
|
||||||
|
@ -124,22 +124,22 @@ func InvokeID(args []interface{}, prefix []byte) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if invocation made from known container or audit contracts.
|
Check if the invocation is made from known container or audit contracts.
|
||||||
This is necessary because calls from these contracts require to do transfer
|
This is necessary because calls from these contracts require to do transfer
|
||||||
without signature collection (1 invoke transfer).
|
without signature collection (1 invoke transfer).
|
||||||
|
|
||||||
IR1, IR2, IR3, IR4 -(4 invokes)-> [ Container Contract ] -(1 invoke)-> [ Balance Contract ]
|
IR1, IR2, IR3, IR4 -(4 invokes)-> [ Container Contract ] -(1 invoke)-> [ Balance Contract ]
|
||||||
|
|
||||||
We can do 1 invoke transfer if:
|
We can do 1 invoke transfer if:
|
||||||
- invoke happened from inner ring node,
|
- invokation has happened from inner ring node,
|
||||||
- it is indirect invocation from other smart-contract.
|
- it is indirect invocation from another smart-contract.
|
||||||
|
|
||||||
However there is a possible attack, when malicious inner ring node creates
|
However, there is a possible attack, when a malicious inner ring node creates
|
||||||
malicious smart-contract in morph chain to do indirect call.
|
a malicious smart-contract in the morph chain to do indirect call.
|
||||||
|
|
||||||
MaliciousIR -(1 invoke)-> [ Malicious Contract ] -(1 invoke) -> [ Balance Contract ]
|
MaliciousIR -(1 invoke)-> [ Malicious Contract ] -(1 invoke)-> [ Balance Contract ]
|
||||||
|
|
||||||
To prevent that, we have to allow 1 invoke transfer from authorised well known
|
To prevent that, we have to allow 1 invoke transfer from authorised well-known
|
||||||
smart-contracts, that will be set up at `Init` method.
|
smart-contracts, that will be set up at `Init` method.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -3,31 +3,31 @@ package common
|
||||||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrAlphabetWitnessFailed appears when method must be
|
// ErrAlphabetWitnessFailed appears when the method must be
|
||||||
// called by Alphabet but was not.
|
// called by the Alphabet but was not.
|
||||||
ErrAlphabetWitnessFailed = "alphabet witness check failed"
|
ErrAlphabetWitnessFailed = "alphabet witness check failed"
|
||||||
// ErrOwnerWitnessFailed appears when method must be called
|
// ErrOwnerWitnessFailed appears when the method must be called
|
||||||
// by owner of some assets but was not.
|
// by an owner of some assets but was not.
|
||||||
ErrOwnerWitnessFailed = "owner witness check failed"
|
ErrOwnerWitnessFailed = "owner witness check failed"
|
||||||
// ErrWitnessFailed appears when method must be called
|
// ErrWitnessFailed appears when the method must be called
|
||||||
// using certain public key but was not.
|
// using certain public key but was not.
|
||||||
ErrWitnessFailed = "witness check failed"
|
ErrWitnessFailed = "witness check failed"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckAlphabetWitness checks witness of the passed caller.
|
// CheckAlphabetWitness checks witness of the passed caller.
|
||||||
// Panics with ErrAlphabetWitnessFailed message on fail.
|
// It panics with ErrAlphabetWitnessFailed message on fail.
|
||||||
func CheckAlphabetWitness(caller []byte) {
|
func CheckAlphabetWitness(caller []byte) {
|
||||||
checkWitnessWithPanic(caller, ErrAlphabetWitnessFailed)
|
checkWitnessWithPanic(caller, ErrAlphabetWitnessFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckOwnerWitness checks witness of the passed caller.
|
// CheckOwnerWitness checks witness of the passed caller.
|
||||||
// Panics with ErrOwnerWitnessFailed message on fail.
|
// It panics with ErrOwnerWitnessFailed message on fail.
|
||||||
func CheckOwnerWitness(caller []byte) {
|
func CheckOwnerWitness(caller []byte) {
|
||||||
checkWitnessWithPanic(caller, ErrOwnerWitnessFailed)
|
checkWitnessWithPanic(caller, ErrOwnerWitnessFailed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckWitness checks witness of the passed caller.
|
// CheckWitness checks witness of the passed caller.
|
||||||
// Panics with ErrWitnessFailed message on fail.
|
// It panics with ErrWitnessFailed message on fail.
|
||||||
func CheckWitness(caller []byte) {
|
func CheckWitness(caller []byte) {
|
||||||
checkWitnessWithPanic(caller, ErrWitnessFailed)
|
checkWitnessWithPanic(caller, ErrWitnessFailed)
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,11 +63,11 @@ const (
|
||||||
singleEstimatePrefix = "est"
|
singleEstimatePrefix = "est"
|
||||||
estimateKeyPrefix = "cnr"
|
estimateKeyPrefix = "cnr"
|
||||||
estimatePostfixSize = 10
|
estimatePostfixSize = 10
|
||||||
// CleanupDelta contains number of last epochs for which container estimations are present.
|
// CleanupDelta contains the number of the last epochs for which container estimations are present.
|
||||||
CleanupDelta = 3
|
CleanupDelta = 3
|
||||||
// TotalCleanupDelta contains number of epochs after which estimation
|
// TotalCleanupDelta contains the number of the epochs after which estimation
|
||||||
// will be removed by epoch tick cleanup if any node didn't updated
|
// will be removed by epoch tick cleanup if any of the nodes hasn't updated
|
||||||
// container size and/or container was removed. Must be greater than CleanupDelta.
|
// container size and/or container has been removed. It must be greater than CleanupDelta.
|
||||||
TotalCleanupDelta = CleanupDelta + 1
|
TotalCleanupDelta = CleanupDelta + 1
|
||||||
|
|
||||||
// NotFoundError is returned if container is missing.
|
// NotFoundError is returned if container is missing.
|
||||||
|
@ -84,7 +84,7 @@ var (
|
||||||
eACLPrefix = []byte("eACL")
|
eACLPrefix = []byte("eACL")
|
||||||
)
|
)
|
||||||
|
|
||||||
// OnNEP11Payment is needed for registration with contract as owner to work.
|
// OnNEP11Payment is needed for registration with contract as the owner to work.
|
||||||
func OnNEP11Payment(a interop.Hash160, b int, c []byte, d interface{}) {
|
func OnNEP11Payment(a interop.Hash160, b int, c []byte, d interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,8 +145,8 @@ func registerNiceNameTLD(addrNNS interop.Hash160, nnsRoot string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// by committee only.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
panic("only committee can update contract")
|
panic("only committee can update contract")
|
||||||
|
@ -157,13 +157,13 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("container contract updated")
|
runtime.Log("container contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put method creates new container if it was invoked by Alphabet nodes
|
// Put method creates a new container if it has been invoked by Alphabet nodes
|
||||||
// of the Inner Ring. Otherwise it produces containerPut notification.
|
// of the Inner Ring. Otherwise, it produces containerPut notification.
|
||||||
//
|
//
|
||||||
// Container should be stable marshaled Container structure from API.
|
// Container should be a stable marshaled Container structure from API.
|
||||||
// Signature is a RFC6979 signature of Container.
|
// Signature is a RFC6979 signature of the Container.
|
||||||
// PublicKey contains public key of the signer.
|
// PublicKey contains the public key of the signer.
|
||||||
// Token is optional and should be stable marshaled SessionToken structure from
|
// Token is optional and should be a stable marshaled SessionToken structure from
|
||||||
// API.
|
// API.
|
||||||
func Put(container []byte, signature interop.Signature, publicKey interop.PublicKey, token []byte) {
|
func Put(container []byte, signature interop.Signature, publicKey interop.PublicKey, token []byte) {
|
||||||
PutNamed(container, signature, publicKey, token, "", "")
|
PutNamed(container, signature, publicKey, token, "", "")
|
||||||
|
@ -279,7 +279,7 @@ func PutNamed(container []byte, signature interop.Signature,
|
||||||
runtime.Notify("PutSuccess", containerID, publicKey)
|
runtime.Notify("PutSuccess", containerID, publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkNiceNameAvailable checks if nice name is available for the container.
|
// checkNiceNameAvailable checks if the nice name is available for the container.
|
||||||
// It panics if the name is taken. Returned value specifies if new domain registration is needed.
|
// It panics if the name is taken. Returned value specifies if new domain registration is needed.
|
||||||
func checkNiceNameAvailable(nnsContractAddr interop.Hash160, domain string) bool {
|
func checkNiceNameAvailable(nnsContractAddr interop.Hash160, domain string) bool {
|
||||||
isAvail := contract.Call(nnsContractAddr, "isAvailable",
|
isAvail := contract.Call(nnsContractAddr, "isAvailable",
|
||||||
|
@ -303,15 +303,15 @@ func checkNiceNameAvailable(nnsContractAddr interop.Hash160, domain string) bool
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete method removes container from contract storage if it was
|
// Delete method removes a container from the contract storage if it has been
|
||||||
// invoked by Alphabet nodes of the Inner Ring. Otherwise it produces
|
// invoked by Alphabet nodes of the Inner Ring. Otherwise, it produces
|
||||||
// containerDelete notification.
|
// containerDelete notification.
|
||||||
//
|
//
|
||||||
// Signature is a RFC6979 signature of container ID.
|
// Signature is a RFC6979 signature of the container ID.
|
||||||
// Token is optional and should be stable marshaled SessionToken structure from
|
// Token is optional and should be a stable marshaled SessionToken structure from
|
||||||
// API.
|
// API.
|
||||||
//
|
//
|
||||||
// If a container doesn't exist it panics with NotFoundError.
|
// If the container doesn't exist, it panics with NotFoundError.
|
||||||
func Delete(containerID []byte, signature interop.Signature, token []byte) {
|
func Delete(containerID []byte, signature interop.Signature, token []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -348,8 +348,8 @@ func Delete(containerID []byte, signature interop.Signature, token []byte) {
|
||||||
if len(domain) != 0 {
|
if len(domain) != 0 {
|
||||||
storage.Delete(ctx, key)
|
storage.Delete(ctx, key)
|
||||||
// We should do `getRecord` first because NNS record could be deleted
|
// We should do `getRecord` first because NNS record could be deleted
|
||||||
// by other means (expiration, manual) thus leading to failing `deleteRecord`
|
// by other means (expiration, manual), thus leading to failing `deleteRecord`
|
||||||
// and inability to delete container. We should also check that we own the record in case.
|
// and inability to delete a container. We should also check if we own the record in case.
|
||||||
nnsContractAddr := storage.Get(ctx, nnsContractKey).(interop.Hash160)
|
nnsContractAddr := storage.Get(ctx, nnsContractKey).(interop.Hash160)
|
||||||
res := contract.Call(nnsContractAddr, "getRecords", contract.ReadStates|contract.AllowCall, domain, 16 /* TXT */)
|
res := contract.Call(nnsContractAddr, "getRecords", contract.ReadStates|contract.AllowCall, domain, 16 /* TXT */)
|
||||||
if res != nil && std.Base58Encode(containerID) == string(res.([]interface{})[0].(string)) {
|
if res != nil && std.Base58Encode(containerID) == string(res.([]interface{})[0].(string)) {
|
||||||
|
@ -361,11 +361,11 @@ func Delete(containerID []byte, signature interop.Signature, token []byte) {
|
||||||
runtime.Notify("DeleteSuccess", containerID)
|
runtime.Notify("DeleteSuccess", containerID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get method returns structure that contains stable marshaled Container structure,
|
// Get method returns a structure that contains a stable marshaled Container structure,
|
||||||
// signature, public key of the container creator and stable marshaled SessionToken
|
// the signature, the public key of the container creator and a stable marshaled SessionToken
|
||||||
// structure if it was provided.
|
// structure if it was provided.
|
||||||
//
|
//
|
||||||
// If a container doesn't exist it panics with NotFoundError.
|
// If the container doesn't exist, it panics with NotFoundError.
|
||||||
func Get(containerID []byte) Container {
|
func Get(containerID []byte) Container {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
cnt := getContainer(ctx, containerID)
|
cnt := getContainer(ctx, containerID)
|
||||||
|
@ -375,9 +375,9 @@ func Get(containerID []byte) Container {
|
||||||
return cnt
|
return cnt
|
||||||
}
|
}
|
||||||
|
|
||||||
// Owner method returns 25 byte Owner ID of the container.
|
// Owner method returns a 25 byte Owner ID of the container.
|
||||||
//
|
//
|
||||||
// If a container doesn't exist it panics with NotFoundError.
|
// If the container doesn't exist, it panics with NotFoundError.
|
||||||
func Owner(containerID []byte) []byte {
|
func Owner(containerID []byte) []byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
owner := getOwnerByID(ctx, containerID)
|
owner := getOwnerByID(ctx, containerID)
|
||||||
|
@ -387,7 +387,7 @@ func Owner(containerID []byte) []byte {
|
||||||
return owner
|
return owner
|
||||||
}
|
}
|
||||||
|
|
||||||
// List method returns list of all container IDs owned by specified owner.
|
// List method returns a list of all container IDs owned by the specified owner.
|
||||||
func List(owner []byte) [][]byte {
|
func List(owner []byte) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -406,17 +406,17 @@ func List(owner []byte) [][]byte {
|
||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetEACL method sets new extended ACL table related to the contract
|
// SetEACL method sets a new extended ACL table related to the contract
|
||||||
// if it was invoked by Alphabet nodes of the Inner Ring. Otherwise it produces
|
// if it was invoked by Alphabet nodes of the Inner Ring. Otherwise, it produces
|
||||||
// setEACL notification.
|
// setEACL notification.
|
||||||
//
|
//
|
||||||
// EACL should be stable marshaled EACLTable structure from API.
|
// EACL should be a stable marshaled EACLTable structure from API.
|
||||||
// Signature is a RFC6979 signature of Container.
|
// Signature is a RFC6979 signature of the Container.
|
||||||
// PublicKey contains public key of the signer.
|
// PublicKey contains the public key of the signer.
|
||||||
// Token is optional and should be stable marshaled SessionToken structure from
|
// Token is optional and should be a stable marshaled SessionToken structure from
|
||||||
// API.
|
// API.
|
||||||
//
|
//
|
||||||
// If a container doesn't exist it panics with NotFoundError.
|
// If the container doesn't exist, it panics with NotFoundError.
|
||||||
func SetEACL(eACL []byte, signature interop.Signature, publicKey interop.PublicKey, token []byte) {
|
func SetEACL(eACL []byte, signature interop.Signature, publicKey interop.PublicKey, token []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -469,11 +469,11 @@ func SetEACL(eACL []byte, signature interop.Signature, publicKey interop.PublicK
|
||||||
runtime.Notify("SetEACLSuccess", containerID, publicKey)
|
runtime.Notify("SetEACLSuccess", containerID, publicKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EACL method returns structure that contains stable marshaled EACLTable structure,
|
// EACL method returns a structure that contains a stable marshaled EACLTable structure,
|
||||||
// signature, public key of the extended ACL setter and stable marshaled SessionToken
|
// the signature, the public key of the extended ACL setter and a stable marshaled SessionToken
|
||||||
// structure if it was provided.
|
// structure if it was provided.
|
||||||
//
|
//
|
||||||
// If a container doesn't exist it panics with NotFoundError.
|
// If the container doesn't exist, it panics with NotFoundError.
|
||||||
func EACL(containerID []byte) ExtendedACL {
|
func EACL(containerID []byte) ExtendedACL {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -486,10 +486,10 @@ func EACL(containerID []byte) ExtendedACL {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutContainerSize method saves container size estimation in contract
|
// PutContainerSize method saves container size estimation in contract
|
||||||
// memory. Can be invoked only by Storage nodes from the network map. Method
|
// memory. It can be invoked only by Storage nodes from the network map. This method
|
||||||
// checks witness based on the provided public key of the Storage node.
|
// checks witness based on the provided public key of the Storage node.
|
||||||
//
|
//
|
||||||
// If a container doesn't exist it panics with NotFoundError.
|
// If the container doesn't exist, it panics with NotFoundError.
|
||||||
func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.PublicKey) {
|
func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.PublicKey) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
|
@ -516,13 +516,13 @@ func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.Public
|
||||||
runtime.Log("saved container size estimation")
|
runtime.Log("saved container size estimation")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetContainerSize method returns container ID and slice of container
|
// GetContainerSize method returns the container ID and a slice of container
|
||||||
// estimations. Container estimation includes public key of the Storage Node
|
// estimations. Container estimation includes the public key of the Storage Node
|
||||||
// that registered estimation and value of estimation.
|
// that registered estimation and value of estimation.
|
||||||
//
|
//
|
||||||
// Use ID obtained from ListContainerSizes method. Estimations are removed
|
// Use the ID obtained from ListContainerSizes method. Estimations are removed
|
||||||
// from contract storage every epoch, see NewEpoch method, therefore method
|
// from contract storage every epoch, see NewEpoch method; therefore, this method
|
||||||
// can return different results in different epochs.
|
// can return different results during different epochs.
|
||||||
func GetContainerSize(id []byte) containerSizes {
|
func GetContainerSize(id []byte) containerSizes {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -535,8 +535,8 @@ func GetContainerSize(id []byte) containerSizes {
|
||||||
return getContainerSizeEstimation(ctx, id, cid)
|
return getContainerSizeEstimation(ctx, id, cid)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListContainerSizes method returns IDs of container size estimations
|
// ListContainerSizes method returns the IDs of container size estimations
|
||||||
// that has been registered for specified epoch.
|
// that has been registered for the specified epoch.
|
||||||
func ListContainerSizes(epoch int) [][]byte {
|
func ListContainerSizes(epoch int) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -568,7 +568,7 @@ func ListContainerSizes(epoch int) [][]byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEpoch method removes all container size estimations from epoch older than
|
// NewEpoch method removes all container size estimations from epoch older than
|
||||||
// epochNum + 3. Can be invoked only by NewEpoch method of the Netmap contract.
|
// epochNum + 3. It can be invoked only by NewEpoch method of the Netmap contract.
|
||||||
func NewEpoch(epochNum int) {
|
func NewEpoch(epochNum int) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -591,7 +591,7 @@ func NewEpoch(epochNum int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartContainerEstimation method produces StartEstimation notification.
|
// StartContainerEstimation method produces StartEstimation notification.
|
||||||
// Can be invoked only by Alphabet nodes of the Inner Ring.
|
// It can be invoked only by Alphabet nodes of the Inner Ring.
|
||||||
func StartContainerEstimation(epoch int) {
|
func StartContainerEstimation(epoch int) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -629,7 +629,7 @@ func StartContainerEstimation(epoch int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopContainerEstimation method produces StopEstimation notification.
|
// StopContainerEstimation method produces StopEstimation notification.
|
||||||
// Can be invoked only by Alphabet nodes of the Inner Ring.
|
// It can be invoked only by Alphabet nodes of the Inner Ring.
|
||||||
func StopContainerEstimation(epoch int) {
|
func StopContainerEstimation(epoch int) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -666,7 +666,7 @@ func StopContainerEstimation(epoch int) {
|
||||||
runtime.Log("notification has been produced")
|
runtime.Log("notification has been produced")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
@ -763,7 +763,7 @@ func getContainerSizeEstimation(ctx storage.Context, key, cid []byte) containerS
|
||||||
}
|
}
|
||||||
|
|
||||||
// isStorageNode looks into _previous_ epoch network map, because storage node
|
// isStorageNode looks into _previous_ epoch network map, because storage node
|
||||||
// announce container size estimation of previous epoch.
|
// announces container size estimation of the previous epoch.
|
||||||
func isStorageNode(ctx storage.Context, key interop.PublicKey) bool {
|
func isStorageNode(ctx storage.Context, key interop.PublicKey) bool {
|
||||||
netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160)
|
netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160)
|
||||||
snapshot := contract.Call(netmapContractAddr, "snapshot", contract.ReadOnly, 1).([]storageNode)
|
snapshot := contract.Call(netmapContractAddr, "snapshot", contract.ReadOnly, 1).([]storageNode)
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
/*
|
/*
|
||||||
Container contract is a contract deployed in NeoFS side chain.
|
Container contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Container contract stores and manages containers, extended ACLs and container
|
Container contract stores and manages containers, extended ACLs and container
|
||||||
size estimations. Contract does not perform sanity or signature checks of the
|
size estimations. Contract does not perform sanity or signature checks of
|
||||||
containers or extended ACLs, it is done by Alphabet nodes of the Inner Ring.
|
containers or extended ACLs, it is done by Alphabet nodes of the Inner Ring.
|
||||||
Alphabet nodes approve it by invoking the same Put or SetEACL methods with
|
Alphabet nodes approve it by invoking the same Put or SetEACL methods with
|
||||||
the same arguments.
|
the same arguments.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
containerPut notification. This notification is produced when user wants to
|
containerPut notification. This notification is produced when a user wants to
|
||||||
create new container. Alphabet nodes of the Inner Ring catch notification and
|
create a new container. Alphabet nodes of the Inner Ring catch the notification and
|
||||||
validate container data, signature and token if it is present.
|
validate container data, signature and token if present.
|
||||||
|
|
||||||
containerPut:
|
containerPut:
|
||||||
- name: container
|
- name: container
|
||||||
|
@ -23,9 +23,9 @@ validate container data, signature and token if it is present.
|
||||||
- name: token
|
- name: token
|
||||||
type: ByteArray
|
type: ByteArray
|
||||||
|
|
||||||
containerDelete notification. This notification is produced when container owner
|
containerDelete notification. This notification is produced when a container owner
|
||||||
wants to delete container. Alphabet nodes of the Inner Ring catch notification
|
wants to delete a container. Alphabet nodes of the Inner Ring catch the notification
|
||||||
and validate container ownership, signature and token if it is present.
|
and validate container ownership, signature and token if present.
|
||||||
|
|
||||||
containerDelete:
|
containerDelete:
|
||||||
- name: containerID
|
- name: containerID
|
||||||
|
@ -35,9 +35,9 @@ and validate container ownership, signature and token if it is present.
|
||||||
- name: token
|
- name: token
|
||||||
type: ByteArray
|
type: ByteArray
|
||||||
|
|
||||||
setEACL notification. This notification is produced when container owner wants
|
setEACL notification. This notification is produced when a container owner wants
|
||||||
to update extended ACL of the container. Alphabet nodes of the Inner Ring catch
|
to update an extended ACL of a container. Alphabet nodes of the Inner Ring catch
|
||||||
notification and validate container ownership, signature and token if it is
|
the notification and validate container ownership, signature and token if
|
||||||
present.
|
present.
|
||||||
|
|
||||||
setEACL:
|
setEACL:
|
||||||
|
|
30
neofs/doc.go
30
neofs/doc.go
|
@ -1,22 +1,22 @@
|
||||||
/*
|
/*
|
||||||
NeoFS contract is a contract deployed in NeoFS main chain.
|
NeoFS contract is a contract deployed in NeoFS mainchain.
|
||||||
|
|
||||||
NeoFS contract is an entry point to NeoFS users. This contract stores all NeoFS
|
NeoFS contract is an entry point to NeoFS users. This contract stores all NeoFS
|
||||||
related GAS, registers new Inner Ring candidates and produces notifications
|
related GAS, registers new Inner Ring candidates and produces notifications
|
||||||
to control side chain.
|
to control the sidechain.
|
||||||
|
|
||||||
While main chain committee controls list of Alphabet nodes in native
|
While mainchain committee controls the list of Alphabet nodes in native
|
||||||
RoleManagement contract, NeoFS can't change more than 1\3 keys at a time.
|
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.
|
NeoFS contract contains the actual list of Alphabet nodes in the sidechain.
|
||||||
|
|
||||||
Network configuration also stored in NeoFS contract. All the changes in
|
Network configuration is also stored in NeoFS contract. All changes in
|
||||||
configuration are mirrored in side chain with notifications.
|
configuration are mirrored in the sidechain with notifications.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
Deposit notification. This notification is produced when user transfers native
|
Deposit notification. This notification is produced when user transfers native
|
||||||
GAS to the NeoFS contract address. The same amount of NEOFS token will be
|
GAS to the NeoFS contract address. The same amount of NEOFS token will be
|
||||||
minted in Balance contract in the side chain.
|
minted in Balance contract in the sidechain.
|
||||||
|
|
||||||
Deposit:
|
Deposit:
|
||||||
- name: from
|
- name: from
|
||||||
|
@ -28,8 +28,8 @@ minted in Balance contract in the side chain.
|
||||||
- name: txHash
|
- name: txHash
|
||||||
type: Hash256
|
type: Hash256
|
||||||
|
|
||||||
Withdraw notification. This notification is produced when user wants to
|
Withdraw notification. This notification is produced when a user wants to
|
||||||
withdraw GAS from internal NeoFS balance and has payed fee for that.
|
withdraw GAS from the internal NeoFS balance and has paid fee for that.
|
||||||
|
|
||||||
Withdraw:
|
Withdraw:
|
||||||
- name: user
|
- name: user
|
||||||
|
@ -41,7 +41,7 @@ withdraw GAS from internal NeoFS balance and has payed fee for that.
|
||||||
|
|
||||||
|
|
||||||
Cheque notification. This notification is produced when NeoFS contract
|
Cheque notification. This notification is produced when NeoFS contract
|
||||||
successfully transferred assets back to the user after withdraw.
|
has successfully transferred assets back to the user after withdraw.
|
||||||
|
|
||||||
Cheque:
|
Cheque:
|
||||||
- name: id
|
- name: id
|
||||||
|
@ -53,8 +53,8 @@ successfully transferred assets back to the user after withdraw.
|
||||||
- name: lockAccount
|
- name: lockAccount
|
||||||
type: ByteArray
|
type: ByteArray
|
||||||
|
|
||||||
Bind notification. This notification is produced when user wants to bind
|
Bind notification. This notification is produced when a user wants to bind
|
||||||
public keys with user account (OwnerID). Keys argument is array of ByteArray.
|
public keys with the user account (OwnerID). Keys argument is an array of ByteArray.
|
||||||
|
|
||||||
Bind:
|
Bind:
|
||||||
- name: user
|
- name: user
|
||||||
|
@ -62,8 +62,8 @@ public keys with user account (OwnerID). Keys argument is array of ByteArray.
|
||||||
- name: keys
|
- name: keys
|
||||||
type: Array
|
type: Array
|
||||||
|
|
||||||
Unbind notification. This notification is produced when user wants to unbind
|
Unbind notification. This notification is produced when a user wants to unbind
|
||||||
public keys with user account (OwnerID). Keys argument is an array of ByteArray.
|
public keys with the user account (OwnerID). Keys argument is an array of ByteArray.
|
||||||
|
|
||||||
Unbind:
|
Unbind:
|
||||||
- name: user
|
- name: user
|
||||||
|
@ -72,7 +72,7 @@ public keys with user account (OwnerID). Keys argument is an array of ByteArray.
|
||||||
type: Array
|
type: Array
|
||||||
|
|
||||||
AlphabetUpdate notification. This notification is produced when Alphabet nodes
|
AlphabetUpdate notification. This notification is produced when Alphabet nodes
|
||||||
updated it's list in the contract. Alphabet argument is an array of ByteArray. It
|
have updated their lists in the contract. Alphabet argument is an array of ByteArray. It
|
||||||
contains public keys of new alphabet nodes.
|
contains public keys of new alphabet nodes.
|
||||||
|
|
||||||
AlphabetUpdate:
|
AlphabetUpdate:
|
||||||
|
|
|
@ -103,8 +103,8 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("neofs: contract initialized")
|
runtime.Log("neofs: contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by side chain committee.
|
// only by sidechain committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
blockHeight := ledger.CurrentIndex()
|
blockHeight := ledger.CurrentIndex()
|
||||||
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
||||||
|
@ -117,7 +117,7 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("neofs contract updated")
|
runtime.Log("neofs contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlphabetList returns array of alphabet node keys. Use in side chain notary
|
// AlphabetList returns an array of alphabet node keys. It is used in sidechain notary
|
||||||
// disabled environment.
|
// disabled environment.
|
||||||
func AlphabetList() []common.IRNode {
|
func AlphabetList() []common.IRNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
@ -129,14 +129,14 @@ func AlphabetList() []common.IRNode {
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlphabetAddress returns 2\3n+1 multi signature address of alphabet nodes.
|
// AlphabetAddress returns 2\3n+1 multisignature address of alphabet nodes.
|
||||||
// Used in side chain notary disabled environment.
|
// It is used in sidechain notary disabled environment.
|
||||||
func AlphabetAddress() interop.Hash160 {
|
func AlphabetAddress() interop.Hash160 {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return multiaddress(getAlphabetNodes(ctx))
|
return multiaddress(getAlphabetNodes(ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingCandidates returns array of structures that contain Inner Ring
|
// InnerRingCandidates returns an array of structures that contain an Inner Ring
|
||||||
// candidate node key.
|
// candidate node key.
|
||||||
func InnerRingCandidates() []common.IRNode {
|
func InnerRingCandidates() []common.IRNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
@ -150,10 +150,10 @@ func InnerRingCandidates() []common.IRNode {
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingCandidateRemove removes key from the list of Inner Ring candidates.
|
// InnerRingCandidateRemove removes a key from a list of Inner Ring candidates.
|
||||||
// Can be invoked by Alphabet nodes or candidate itself.
|
// It can be invoked by Alphabet nodes or the candidate itself.
|
||||||
//
|
//
|
||||||
// Method does not return fee back to the candidate.
|
// This 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)
|
||||||
|
@ -201,11 +201,11 @@ func InnerRingCandidateRemove(key interop.PublicKey) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingCandidateAdd adds key to the list of Inner Ring candidates.
|
// InnerRingCandidateAdd adds a key to a list of Inner Ring candidates.
|
||||||
// Can be invoked only by candidate itself.
|
// It can be invoked only by the candidate itself.
|
||||||
//
|
//
|
||||||
// This method transfers fee from candidate to contract account.
|
// This method transfers fee from a candidate to the contract account.
|
||||||
// Fee value specified in NeoFS network config with the key InnerRingCandidateFee.
|
// Fee value is 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()
|
||||||
|
|
||||||
|
@ -230,7 +230,7 @@ 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
|
// 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
|
// NeoFS balance contract has precision 12. Values bigger than 9000.0 can
|
||||||
// break JSON limits for integers when precision is converted.
|
// 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{}) {
|
||||||
|
@ -264,13 +264,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. Can be invoked only
|
// Withdraw initializes gas asset withdraw from NeoFS. It can be invoked only
|
||||||
// by the specified user.
|
// by the specified user.
|
||||||
//
|
//
|
||||||
// This method produces Withdraw notification to lock assets in side chain and
|
// This method produces Withdraw notification to lock assets in the sidechain and
|
||||||
// transfers withdraw fee from user account to each Alphabet node. If notary
|
// transfers withdraw fee from a user account to each Alphabet node. If notary
|
||||||
// is enabled in main chain, fee is transferred to Processing contract.
|
// is enabled in the mainchain, fee is transferred to Processing contract.
|
||||||
// Fee value specified in NeoFS network config with the key WithdrawFee.
|
// Fee value is 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("you should be the owner of the wallet")
|
panic("you should be the owner of the wallet")
|
||||||
|
@ -316,11 +316,11 @@ func Withdraw(user interop.Hash160, amount int) {
|
||||||
runtime.Notify("Withdraw", user, amount, tx.Hash)
|
runtime.Notify("Withdraw", user, amount, tx.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cheque transfers GAS back to the user from contract account, if assets were
|
// Cheque transfers GAS back to the user from the contract account, if assets were
|
||||||
// successfully locked in NeoFS balance contract. Can be invoked only by
|
// successfully locked in NeoFS balance contract. It can be invoked only by
|
||||||
// Alphabet nodes.
|
// Alphabet nodes.
|
||||||
//
|
//
|
||||||
// This method produces Cheque notification to burn assets in side chain.
|
// This method produces Cheque notification to burn assets in sidechain.
|
||||||
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)
|
||||||
|
@ -363,11 +363,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 method produces notification to bind specified public keys in NeoFSID
|
// Bind method produces notification to bind the specified public keys in NeoFSID
|
||||||
// contract in side chain. Can be invoked only by specified user.
|
// contract in the sidechain. It can be invoked only by specified user.
|
||||||
//
|
//
|
||||||
// This method produces Bind notification. Method panics if keys are not
|
// This method produces Bind notification. This method panics if keys are not
|
||||||
// 33 byte long. User argument must be valid 20 byte script hash.
|
// 33 byte long. User argument must be a 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("you should be the owner of the wallet")
|
panic("you should be the owner of the wallet")
|
||||||
|
@ -383,11 +383,11 @@ func Bind(user []byte, keys []interop.PublicKey) {
|
||||||
runtime.Notify("Bind", user, keys)
|
runtime.Notify("Bind", user, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unbind method produces notification to unbind specified public keys in NeoFSID
|
// Unbind method produces notification to unbind the specified public keys in NeoFSID
|
||||||
// contract in side chain. Can be invoked only by specified user.
|
// contract in the sidechain. It can be invoked only by the specified user.
|
||||||
//
|
//
|
||||||
// This method produces Unbind notification. Method panics if keys are not
|
// This method produces Unbind notification. This method panics if keys are not
|
||||||
// 33 byte long. User argument must be valid 20 byte script hash.
|
// 33 byte long. User argument must be a 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("you should be the owner of the wallet")
|
panic("you should be the owner of the wallet")
|
||||||
|
@ -403,11 +403,11 @@ func Unbind(user []byte, keys []interop.PublicKey) {
|
||||||
runtime.Notify("Unbind", user, keys)
|
runtime.Notify("Unbind", user, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AlphabetUpdate updates list of alphabet nodes with provided list of
|
// AlphabetUpdate updates a list of alphabet nodes with the provided list of
|
||||||
// public keys. Can be invoked only by alphabet nodes.
|
// public keys. It can be invoked only by alphabet nodes.
|
||||||
//
|
//
|
||||||
// This method used in notary disabled side chain environment. In this case
|
// This method is used in notary disabled sidechain environment. In this case,
|
||||||
// actual alphabet list should be stored in the NeoFS contract.
|
// the 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,14 +460,14 @@ func AlphabetUpdate(id []byte, args []interop.PublicKey) {
|
||||||
runtime.Log("alphabet list has been updated")
|
runtime.Log("alphabet list has been updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config returns configuration value of NeoFS configuration. If key does
|
// Config returns configuration value of NeoFS configuration. If the key does
|
||||||
// not exists, returns nil.
|
// 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. Can be invoked
|
// SetConfig key-value pair as a NeoFS runtime configuration value. It can be invoked
|
||||||
// only by Alphabet nodes.
|
// only by Alphabet nodes.
|
||||||
func SetConfig(id, key, val []byte) {
|
func SetConfig(id, key, val []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
@ -506,7 +506,7 @@ func SetConfig(id, key, val []byte) {
|
||||||
runtime.Log("configuration has been updated")
|
runtime.Log("configuration has been updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListConfig returns array of structures that contain key and value of all
|
// ListConfig returns an array of structures that contain a key and a value of all
|
||||||
// NeoFS configuration records. Key and value are both byte arrays.
|
// NeoFS configuration records. Key and value are both byte arrays.
|
||||||
func ListConfig() []record {
|
func ListConfig() []record {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
@ -532,7 +532,7 @@ func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
// getAlphabetNodes returns deserialized slice of nodes from storage.
|
// getAlphabetNodes returns a deserialized slice of nodes from storage.
|
||||||
func getAlphabetNodes(ctx storage.Context) []interop.PublicKey {
|
func getAlphabetNodes(ctx storage.Context) []interop.PublicKey {
|
||||||
data := storage.Get(ctx, alphabetKey)
|
data := storage.Get(ctx, alphabetKey)
|
||||||
if data != nil {
|
if data != nil {
|
||||||
|
@ -542,7 +542,7 @@ func getAlphabetNodes(ctx storage.Context) []interop.PublicKey {
|
||||||
return []interop.PublicKey{}
|
return []interop.PublicKey{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// getConfig returns installed neofs configuration value or nil if it is not set.
|
// getConfig returns the installed neofs configuration value or nil if it is not set.
|
||||||
func getConfig(ctx storage.Context, key interface{}) interface{} {
|
func getConfig(ctx storage.Context, key interface{}) interface{} {
|
||||||
postfix := key.([]byte)
|
postfix := key.([]byte)
|
||||||
storageKey := append(configPrefix, postfix...)
|
storageKey := append(configPrefix, postfix...)
|
||||||
|
@ -550,7 +550,7 @@ func getConfig(ctx storage.Context, key interface{}) interface{} {
|
||||||
return storage.Get(ctx, storageKey)
|
return storage.Get(ctx, storageKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setConfig sets neofs configuration value in the contract storage.
|
// setConfig sets a neofs configuration value in the contract storage.
|
||||||
func setConfig(ctx storage.Context, key, val interface{}) {
|
func setConfig(ctx storage.Context, key, val interface{}) {
|
||||||
postfix := key.([]byte)
|
postfix := key.([]byte)
|
||||||
storageKey := append(configPrefix, postfix...)
|
storageKey := append(configPrefix, postfix...)
|
||||||
|
@ -558,7 +558,7 @@ func setConfig(ctx storage.Context, key, val interface{}) {
|
||||||
storage.Put(ctx, storageKey, val)
|
storage.Put(ctx, storageKey, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiaddress returns multi signature address from list of IRNode structures
|
// multiaddress returns a multisignature address from the list of IRNode structures
|
||||||
// with m = 2/3n+1.
|
// with m = 2/3n+1.
|
||||||
func multiaddress(keys []interop.PublicKey) []byte {
|
func multiaddress(keys []interop.PublicKey) []byte {
|
||||||
threshold := len(keys)*2/3 + 1
|
threshold := len(keys)*2/3 + 1
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
/*
|
/*
|
||||||
NeoFSID contract is a contract deployed in NeoFS side chain.
|
NeoFSID contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
NeoFSID contract used to store connection between OwnerID and it's public keys.
|
NeoFSID contract is used to store connection between an OwnerID and its public keys.
|
||||||
OwnerID is a 25-byte N3 wallet address that can be produced from public key.
|
OwnerID is a 25-byte N3 wallet address that can be produced from a public key.
|
||||||
It is one-way conversion. In simple cases NeoFS verifies ownership by checking
|
It is one-way conversion. In simple cases, NeoFS verifies ownership by checking
|
||||||
signature and relation between public key and OwnerID.
|
signature and relation between a public key and an OwnerID.
|
||||||
|
|
||||||
In more complex cases, user can use public keys unrelated to OwnerID to maintain
|
In more complex cases, a user can use public keys unrelated to the OwnerID to maintain
|
||||||
secure access to the data. NeoFSID contract stores relation between OwnerID and
|
secure access to the data. NeoFSID contract stores relation between an OwnerID and
|
||||||
arbitrary public keys. Data owner can bind or unbind public key with it's account
|
arbitrary public keys. Data owner can bind a public key with its account or unbind it
|
||||||
by invoking Bind or Unbind methods of NeoFS contract in main chain. After that,
|
by invoking Bind or Unbind methods of NeoFS contract in the mainchain. After that,
|
||||||
Alphabet nodes produce multi signed AddKey and RemoveKey invocations of NeoFSID
|
Alphabet nodes produce multisigned AddKey and RemoveKey invocations of NeoFSID
|
||||||
contract.
|
contract.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
|
@ -60,7 +60,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("neofsid contract initialized")
|
runtime.Log("neofsid contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -72,11 +72,11 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("neofsid contract updated")
|
runtime.Log("neofsid contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddKey binds list of provided public keys to OwnerID. Can be invoked only by
|
// AddKey binds a list of the provided public keys to the OwnerID. It can be invoked only by
|
||||||
// Alphabet nodes.
|
// Alphabet nodes.
|
||||||
//
|
//
|
||||||
// This method panics if OwnerID is not ownerSize byte or public key is not 33 byte long.
|
// This method panics if the OwnerID is not an ownerSize byte or the public key is not 33 byte long.
|
||||||
// If key is already bound, ignores it.
|
// If the key is already bound, the method ignores it.
|
||||||
func AddKey(owner []byte, keys []interop.PublicKey) {
|
func AddKey(owner []byte, keys []interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(owner) != ownerSize {
|
if len(owner) != ownerSize {
|
||||||
|
@ -135,11 +135,11 @@ func AddKey(owner []byte, keys []interop.PublicKey) {
|
||||||
runtime.Log("key bound to the owner")
|
runtime.Log("key bound to the owner")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveKey unbinds provided public keys from OwnerID. Can be invoked only by
|
// RemoveKey unbinds the provided public keys from the OwnerID. It can be invoked only by
|
||||||
// Alphabet nodes.
|
// Alphabet nodes.
|
||||||
//
|
//
|
||||||
// This method panics if OwnerID is not ownerSize byte or public key is not 33 byte long.
|
// This method panics if the OwnerID is not an ownerSize byte or the public key is not 33 byte long.
|
||||||
// If key is already unbound, ignores it.
|
// If the key is already unbound, the method ignores it.
|
||||||
func RemoveKey(owner []byte, keys []interop.PublicKey) {
|
func RemoveKey(owner []byte, keys []interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(owner) != ownerSize {
|
if len(owner) != ownerSize {
|
||||||
|
@ -190,9 +190,9 @@ func RemoveKey(owner []byte, keys []interop.PublicKey) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key method returns list of 33-byte public keys bound with OwnerID.
|
// Key method returns a list of 33-byte public keys bound with the OwnerID.
|
||||||
//
|
//
|
||||||
// This method panics if owner is not ownerSize byte long.
|
// This method panics if the owner is not ownerSize byte long.
|
||||||
func Key(owner []byte) [][]byte {
|
func Key(owner []byte) [][]byte {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(owner) != ownerSize {
|
if len(owner) != ownerSize {
|
||||||
|
@ -207,7 +207,7 @@ func Key(owner []byte) [][]byte {
|
||||||
return info.Keys
|
return info.Keys
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
/*
|
/*
|
||||||
Netmap contract is a contract deployed in NeoFS side chain.
|
Netmap contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Netmap contract stores and manages NeoFS network map, Storage node candidates
|
Netmap contract stores and manages NeoFS network map, Storage node candidates
|
||||||
and epoch number counter. In notary disabled environment, contract also stores
|
and epoch number counter. In notary disabled environment, contract also stores
|
||||||
list of Inner Ring node keys.
|
a list of Inner Ring node keys.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
AddPeer notification. This notification is produced when Storage node sends
|
AddPeer notification. This notification is produced when a Storage node sends
|
||||||
bootstrap request by invoking AddPeer method.
|
a bootstrap request by invoking AddPeer method.
|
||||||
|
|
||||||
AddPeer
|
AddPeer
|
||||||
- name: nodeInfo
|
- name: nodeInfo
|
||||||
type: ByteArray
|
type: ByteArray
|
||||||
|
|
||||||
UpdateState notification. This notification is produced when Storage node wants
|
UpdateState notification. This notification is produced when a Storage node wants
|
||||||
to change it's state (go offline) by invoking UpdateState method. Supported
|
to change its state (go offline) by invoking UpdateState method. Supported
|
||||||
states: (2) -- offline.
|
states: (2) -- offline.
|
||||||
|
|
||||||
UpdateState
|
UpdateState
|
||||||
|
@ -24,7 +24,7 @@ states: (2) -- offline.
|
||||||
- name: publicKey
|
- name: publicKey
|
||||||
type: PublicKey
|
type: PublicKey
|
||||||
|
|
||||||
NewEpoch notification. This notification is produced when new epoch is applied
|
NewEpoch notification. This notification is produced when a new epoch is applied
|
||||||
in the network by invoking NewEpoch method.
|
in the network by invoking NewEpoch method.
|
||||||
|
|
||||||
NewEpoch
|
NewEpoch
|
||||||
|
|
|
@ -122,7 +122,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("netmap contract initialized")
|
runtime.Log("netmap contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -134,11 +134,11 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("netmap contract updated")
|
runtime.Log("netmap contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// InnerRingList method returns slice of structures that contains public key of
|
// InnerRingList method returns a slice of structures that contains the public key of
|
||||||
// Inner Ring node. Should be used only in notary disabled environment.
|
// an Inner Ring node. It should be used in notary disabled environment only.
|
||||||
//
|
//
|
||||||
// If notary enabled, then look to NeoFSAlphabet role in native RoleManagement
|
// If notary is enabled, look to NeoFSAlphabet role in native RoleManagement
|
||||||
// contract of the side chain.
|
// contract of the sidechain.
|
||||||
func InnerRingList() []common.IRNode {
|
func InnerRingList() []common.IRNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
pubs := getIRNodes(ctx)
|
pubs := getIRNodes(ctx)
|
||||||
|
@ -149,11 +149,11 @@ func InnerRingList() []common.IRNode {
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateInnerRing method updates list of Inner Ring node keys. Should be used
|
// UpdateInnerRing method updates a list of Inner Ring node keys. It should be used
|
||||||
// only in notary disabled environment. Can be invoked only by Alphabet nodes.
|
// only in notary disabled environment. It can be invoked only by Alphabet nodes.
|
||||||
//
|
//
|
||||||
// If notary enabled, then update NeoFSAlphabet role in native RoleManagement
|
// If notary is enabled, update NeoFSAlphabet role in native RoleManagement
|
||||||
// contract of the side chain. Use notary service to collect multi signature.
|
// contract of the sidechain. Use notary service to collect multisignature.
|
||||||
func UpdateInnerRing(keys []interop.PublicKey) {
|
func UpdateInnerRing(keys []interop.PublicKey) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -190,8 +190,8 @@ func UpdateInnerRing(keys []interop.PublicKey) {
|
||||||
common.SetSerialized(ctx, innerRingKey, keys)
|
common.SetSerialized(ctx, innerRingKey, keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddPeerIR method tries to add new candidate to the network map.
|
// AddPeerIR method tries to add a new candidate to the network map.
|
||||||
// Should only be invoked in notary-enabled environment by the alphabet.
|
// It should only be invoked in notary-enabled environment by the alphabet.
|
||||||
func AddPeerIR(nodeInfo []byte) {
|
func AddPeerIR(nodeInfo []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -207,12 +207,12 @@ func AddPeerIR(nodeInfo []byte) {
|
||||||
runtime.Notify("AddPeerSuccess", interop.PublicKey(publicKey))
|
runtime.Notify("AddPeerSuccess", interop.PublicKey(publicKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddPeer method adds new candidate to the next network map if it was invoked
|
// AddPeer method adds a new candidate to the next network map if it was invoked
|
||||||
// by Alphabet node. If it was invoked by node candidate, it produces AddPeer
|
// by Alphabet node. If it was invoked by a node candidate, it produces AddPeer
|
||||||
// notification. Otherwise method throws panic.
|
// notification. Otherwise, the method throws panic.
|
||||||
//
|
//
|
||||||
// If the candidate already exists, it's info is updated.
|
// If the candidate already exists, its info is updated.
|
||||||
// NodeInfo argument contains stable marshaled version of netmap.NodeInfo
|
// NodeInfo argument contains a stable marshaled version of netmap.NodeInfo
|
||||||
// structure.
|
// structure.
|
||||||
func AddPeer(nodeInfo []byte) {
|
func AddPeer(nodeInfo []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
@ -262,11 +262,11 @@ func AddPeer(nodeInfo []byte) {
|
||||||
runtime.Notify("AddPeerSuccess", interop.PublicKey(publicKey))
|
runtime.Notify("AddPeerSuccess", interop.PublicKey(publicKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateState method updates state of node from the network map candidate list.
|
// UpdateState method updates the state of a node from the network map candidate list.
|
||||||
// For notary-ENABLED environment tx must be signed by both storage node and the alphabet.
|
// For notary-ENABLED environment, tx must be signed by both storage node and alphabet.
|
||||||
// To force update without storage node signature, see `UpdateStateIR`.
|
// To force update without storage node signature, see `UpdateStateIR`.
|
||||||
//
|
//
|
||||||
// For notary-DISABLED environment the behaviour depends on who signed the transaction:
|
// For notary-DISABLED environment, the behaviour depends on who signed the transaction:
|
||||||
// 1. If it was signed by alphabet, go into voting.
|
// 1. If it was signed by alphabet, go into voting.
|
||||||
// 2. If it was signed by a storage node, emit `UpdateState` notification.
|
// 2. If it was signed by a storage node, emit `UpdateState` notification.
|
||||||
// 2. Fail in any other case.
|
// 2. Fail in any other case.
|
||||||
|
@ -276,7 +276,7 @@ func AddPeer(nodeInfo []byte) {
|
||||||
// | ENABLED | FAIL | FAIL | OK |
|
// | ENABLED | FAIL | FAIL | OK |
|
||||||
// | DISABLED | NOTIFICATION | OK | OK (same as alphabet) |
|
// | DISABLED | NOTIFICATION | OK | OK (same as alphabet) |
|
||||||
// State argument defines node state. The only supported state now is (2) --
|
// State argument defines node state. The only supported state now is (2) --
|
||||||
// offline state. Node is removed from network map candidate list.
|
// offline state. Node is removed from the network map candidate list.
|
||||||
//
|
//
|
||||||
// Method panics when invoked with unsupported states.
|
// Method panics when invoked with unsupported states.
|
||||||
func UpdateState(state int, publicKey interop.PublicKey) {
|
func UpdateState(state int, publicKey interop.PublicKey) {
|
||||||
|
@ -324,8 +324,8 @@ func UpdateState(state int, publicKey interop.PublicKey) {
|
||||||
runtime.Notify("UpdateStateSuccess", publicKey, state)
|
runtime.Notify("UpdateStateSuccess", publicKey, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateStateIR method tries to change node state in the network map.
|
// UpdateStateIR method tries to change the node state in the network map.
|
||||||
// Should only be invoked in notary-enabled environment by the alphabet.
|
// Should only be invoked in notary-enabled environment by alphabet.
|
||||||
func UpdateStateIR(state nodeState, publicKey interop.PublicKey) {
|
func UpdateStateIR(state nodeState, publicKey interop.PublicKey) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -344,15 +344,15 @@ func UpdateStateIR(state nodeState, publicKey interop.PublicKey) {
|
||||||
runtime.Notify("UpdateStateSuccess", publicKey, state)
|
runtime.Notify("UpdateStateSuccess", publicKey, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEpoch method changes epoch number up to provided epochNum argument. Can
|
// NewEpoch method changes the epoch number up to the provided epochNum argument. It can
|
||||||
// be invoked only by Alphabet nodes. If provided epoch number is less or equal
|
// be invoked only by Alphabet nodes. If provided epoch number is less than the
|
||||||
// current epoch number, method throws panic.
|
// current epoch number or equals it, the method throws panic.
|
||||||
//
|
//
|
||||||
// When epoch number updated, contract sets storage node candidates as current
|
// When epoch number is updated, the contract sets storage node candidates as the current
|
||||||
// network map. Also contract invokes NewEpoch method on Balance and Container
|
// network map. The contract also invokes NewEpoch method on Balance and Container
|
||||||
// contracts.
|
// contracts.
|
||||||
//
|
//
|
||||||
// Produces NewEpoch notification.
|
// It produces NewEpoch notification.
|
||||||
func NewEpoch(epochNum int) {
|
func NewEpoch(epochNum int) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -411,41 +411,41 @@ func NewEpoch(epochNum int) {
|
||||||
runtime.Notify("NewEpoch", epochNum)
|
runtime.Notify("NewEpoch", epochNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Epoch method returns current epoch number.
|
// Epoch method returns the current epoch number.
|
||||||
func Epoch() int {
|
func Epoch() int {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return storage.Get(ctx, snapshotEpoch).(int)
|
return storage.Get(ctx, snapshotEpoch).(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastEpochBlock method returns block number when current epoch was applied.
|
// LastEpochBlock method returns the block number when the current epoch was applied.
|
||||||
func LastEpochBlock() int {
|
func LastEpochBlock() int {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return storage.Get(ctx, snapshotBlockKey).(int)
|
return storage.Get(ctx, snapshotBlockKey).(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Netmap method returns list of structures that contain byte array of stable
|
// Netmap method returns a list of structures that contain a byte array of a stable
|
||||||
// marshalled netmap.NodeInfo structure. These structure contain Storage nodes
|
// marshalled netmap.NodeInfo structure. These structures contain Storage nodes
|
||||||
// of current epoch.
|
// of the current epoch.
|
||||||
func Netmap() []storageNode {
|
func Netmap() []storageNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
id := storage.Get(ctx, snapshotCurrentIDKey).(int)
|
id := storage.Get(ctx, snapshotCurrentIDKey).(int)
|
||||||
return getSnapshot(ctx, snapshotKeyPrefix+string([]byte{byte(id)}))
|
return getSnapshot(ctx, snapshotKeyPrefix+string([]byte{byte(id)}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetmapCandidates method returns list of structures that contain node state
|
// NetmapCandidates method returns a list of structures that contain the node state
|
||||||
// and byte array of stable marshalled netmap.NodeInfo structure.
|
// and a byte array of a stable marshalled netmap.NodeInfo structure.
|
||||||
// These structure contain Storage node candidates for next epoch.
|
// These structures contain Storage node candidates for the next epoch.
|
||||||
func NetmapCandidates() []netmapNode {
|
func NetmapCandidates() []netmapNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return getNetmapNodes(ctx)
|
return getNetmapNodes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Snapshot method returns list of structures that contain node state
|
// Snapshot method returns a list of structures that contain the node state
|
||||||
// (online: 1) and byte array of stable marshalled netmap.NodeInfo structure.
|
// (online: 1) and a byte array of a stable marshalled netmap.NodeInfo structure.
|
||||||
// These structure contain Storage nodes of specified epoch.
|
// These structures contain Storage nodes of the specified epoch.
|
||||||
//
|
//
|
||||||
// Netmap contract contains only two recent network map snapshot: current and
|
// Netmap contract contains only two recent network map snapshots: current and
|
||||||
// previous epoch. For diff bigger than 1 or less than 0 method throws panic.
|
// previous epoch. For diff bigger than 1 or less than 0, the method throws panic.
|
||||||
func Snapshot(diff int) []storageNode {
|
func Snapshot(diff int) []storageNode {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
count := getSnapshotCount(ctx)
|
count := getSnapshotCount(ctx)
|
||||||
|
@ -463,9 +463,9 @@ func getSnapshotCount(ctx storage.Context) int {
|
||||||
return storage.Get(ctx, snapshotCountKey).(int)
|
return storage.Get(ctx, snapshotCountKey).(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSnapshotCount updates number of stored snapshots.
|
// UpdateSnapshotCount updates the number of the stored snapshots.
|
||||||
// If new number is less than the old one, old snapshots are removed.
|
// If a new number is less than the old one, old snapshots are removed.
|
||||||
// Otherwise, history is extended to with empty snapshots, so
|
// Otherwise, history is extended with empty snapshots, so
|
||||||
// `Snapshot` method can return invalid results for `diff = new-old` epochs
|
// `Snapshot` method can return invalid results for `diff = new-old` epochs
|
||||||
// until `diff` epochs have passed.
|
// until `diff` epochs have passed.
|
||||||
func UpdateSnapshotCount(count int) {
|
func UpdateSnapshotCount(count int) {
|
||||||
|
@ -545,9 +545,9 @@ func moveSnapshot(ctx storage.Context, from, to int) {
|
||||||
storage.Put(ctx, keyTo, data)
|
storage.Put(ctx, keyTo, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SnapshotByEpoch method returns list of structures that contain node state
|
// SnapshotByEpoch method returns a list of structures that contain the node state
|
||||||
// (online: 1) and byte array of stable marshalled netmap.NodeInfo structure.
|
// (online: 1) and a byte array of a stable marshalled netmap.NodeInfo structure.
|
||||||
// These structure contain Storage nodes of specified epoch.
|
// These structures contain Storage nodes of the specified epoch.
|
||||||
//
|
//
|
||||||
// Netmap contract contains only two recent network map snapshot: current and
|
// Netmap contract contains only two recent network map snapshot: current and
|
||||||
// previous epoch. For all others epoch method throws panic.
|
// previous epoch. For all others epoch method throws panic.
|
||||||
|
@ -565,7 +565,7 @@ func Config(key []byte) interface{} {
|
||||||
return getConfig(ctx, key)
|
return getConfig(ctx, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetConfig key-value pair as a NeoFS runtime configuration value. Can be invoked
|
// SetConfig key-value pair as a NeoFS runtime configuration value. It can be invoked
|
||||||
// only by Alphabet nodes.
|
// only by Alphabet nodes.
|
||||||
func SetConfig(id, key, val []byte) {
|
func SetConfig(id, key, val []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
@ -603,7 +603,7 @@ func SetConfig(id, key, val []byte) {
|
||||||
runtime.Log("configuration has been updated")
|
runtime.Log("configuration has been updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListConfig returns array of structures that contain key and value of all
|
// ListConfig returns an array of structures that contain key and value of all
|
||||||
// NeoFS configuration records. Key and value are both byte arrays.
|
// NeoFS configuration records. Key and value are both byte arrays.
|
||||||
func ListConfig() []record {
|
func ListConfig() []record {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
@ -624,7 +624,7 @@ func ListConfig() []record {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ implementation. This token is a compatible analogue of C# Neo Name Service
|
||||||
token and is aimed to serve as a domain name service for Neo smart-contracts,
|
token and is aimed to serve as a domain name service for Neo smart-contracts,
|
||||||
thus it's NeoNameService. This token can be minted with new domain name
|
thus it's NeoNameService. This token can be minted with new domain name
|
||||||
registration, the domain name itself is your NFT. Corresponding domain root
|
registration, the domain name itself is your NFT. Corresponding domain root
|
||||||
must be added by the committee before new domain name can be registered.
|
must be added by committee before a new domain name can be registered.
|
||||||
*/
|
*/
|
||||||
package nns
|
package nns
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ import (
|
||||||
const (
|
const (
|
||||||
// prefixTotalSupply contains total supply of minted domains.
|
// prefixTotalSupply contains total supply of minted domains.
|
||||||
prefixTotalSupply byte = 0x00
|
prefixTotalSupply byte = 0x00
|
||||||
// prefixBalance contains map from owner to his balance.
|
// prefixBalance contains map from the owner to their balance.
|
||||||
prefixBalance byte = 0x01
|
prefixBalance byte = 0x01
|
||||||
// prefixAccountToken contains map from (owner + token key) to token ID,
|
// prefixAccountToken contains map from (owner + token key) to token ID,
|
||||||
// where token key = hash160(token ID) and token ID = domain name.
|
// where token key = hash160(token ID) and token ID = domain name.
|
||||||
|
@ -110,25 +110,25 @@ func Decimals() int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
// TotalSupply returns overall number of domains minted by the NeoNameService contract.
|
// TotalSupply returns the overall number of domains minted by NeoNameService contract.
|
||||||
func TotalSupply() int {
|
func TotalSupply() int {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return getTotalSupply(ctx)
|
return getTotalSupply(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OwnerOf returns owner of the specified domain.
|
// OwnerOf returns the owner of the specified domain.
|
||||||
func OwnerOf(tokenID []byte) interop.Hash160 {
|
func OwnerOf(tokenID []byte) interop.Hash160 {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
ns := getNameState(ctx, tokenID)
|
ns := getNameState(ctx, tokenID)
|
||||||
return ns.Owner
|
return ns.Owner
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties returns domain name and expiration date of the specified domain.
|
// Properties returns a domain name and an expiration date of the specified domain.
|
||||||
func Properties(tokenID []byte) map[string]interface{} {
|
func Properties(tokenID []byte) map[string]interface{} {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
ns := getNameState(ctx, tokenID)
|
ns := getNameState(ctx, tokenID)
|
||||||
|
@ -138,7 +138,7 @@ func Properties(tokenID []byte) map[string]interface{} {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BalanceOf returns overall number of domains owned by the specified owner.
|
// BalanceOf returns the overall number of domains owned by the specified owner.
|
||||||
func BalanceOf(owner interop.Hash160) int {
|
func BalanceOf(owner interop.Hash160) int {
|
||||||
if !isValid(owner) {
|
if !isValid(owner) {
|
||||||
panic(`invalid owner`)
|
panic(`invalid owner`)
|
||||||
|
@ -166,7 +166,7 @@ func TokensOf(owner interop.Hash160) iterator.Iterator {
|
||||||
return storage.Find(ctx, append([]byte{prefixAccountToken}, owner...), storage.ValuesOnly)
|
return storage.Find(ctx, append([]byte{prefixAccountToken}, owner...), storage.ValuesOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer transfers domain with the specified name to new owner.
|
// Transfer transfers the domain with the specified name to a new owner.
|
||||||
func Transfer(to interop.Hash160, tokenID []byte, data interface{}) bool {
|
func Transfer(to interop.Hash160, tokenID []byte, data interface{}) bool {
|
||||||
if !isValid(to) {
|
if !isValid(to) {
|
||||||
panic(`invalid receiver`)
|
panic(`invalid receiver`)
|
||||||
|
@ -218,7 +218,7 @@ func GetPrice() int {
|
||||||
return storage.Get(ctx, []byte{prefixRegisterPrice}).(int)
|
return storage.Get(ctx, []byte{prefixRegisterPrice}).(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsAvailable checks whether provided domain name is available.
|
// IsAvailable checks whether the provided domain name is available.
|
||||||
func IsAvailable(name string) bool {
|
func IsAvailable(name string) bool {
|
||||||
fragments := splitAndCheck(name, false)
|
fragments := splitAndCheck(name, false)
|
||||||
if fragments == nil {
|
if fragments == nil {
|
||||||
|
@ -235,7 +235,7 @@ func IsAvailable(name string) bool {
|
||||||
return parentExpired(ctx, 0, fragments)
|
return parentExpired(ctx, 0, fragments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parentExpired returns true if any domain from fragments doesn't exist or expired.
|
// parentExpired returns true if any domain from fragments doesn't exist or is expired.
|
||||||
// first denotes the deepest subdomain to check.
|
// first denotes the deepest subdomain to check.
|
||||||
func parentExpired(ctx storage.Context, first int, fragments []string) bool {
|
func parentExpired(ctx storage.Context, first int, fragments []string) bool {
|
||||||
now := runtime.GetTime()
|
now := runtime.GetTime()
|
||||||
|
@ -257,7 +257,7 @@ func parentExpired(ctx storage.Context, first int, fragments []string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register registers new domain with the specified owner and name if it's available.
|
// Register registers a new domain with the specified owner and name if it's available.
|
||||||
func Register(name string, owner interop.Hash160, email string, refresh, retry, expire, ttl int) bool {
|
func Register(name string, owner interop.Hash160, email string, refresh, retry, expire, ttl int) bool {
|
||||||
fragments := splitAndCheck(name, true)
|
fragments := splitAndCheck(name, true)
|
||||||
if fragments == nil {
|
if fragments == nil {
|
||||||
|
@ -343,7 +343,7 @@ func Renew(name string) int {
|
||||||
return ns.Expiration
|
return ns.Expiration
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateSOA update soa record.
|
// UpdateSOA updates soa record.
|
||||||
func UpdateSOA(name, email string, refresh, retry, expire, ttl int) {
|
func UpdateSOA(name, email string, refresh, retry, expire, ttl int) {
|
||||||
if len(name) > maxDomainNameLength {
|
if len(name) > maxDomainNameLength {
|
||||||
panic("invalid domain name format")
|
panic("invalid domain name format")
|
||||||
|
@ -369,7 +369,7 @@ func SetAdmin(name string, admin interop.Hash160) {
|
||||||
putNameState(ctx, ns)
|
putNameState(ctx, ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetRecord adds new record of the specified type to the provided domain.
|
// SetRecord adds a new record of the specified type to the provided domain.
|
||||||
func SetRecord(name string, typ RecordType, id byte, data string) {
|
func SetRecord(name string, typ RecordType, id byte, data string) {
|
||||||
tokenID := []byte(tokenIDFromName(name))
|
tokenID := []byte(tokenIDFromName(name))
|
||||||
if !checkBaseRecords(typ, data) {
|
if !checkBaseRecords(typ, data) {
|
||||||
|
@ -397,7 +397,7 @@ func checkBaseRecords(typ RecordType, data string) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddRecord adds new record of the specified type to the provided domain.
|
// AddRecord adds a new record of the specified type to the provided domain.
|
||||||
func AddRecord(name string, typ RecordType, data string) {
|
func AddRecord(name string, typ RecordType, data string) {
|
||||||
tokenID := []byte(tokenIDFromName(name))
|
tokenID := []byte(tokenIDFromName(name))
|
||||||
if !checkBaseRecords(typ, data) {
|
if !checkBaseRecords(typ, data) {
|
||||||
|
@ -443,7 +443,7 @@ func Resolve(name string, typ RecordType) []string {
|
||||||
return resolve(ctx, nil, name, typ, 2)
|
return resolve(ctx, nil, name, typ, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllRecords returns an Iterator with RecordState items for given name.
|
// GetAllRecords returns an Iterator with RecordState items for the given name.
|
||||||
func GetAllRecords(name string) iterator.Iterator {
|
func GetAllRecords(name string) iterator.Iterator {
|
||||||
tokenID := []byte(tokenIDFromName(name))
|
tokenID := []byte(tokenIDFromName(name))
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
@ -490,7 +490,7 @@ func getTotalSupply(ctx storage.Context) int {
|
||||||
return val.(int)
|
return val.(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateTotalSupply adds specified diff to the total supply.
|
// updateTotalSupply adds the specified diff to the total supply.
|
||||||
func updateTotalSupply(ctx storage.Context, diff int) {
|
func updateTotalSupply(ctx storage.Context, diff int) {
|
||||||
tsKey := []byte{prefixTotalSupply}
|
tsKey := []byte{prefixTotalSupply}
|
||||||
ts := getTotalSupply(ctx)
|
ts := getTotalSupply(ctx)
|
||||||
|
@ -587,7 +587,7 @@ func addRecord(ctx storage.Context, tokenId []byte, name string, typ RecordType,
|
||||||
storeRecord(ctx, recordKey, name, typ, id, data)
|
storeRecord(ctx, recordKey, name, typ, id, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// storeRecord put record to storage.
|
// storeRecord puts record to storage.
|
||||||
func storeRecord(ctx storage.Context, recordKey []byte, name string, typ RecordType, id byte, data string) {
|
func storeRecord(ctx storage.Context, recordKey []byte, name string, typ RecordType, id byte, data string) {
|
||||||
rs := RecordState{
|
rs := RecordState{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
@ -644,19 +644,19 @@ func updateSoaSerial(ctx storage.Context, tokenId []byte) {
|
||||||
storage.Put(ctx, recordKey, recBytes)
|
storage.Put(ctx, recordKey, recBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRecordsKey returns prefix used to store domain records of different types.
|
// getRecordsKey returns the prefix used to store domain records of different types.
|
||||||
func getRecordsKey(tokenId []byte, name string) []byte {
|
func getRecordsKey(tokenId []byte, name string) []byte {
|
||||||
recordKey := append([]byte{prefixRecord}, getTokenKey(tokenId)...)
|
recordKey := append([]byte{prefixRecord}, getTokenKey(tokenId)...)
|
||||||
return append(recordKey, getTokenKey([]byte(name))...)
|
return append(recordKey, getTokenKey([]byte(name))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getRecordsKeyByType returns key used to store domain records.
|
// getRecordsKeyByType returns the key used to store domain records.
|
||||||
func getRecordsKeyByType(tokenId []byte, name string, typ RecordType) []byte {
|
func getRecordsKeyByType(tokenId []byte, name string, typ RecordType) []byte {
|
||||||
recordKey := getRecordsKey(tokenId, name)
|
recordKey := getRecordsKey(tokenId, name)
|
||||||
return append(recordKey, byte(typ))
|
return append(recordKey, byte(typ))
|
||||||
}
|
}
|
||||||
|
|
||||||
// getIdRecordKey returns key used to store domain records.
|
// getIdRecordKey returns the key used to store domain records.
|
||||||
func getIdRecordKey(tokenId []byte, name string, typ RecordType, id byte) []byte {
|
func getIdRecordKey(tokenId []byte, name string, typ RecordType, id byte) []byte {
|
||||||
recordKey := getRecordsKey(tokenId, name)
|
recordKey := getRecordsKey(tokenId, name)
|
||||||
return append(recordKey, byte(typ), id)
|
return append(recordKey, byte(typ), id)
|
||||||
|
@ -682,7 +682,7 @@ func checkCommittee() {
|
||||||
|
|
||||||
// checkFragment validates root or a part of domain name.
|
// checkFragment validates root or a part of domain name.
|
||||||
// 1. Root domain must start with a letter.
|
// 1. Root domain must start with a letter.
|
||||||
// 2. All other fragments must start and end in a letter or a digit.
|
// 2. All other fragments must start and end with a letter or a digit.
|
||||||
func checkFragment(v string, isRoot bool) bool {
|
func checkFragment(v string, isRoot bool) bool {
|
||||||
maxLength := maxDomainNameFragmentLength
|
maxLength := maxDomainNameFragmentLength
|
||||||
if isRoot {
|
if isRoot {
|
||||||
|
@ -843,7 +843,7 @@ func checkIPv6(data string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// tokenIDFromName returns token ID (domain.root) from provided name.
|
// tokenIDFromName returns token ID (domain.root) from the provided name.
|
||||||
func tokenIDFromName(name string) string {
|
func tokenIDFromName(name string) string {
|
||||||
fragments := splitAndCheck(name, true)
|
fragments := splitAndCheck(name, true)
|
||||||
if fragments == nil {
|
if fragments == nil {
|
||||||
|
@ -868,7 +868,7 @@ func tokenIDFromName(name string) string {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolve resolves provided name using record with the specified type and given
|
// resolve resolves the provided name using record with the specified type and given
|
||||||
// maximum redirections constraint.
|
// maximum redirections constraint.
|
||||||
func resolve(ctx storage.Context, res []string, name string, typ RecordType, redirect int) []string {
|
func resolve(ctx storage.Context, res []string, name string, typ RecordType, redirect int) []string {
|
||||||
if redirect < 0 {
|
if redirect < 0 {
|
||||||
|
|
|
@ -3,7 +3,7 @@ package nns
|
||||||
// RecordType is domain name service record types.
|
// RecordType is domain name service record types.
|
||||||
type RecordType byte
|
type RecordType byte
|
||||||
|
|
||||||
// Record types defined in [RFC 1035](https://tools.ietf.org/html/rfc1035)
|
// Record types are defined in [RFC 1035](https://tools.ietf.org/html/rfc1035)
|
||||||
const (
|
const (
|
||||||
// A represents address record type.
|
// A represents address record type.
|
||||||
A RecordType = 1
|
A RecordType = 1
|
||||||
|
@ -15,7 +15,7 @@ const (
|
||||||
TXT RecordType = 16
|
TXT RecordType = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
// Record types defined in [RFC 3596](https://tools.ietf.org/html/rfc3596)
|
// Record types are defined in [RFC 3596](https://tools.ietf.org/html/rfc3596)
|
||||||
const (
|
const (
|
||||||
// AAAA represents IPv6 address record type.
|
// AAAA represents IPv6 address record type.
|
||||||
AAAA RecordType = 28
|
AAAA RecordType = 28
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
/*
|
/*
|
||||||
Processing contract is a contract deployed in NeoFS main chain.
|
Processing contract is a contract deployed in NeoFS mainchain.
|
||||||
|
|
||||||
Processing contract pays for all multi signature transaction executions when notary
|
Processing contract pays for all multisignature transaction executions when notary
|
||||||
service enabled in main chain. Notary service prepares multi signed transaction,
|
service is enabled in the mainchain. Notary service prepares multisigned transactions,
|
||||||
however they should contain side chain GAS to be executed. It is inconvenient to
|
however they should contain sidechain GAS to be executed. It is inconvenient to
|
||||||
ask Alphabet nodes to pay for these transactions: nodes can change over time,
|
ask Alphabet nodes to pay for these transactions: nodes can change over time,
|
||||||
some nodes will spend side chain GAS faster, it creates economic instability.
|
some nodes will spend sidechain GAS faster. It leads to economic instability.
|
||||||
|
|
||||||
Processing contract exists to solve this issue. At the Withdraw invocation of
|
Processing contract exists to solve this issue. At the Withdraw invocation of
|
||||||
NeoFS contract, user pays fee directly to this contract. This fee is used to
|
NeoFS contract, a user pays fee directly to this contract. This fee is used to
|
||||||
pay for Cheque invocation of NeoFS contract that returns main chain GAS back
|
pay for Cheque invocation of NeoFS contract that returns mainchain GAS back
|
||||||
to the user. Address of the Processing contract is uses as the first signer in
|
to the user. The address of the Processing contract is used as the first signer in
|
||||||
the multi signature transaction. Therefore NeoVM executes Verify method of the
|
the multisignature transaction. Therefore, NeoVM executes Verify method of the
|
||||||
contract and if invocation is verified, then Processing contract pays for the
|
contract and if invocation is verified, Processing contract pays for the
|
||||||
execution.
|
execution.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
|
@ -48,8 +48,8 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("processing contract initialized")
|
runtime.Log("processing contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by side chain committee.
|
// only by the sidechain committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
blockHeight := ledger.CurrentIndex()
|
blockHeight := ledger.CurrentIndex()
|
||||||
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
||||||
|
@ -64,7 +64,7 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("processing contract updated")
|
runtime.Log("processing contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify method returns true if transaction contains valid multi signature of
|
// Verify method returns true if transaction contains valid multisignature of
|
||||||
// Alphabet nodes of the Inner Ring.
|
// Alphabet nodes of the Inner Ring.
|
||||||
func Verify() bool {
|
func Verify() bool {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
@ -74,7 +74,7 @@ func Verify() bool {
|
||||||
return runtime.CheckWitness(multiaddr)
|
return runtime.CheckWitness(multiaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
20
proxy/doc.go
20
proxy/doc.go
|
@ -1,18 +1,18 @@
|
||||||
/*
|
/*
|
||||||
Proxy contract is a contract deployed in NeoFS side chain.
|
Proxy contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Proxy contract pays for all multi signature transaction executions when notary
|
Proxy contract pays for all multisignature transaction executions when notary
|
||||||
service enabled in side chain. Notary service prepares multi signed transaction,
|
service is enabled in the sidechain. Notary service prepares multisigned transactions,
|
||||||
however they should contain side chain GAS to be executed. It is inconvenient to
|
however they should contain sidechain GAS to be executed. It is inconvenient to
|
||||||
ask Alphabet nodes to pay for these transactions: nodes can change over time,
|
ask Alphabet nodes to pay for these transactions: nodes can change over time,
|
||||||
some nodes will spend side chain GAS faster, it creates economic instability.
|
some nodes will spend sidechain GAS faster. It leads to economic instability.
|
||||||
|
|
||||||
Proxy contract exists to solve this issue. While Alphabet contracts hold all
|
Proxy contract exists to solve this issue. While Alphabet contracts hold all
|
||||||
side chain NEO, proxy contract holds most of the side chain GAS. Alphabet
|
sidechain NEO, proxy contract holds most of the sidechain GAS. Alphabet
|
||||||
contracts emits half of the available GAS to the proxy contract. Address of the
|
contracts emit half of the available GAS to the proxy contract. The address of the
|
||||||
Proxy contract is used as the first signer in the multi signature transaction.
|
Proxy contract is used as the first signer in a multisignature transaction.
|
||||||
Therefore NeoVM executes Verify method of the contract and if invocation is
|
Therefore, NeoVM executes Verify method of the contract; and if invocation is
|
||||||
verified, then Proxy contract pays for the execution.
|
verified, Proxy contract pays for the execution.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("proxy contract initialized")
|
runtime.Log("proxy contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -40,7 +40,7 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("proxy contract updated")
|
runtime.Log("proxy contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify method returns true if transaction contains valid multi signature of
|
// Verify method returns true if transaction contains valid multisignature of
|
||||||
// Alphabet nodes of the Inner Ring.
|
// Alphabet nodes of the Inner Ring.
|
||||||
func Verify() bool {
|
func Verify() bool {
|
||||||
alphabet := neo.GetCommittee()
|
alphabet := neo.GetCommittee()
|
||||||
|
@ -54,7 +54,7 @@ func Verify() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
/*
|
/*
|
||||||
Reputation contract is a contract deployed in NeoFS side chain.
|
Reputation contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Inner Ring nodes produce data audit for each container in each epoch. In the end
|
Inner Ring nodes produce data audit for each container during each epoch. In the end,
|
||||||
nodes produce DataAuditResult structure that contains information about audit
|
nodes produce DataAuditResult structure that contains information about audit
|
||||||
progress. Reputation contract provides storage for such structures and simple
|
progress. Reputation contract provides storage for such structures and simple
|
||||||
interface to iterate over available DataAuditResults on specified epoch.
|
interface to iterate over available DataAuditResults on specified epoch.
|
||||||
|
|
||||||
During settlement process, Alphabet nodes fetch all DataAuditResult structures
|
During settlement process, Alphabet nodes fetch all DataAuditResult structures
|
||||||
from the epoch and execute balance transfers from data owners to Storage and
|
from the epoch and execute balance transfers from data owners to Storage and
|
||||||
Inner Ring nodes, if data audit succeed.
|
Inner Ring nodes if data audit succeeds.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
runtime.Log("reputation contract initialized")
|
runtime.Log("reputation contract initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -52,12 +52,12 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("reputation contract updated")
|
runtime.Log("reputation contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put method saves DataAuditResult in contract storage. Can be invoked only by
|
// Put method saves DataAuditResult in contract storage. It can be invoked only by
|
||||||
// Inner Ring nodes. Does not require multi signature invocations.
|
// Inner Ring nodes. It does not require multisignature invocations.
|
||||||
//
|
//
|
||||||
// Epoch is an epoch number when DataAuditResult structure was generated.
|
// Epoch is the epoch number when DataAuditResult structure was generated.
|
||||||
// PeerID contains public keys of Inner Ring node that produced DataAuditResult.
|
// PeerID contains public keys of the Inner Ring node that has produced DataAuditResult.
|
||||||
// Value contains stable marshaled structure of DataAuditResult.
|
// Value contains a stable marshaled structure of DataAuditResult.
|
||||||
func Put(epoch int, peerID []byte, value []byte) {
|
func Put(epoch int, peerID []byte, value []byte) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||||
|
@ -108,15 +108,15 @@ func Put(epoch int, peerID []byte, value []byte) {
|
||||||
storage.Put(ctx, key, value)
|
storage.Put(ctx, key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get method returns list of all stable marshaled DataAuditResult structures
|
// Get method returns a list of all stable marshaled DataAuditResult structures
|
||||||
// produced by specified Inner Ring node in specified epoch.
|
// produced by the specified Inner Ring node during the specified epoch.
|
||||||
func Get(epoch int, peerID []byte) [][]byte {
|
func Get(epoch int, peerID []byte) [][]byte {
|
||||||
id := storageID(epoch, peerID)
|
id := storageID(epoch, peerID)
|
||||||
return GetByID(id)
|
return GetByID(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByID method returns list of all stable marshaled DataAuditResult with
|
// GetByID method returns a list of all stable marshaled DataAuditResult with
|
||||||
// specified id. Use ListByEpoch method to obtain id.
|
// the specified id. Use ListByEpoch method to obtain the id.
|
||||||
func GetByID(id []byte) [][]byte {
|
func GetByID(id []byte) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ func getReputationKey(prefix byte, id []byte) []byte {
|
||||||
return append([]byte{prefix}, id...)
|
return append([]byte{prefix}, id...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListByEpoch returns list of IDs that may be used to get reputation data
|
// ListByEpoch returns a list of IDs that may be used to get reputation data
|
||||||
// with GetByID method.
|
// with GetByID method.
|
||||||
func ListByEpoch(epoch int) [][]byte {
|
func ListByEpoch(epoch int) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
@ -150,7 +150,7 @@ func ListByEpoch(epoch int) [][]byte {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
/*
|
/*
|
||||||
Subnet contract is a contract deployed in NeoFS side chain.
|
Subnet contract is a contract deployed in NeoFS sidechain.
|
||||||
|
|
||||||
Subnet contract stores and manages NeoFS subnetwork states. It allows registering
|
Subnet contract stores and manages NeoFS subnetwork states. It allows registering
|
||||||
and deleting subnetworks, limiting access to them and defining a list of the Storage
|
and deleting subnetworks, limiting access to them, and defining a list of the Storage
|
||||||
Nodes that can be included in them.
|
Nodes that can be included in them.
|
||||||
|
|
||||||
Contract notifications
|
Contract notifications
|
||||||
|
|
||||||
Put notification. This notification is produced when new subnetwork is
|
Put notification. This notification is produced when a new subnetwork is
|
||||||
registered by invoking Put method.
|
registered by invoking Put method.
|
||||||
|
|
||||||
Put
|
Put
|
||||||
|
|
|
@ -71,7 +71,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
storage.Put(ctx, []byte{notaryDisabledKey}, args.notaryDisabled)
|
storage.Put(ctx, []byte{notaryDisabledKey}, args.notaryDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. Can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
|
@ -83,7 +83,7 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
||||||
runtime.Log("subnet contract updated")
|
runtime.Log("subnet contract updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put creates new subnet with the specified owner and info.
|
// Put creates a new subnet with the specified owner and info.
|
||||||
func Put(id []byte, ownerKey interop.PublicKey, info []byte) {
|
func Put(id []byte, ownerKey interop.PublicKey, info []byte) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(id) != subnetIDSize {
|
if len(id) != subnetIDSize {
|
||||||
|
@ -129,7 +129,7 @@ func Put(id []byte, ownerKey interop.PublicKey, info []byte) {
|
||||||
storage.Put(ctx, stKey, info)
|
storage.Put(ctx, stKey, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get returns info about subnet with the specified id.
|
// Get returns info about the subnet with the specified id.
|
||||||
func Get(id []byte) []byte {
|
func Get(id []byte) []byte {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(id) != subnetIDSize {
|
if len(id) != subnetIDSize {
|
||||||
|
@ -145,7 +145,7 @@ func Get(id []byte) []byte {
|
||||||
return raw.([]byte)
|
return raw.([]byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes subnet with the specified id.
|
// Delete deletes the subnet with the specified id.
|
||||||
func Delete(id []byte) {
|
func Delete(id []byte) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(id) != subnetIDSize {
|
if len(id) != subnetIDSize {
|
||||||
|
@ -182,7 +182,7 @@ func Delete(id []byte) {
|
||||||
runtime.Notify("Delete", id)
|
runtime.Notify("Delete", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNodeAdmin adds new node administrator to the specified subnetwork.
|
// AddNodeAdmin adds a new node administrator to the specified subnetwork.
|
||||||
func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(subnetID) != subnetIDSize {
|
if len(subnetID) != subnetIDSize {
|
||||||
|
@ -215,7 +215,7 @@ func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNodeAdmin removes node administrator from the specified subnetwork.
|
// RemoveNodeAdmin removes node administrator from the specified subnetwork.
|
||||||
// Must be called by subnet owner only.
|
// Must be called by the subnet owner only.
|
||||||
func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(subnetID) != subnetIDSize {
|
if len(subnetID) != subnetIDSize {
|
||||||
|
@ -247,8 +247,8 @@ func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
||||||
deleteKeyFromList(ctx, adminKey, stKey)
|
deleteKeyFromList(ctx, adminKey, stKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNode adds node to the specified subnetwork.
|
// AddNode adds a node to the specified subnetwork.
|
||||||
// Must be called by subnet's owner or node administrator
|
// Must be called by the subnet's owner or the node administrator
|
||||||
// only.
|
// only.
|
||||||
func AddNode(subnetID []byte, node interop.PublicKey) {
|
func AddNode(subnetID []byte, node interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
|
@ -286,8 +286,8 @@ func AddNode(subnetID []byte, node interop.PublicKey) {
|
||||||
putKeyInList(ctx, node, stKey)
|
putKeyInList(ctx, node, stKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNode removes node from the specified subnetwork.
|
// RemoveNode removes a node from the specified subnetwork.
|
||||||
// Must be called by subnet's owner or node administrator
|
// Must be called by the subnet's owner or the node administrator
|
||||||
// only.
|
// only.
|
||||||
func RemoveNode(subnetID []byte, node interop.PublicKey) {
|
func RemoveNode(subnetID []byte, node interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
|
@ -327,8 +327,8 @@ func RemoveNode(subnetID []byte, node interop.PublicKey) {
|
||||||
runtime.Notify("RemoveNode", subnetID, node)
|
runtime.Notify("RemoveNode", subnetID, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeAllowed checks if node is included in the
|
// NodeAllowed checks if a node is included in the
|
||||||
// specified subnet or not.
|
// specified subnet.
|
||||||
func NodeAllowed(subnetID []byte, node interop.PublicKey) bool {
|
func NodeAllowed(subnetID []byte, node interop.PublicKey) bool {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(subnetID) != subnetIDSize {
|
if len(subnetID) != subnetIDSize {
|
||||||
|
@ -353,8 +353,8 @@ func NodeAllowed(subnetID []byte, node interop.PublicKey) bool {
|
||||||
return storage.Get(ctx, append(stKey, node...)) != nil
|
return storage.Get(ctx, append(stKey, node...)) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddClientAdmin adds new client administrator of the specified group in the specified subnetwork.
|
// AddClientAdmin adds a new client administrator of the specified group in the specified subnetwork.
|
||||||
// Must be called by owner only.
|
// Must be called by the owner only.
|
||||||
func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) {
|
func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(subnetID) != subnetIDSize {
|
if len(subnetID) != subnetIDSize {
|
||||||
|
@ -394,7 +394,7 @@ func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.Publ
|
||||||
|
|
||||||
// RemoveClientAdmin removes client administrator from the
|
// RemoveClientAdmin removes client administrator from the
|
||||||
// specified group in the specified subnetwork.
|
// specified group in the specified subnetwork.
|
||||||
// Must be called by owner only.
|
// Must be called by the owner only.
|
||||||
func RemoveClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) {
|
func RemoveClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(subnetID) != subnetIDSize {
|
if len(subnetID) != subnetIDSize {
|
||||||
|
@ -477,7 +477,7 @@ func AddUser(subnetID []byte, groupID []byte, userID []byte) {
|
||||||
putKeyInList(ctx, userID, stKey)
|
putKeyInList(ctx, userID, stKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveUser removes user from the specified subnetwork and group.
|
// RemoveUser removes a user from the specified subnetwork and group.
|
||||||
// Must be called by the owner or the group's admin only.
|
// Must be called by the owner or the group's admin only.
|
||||||
func RemoveUser(subnetID []byte, groupID []byte, userID []byte) {
|
func RemoveUser(subnetID []byte, groupID []byte, userID []byte) {
|
||||||
// V2 format
|
// V2 format
|
||||||
|
@ -522,8 +522,8 @@ func RemoveUser(subnetID []byte, groupID []byte, userID []byte) {
|
||||||
deleteKeyFromList(ctx, userID, stKey)
|
deleteKeyFromList(ctx, userID, stKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserAllowed returns bool that indicates if node is included in the
|
// UserAllowed returns bool that indicates if a node is included in the
|
||||||
// specified subnet or not.
|
// specified subnet.
|
||||||
func UserAllowed(subnetID []byte, user []byte) bool {
|
func UserAllowed(subnetID []byte, user []byte) bool {
|
||||||
// V2 format
|
// V2 format
|
||||||
if len(subnetID) != subnetIDSize {
|
if len(subnetID) != subnetIDSize {
|
||||||
|
@ -551,7 +551,7 @@ func UserAllowed(subnetID []byte, user []byte) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Version returns version of the contract.
|
// Version returns the version of the contract.
|
||||||
func Version() int {
|
func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ func TestVote(t *testing.T) {
|
||||||
c.Invoke(t, stackitem.Null{}, method, int64(0), []interface{}{newAlphabetPub})
|
c.Invoke(t, stackitem.Null{}, method, int64(0), []interface{}{newAlphabetPub})
|
||||||
|
|
||||||
// wait one block util
|
// wait one block util
|
||||||
// new committee is accepted
|
// a new committee is accepted
|
||||||
c.AddNewBlock(t)
|
c.AddNewBlock(t)
|
||||||
|
|
||||||
cNewAlphabet.Invoke(t, stackitem.Null{}, "emit")
|
cNewAlphabet.Invoke(t, stackitem.Null{}, "emit")
|
||||||
|
|
Loading…
Reference in a new issue