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
|
||||
[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
|
||||
- processing
|
||||
|
||||
Side chain contracts:
|
||||
Sidechain contracts:
|
||||
|
||||
- alphabet
|
||||
- audit
|
||||
|
@ -41,7 +41,7 @@ To compile smart contracts you need:
|
|||
|
||||
## 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
|
||||
corresponding directories.
|
||||
|
||||
|
@ -71,7 +71,7 @@ Remove compiled files with `make clean` or `make mr_proper` command.
|
|||
|
||||
# Testing
|
||||
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
|
||||
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")
|
||||
}
|
||||
|
||||
// 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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -81,12 +81,12 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
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 {
|
||||
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 {
|
||||
return neo.BalanceOf(runtime.GetExecutingScriptHash())
|
||||
}
|
||||
|
@ -116,16 +116,16 @@ func checkPermission(ir []interop.PublicKey) bool {
|
|||
return runtime.CheckWitness(node)
|
||||
}
|
||||
|
||||
// Emit method produces side chain GAS and distributes it among Inner Ring nodes
|
||||
// and proxy contract. Can be invoked only by Alphabet node of the Inner Ring.
|
||||
// Emit method produces sidechain GAS and distributes it among Inner Ring nodes
|
||||
// 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
|
||||
// account to itself. If notary enabled, then 50% of the GAS in the contract account
|
||||
// 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.
|
||||
// To produce GAS, an alphabet contract transfers all available NEO from the contract
|
||||
// account to itself. If notary is enabled, 50% of the GAS in the contract account
|
||||
// are transferred to proxy contract. 43.75% of the GAS are equally distributed
|
||||
// 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
|
||||
// Inner Ring nodes. Remaining 12.5% of the GAS stays in the contract.
|
||||
// If notary is disabled, 87.5% of the GAS are equally distributed among all
|
||||
// Inner Ring nodes. Remaining 12.5% of the GAS stay in the contract.
|
||||
func Emit() {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
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.
|
||||
//
|
||||
// This method is used when governance changes list of Alphabet nodes of the
|
||||
// Inner Ring. Alphabet nodes share keys with side chain validators, therefore
|
||||
// it is required to change them as well. To do that NEO holders, which are
|
||||
// alphabet contracts, should vote for new committee.
|
||||
// This method is used when governance changes the list of Alphabet nodes of the
|
||||
// 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
|
||||
// alphabet contracts) should vote for a new committee.
|
||||
func Vote(epoch int, candidates []interop.PublicKey) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -255,13 +255,13 @@ func voteID(epoch interface{}, args []interop.PublicKey) []byte {
|
|||
return crypto.Sha256(result)
|
||||
}
|
||||
|
||||
// Name returns Glagolitic name of the contract.
|
||||
// Name returns the Glagolitic name of the contract.
|
||||
func Name() string {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
return name(ctx)
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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
|
||||
validators in the side chain. NEO token is required to produce GAS and vote for
|
||||
a new committee. If can be distributed among alphabet nodes of Inner Ring.
|
||||
However, some of them may be malicious and some NEO can be lost. It will lead
|
||||
to side chain economic destabilization. To avoid it, all 100 000 000 NEO are
|
||||
Alphabet contract is designed to support GAS production and vote for new
|
||||
validators in the sidechain. NEO token is required to produce GAS and vote for
|
||||
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 destabilize
|
||||
the economic of the sidechain. To avoid it, all 100,000,000 NEO are
|
||||
distributed among all alphabet contracts.
|
||||
|
||||
To identify alphabet contracts, they are named with letters of the Glagolitic.
|
||||
Names are set at contract deploy. Alphabet nodes of Inner Ring communicate with
|
||||
To identify alphabet contracts, they are named with letters of the Glagolitic alphabet.
|
||||
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
|
||||
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.
|
||||
|
||||
Contract notifications
|
||||
|
|
|
@ -19,8 +19,8 @@ type (
|
|||
}
|
||||
)
|
||||
|
||||
// Audit key is a combination of epoch, container ID and public key of node that
|
||||
// executed audit. Together it should be no more than 64 bytes. We can't shrink
|
||||
// Audit key is a combination of the epoch, the container ID and the public key of the node that
|
||||
// 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
|
||||
// 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")
|
||||
}
|
||||
|
||||
// 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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -82,11 +82,11 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
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.
|
||||
//
|
||||
// Inner Ring nodes perform audit of the containers and produce `DataAuditResult`
|
||||
// structures. They are being stored in audit contract and used for settlements
|
||||
// Inner Ring nodes perform audit of containers and produce `DataAuditResult`
|
||||
// structures. They are stored in audit contract and used for settlements
|
||||
// in later epochs.
|
||||
func Put(rawAuditResult []byte) {
|
||||
ctx := storage.GetContext()
|
||||
|
@ -122,16 +122,16 @@ func Put(rawAuditResult []byte) {
|
|||
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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
return storage.Get(ctx, id).([]byte)
|
||||
}
|
||||
|
||||
// List method returns list of all available DataAuditResult IDs from
|
||||
// contract storage.
|
||||
// List method returns a list of all available DataAuditResult IDs from
|
||||
// the contract storage.
|
||||
func List() [][]byte {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
it := storage.Find(ctx, []byte{}, storage.KeysOnly)
|
||||
|
@ -139,8 +139,8 @@ func List() [][]byte {
|
|||
return list(it)
|
||||
}
|
||||
|
||||
// ListByEpoch method returns list of DataAuditResult IDs generated in
|
||||
// specified epoch.
|
||||
// ListByEpoch method returns a list of DataAuditResult IDs generated during
|
||||
// the specified epoch.
|
||||
func ListByEpoch(epoch int) [][]byte {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
var buf interface{} = epoch
|
||||
|
@ -149,8 +149,8 @@ func ListByEpoch(epoch int) [][]byte {
|
|||
return list(it)
|
||||
}
|
||||
|
||||
// ListByCID method returns list of DataAuditResult IDs generated in
|
||||
// specified epoch for specified container.
|
||||
// ListByCID method returns a list of DataAuditResult IDs generated during
|
||||
// the specified epoch for the specified container.
|
||||
func ListByCID(epoch int, cid []byte) [][]byte {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
||||
|
@ -162,8 +162,8 @@ func ListByCID(epoch int, cid []byte) [][]byte {
|
|||
return list(it)
|
||||
}
|
||||
|
||||
// ListByNode method returns list of DataAuditResult IDs generated in
|
||||
// specified epoch for specified container by specified Inner Ring node.
|
||||
// ListByNode method returns a list of DataAuditResult IDs generated in
|
||||
// the specified epoch for the specified container by the specified Inner Ring node.
|
||||
func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
hdr := auditHeader{
|
||||
|
@ -200,12 +200,12 @@ loop:
|
|||
return result
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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) {
|
||||
var buf interface{} = input[0]
|
||||
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.
|
||||
If container contains StorageGroup objects, then the Inner Ring node initializes
|
||||
Inner Ring nodes perform audit of the registered containers during every epoch.
|
||||
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
|
||||
node creates a DataAuditResult structure for the container. The content of this
|
||||
structure makes it possible to determine which storage nodes were examined and
|
||||
the status of these checks. Based on this information, container owner is
|
||||
structure makes it possible to determine which storage nodes have been examined and
|
||||
see the status of these checks. Regarding this information, the container owner is
|
||||
charged for data storage.
|
||||
|
||||
Audit contract is used as reliable and verifiable storage for all
|
||||
DataAuditResult structures. At the end of the data audit routine, the Inner Ring
|
||||
Audit contract is used as a reliable and verifiable storage for all
|
||||
DataAuditResult structures. At the end of data audit routine, Inner Ring
|
||||
nodes send a stable marshaled version of the DataAuditResult structure to the
|
||||
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
|
||||
|
||||
Alphabet contract does not produce notifications to process.
|
||||
Audit contract does not produce notifications to process.
|
||||
*/
|
||||
package audit
|
||||
|
|
|
@ -24,7 +24,7 @@ type (
|
|||
|
||||
// Account structure stores metadata of each NeoFS balance account.
|
||||
Account struct {
|
||||
// Active balance
|
||||
// Active balance
|
||||
Balance int
|
||||
// Until valid for lock accounts
|
||||
Until int
|
||||
|
@ -89,7 +89,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -113,13 +113,13 @@ func Decimals() int {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
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.
|
||||
func BalanceOf(account interop.Hash160) int {
|
||||
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
|
||||
// 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.
|
||||
func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
|
||||
ctx := storage.GetContext()
|
||||
return token.transfer(ctx, from, to, amount, false, nil)
|
||||
}
|
||||
|
||||
// TransferX is a method for NeoFS balance transfers from one account to
|
||||
// another. Can be invoked by account owner or by Alphabet nodes.
|
||||
// TransferX is a method for NeoFS balance to be transferred from one account to
|
||||
// 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.
|
||||
// Also TransferX method allows to transfer assets by Alphabet nodes of the
|
||||
// Inner Ring with multi signature.
|
||||
// TransferX method also allows to transfer assets by Alphabet nodes of the
|
||||
// Inner Ring with multisignature.
|
||||
func TransferX(from, to interop.Hash160, amount int, details []byte) {
|
||||
ctx := storage.GetContext()
|
||||
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")
|
||||
}
|
||||
|
||||
// Lock is a method that transfers assets from user account to lock account
|
||||
// related to the user. Can be invoked only by Alphabet nodes of the Inner Ring.
|
||||
// Lock is a method that transfers assets from a user account to the lock account
|
||||
// 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
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
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)
|
||||
}
|
||||
|
||||
// NewEpoch is a method that checks timeout on lock accounts and return assets
|
||||
// if lock is not available anymore. Can be invoked only by NewEpoch method
|
||||
// NewEpoch is a method that checks timeout on lock accounts and returns assets
|
||||
// if lock is not available anymore. It can be invoked only by NewEpoch method
|
||||
// of Netmap contract.
|
||||
//
|
||||
// Produces Transfer and TransferX notifications.
|
||||
// It produces Transfer and TransferX notifications.
|
||||
func NewEpoch(epochNum int) {
|
||||
ctx := storage.GetContext()
|
||||
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.
|
||||
// Can be invoked only by Alphabet nodes of the Inner Ring.
|
||||
// Mint is a method that transfers assets to a user account from an empty account.
|
||||
// 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
|
||||
// Deposit notification from NeoFS contract. Before that Alphabet nodes should
|
||||
// synchronize precision of main chain GAS contract and Balance contract.
|
||||
// Mint method is invoked by Alphabet nodes of the Inner Ring when they process
|
||||
// Deposit notification from NeoFS contract. Before that, Alphabet nodes should
|
||||
// synchronize precision of mainchain GAS contract and Balance contract.
|
||||
// Mint increases total supply of NEP-17 compatible NeoFS token.
|
||||
func Mint(to interop.Hash160, amount int, txDetails []byte) {
|
||||
ctx := storage.GetContext()
|
||||
|
@ -349,15 +349,15 @@ func Mint(to interop.Hash160, amount int, txDetails []byte) {
|
|||
runtime.Notify("Mint", to, amount)
|
||||
}
|
||||
|
||||
// Burn is a method that transfers assets from user account to empty account.
|
||||
// Can be invoked only by Alphabet nodes of the Inner Ring.
|
||||
// Burn is a method that transfers assets from a user account to an empty account.
|
||||
// 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
|
||||
// Cheque notification from NeoFS contract. It means that locked assets were
|
||||
// transferred to user in main chain, therefore lock account should be destroyed.
|
||||
// Before that Alphabet nodes should synchronize precision of main chain GAS
|
||||
// Burn method is invoked by Alphabet nodes of the Inner Ring when they process
|
||||
// Cheque notification from NeoFS contract. It means that locked assets have been
|
||||
// transferred to the user in the mainchain, therefore the lock account should be destroyed.
|
||||
// Before that, Alphabet nodes should synchronize precision of mainchain GAS
|
||||
// contract and Balance contract. Burn decreases total supply of NEP-17
|
||||
// compatible NeoFS token.
|
||||
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)
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
return common.Version
|
||||
}
|
||||
|
@ -484,7 +484,7 @@ func (t Token) canTransfer(ctx storage.Context, from, to interop.Hash160, amount
|
|||
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 {
|
||||
if len(addr) == 20 {
|
||||
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
|
||||
contract so in can be tracked and controlled by N3 compatible network
|
||||
Balance contract stores all NeoFS account balances. It is a NEP-17 compatible
|
||||
contract, so it can be tracked and controlled by N3 compatible network
|
||||
monitors and wallet software.
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
in special lock account. When NeoFS contract transfers GAS assets back to the
|
||||
user, lock account is destroyed with burn operation.
|
||||
in a special lock account. When NeoFS contract transfers GAS assets back to the
|
||||
user, the lock account is destroyed with burn operation.
|
||||
|
||||
Contract notifications
|
||||
|
||||
Transfer notification. This is NEP-17 standard notification.
|
||||
Transfer notification. This is a NEP-17 standard notification.
|
||||
|
||||
Transfer:
|
||||
- name: from
|
||||
|
@ -27,7 +27,7 @@ Transfer notification. This is NEP-17 standard notification.
|
|||
- name: amount
|
||||
type: Integer
|
||||
|
||||
TransferX notification. This is enhanced transfer notification with details.
|
||||
TransferX notification. This is an enhanced transfer notification with details.
|
||||
|
||||
TransferX:
|
||||
- name: from
|
||||
|
@ -39,11 +39,11 @@ TransferX notification. This is enhanced transfer notification with details.
|
|||
- name: details
|
||||
type: ByteArray
|
||||
|
||||
Lock notification. This notification is produced when Lock account has been
|
||||
created. It contains information about main chain transaction that produced
|
||||
asset lock, address of lock account and NeoFS epoch number until lock account
|
||||
is valid. Alphabet nodes of the Inner Ring catch notification and initialize
|
||||
Cheque method invocation of the NeoFS contract.
|
||||
Lock notification. This notification is produced when a lock account is
|
||||
created. It contains information about the mainchain transaction that has produced
|
||||
the asset lock, the address of the lock account and the NeoFS epoch number until which the
|
||||
lock account is valid. Alphabet nodes of the Inner Ring catch notification and initialize
|
||||
Cheque method invocation of NeoFS contract.
|
||||
|
||||
Lock:
|
||||
- name: txID
|
||||
|
@ -58,7 +58,7 @@ Cheque method invocation of the NeoFS contract.
|
|||
type: Integer
|
||||
|
||||
Mint notification. This notification is produced when user balance is
|
||||
replenished from deposit in the main chain.
|
||||
replenished from deposit in the mainchain.
|
||||
|
||||
Mint:
|
||||
- name: to
|
||||
|
@ -68,7 +68,7 @@ replenished from deposit in the main chain.
|
|||
|
||||
|
||||
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:
|
||||
- name: from
|
||||
|
|
14
common/ir.go
14
common/ir.go
|
@ -15,7 +15,7 @@ type IRNode struct {
|
|||
|
||||
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.
|
||||
func InnerRingInvoker(ir []interop.PublicKey) interop.PublicKey {
|
||||
for i := 0; i < len(ir); i++ {
|
||||
|
@ -28,14 +28,14 @@ func InnerRingInvoker(ir []interop.PublicKey) interop.PublicKey {
|
|||
return nil
|
||||
}
|
||||
|
||||
// InnerRingNodes return list of inner ring nodes from state validator role
|
||||
// in side chain.
|
||||
// InnerRingNodes return a list of inner ring nodes from state validator role
|
||||
// in the sidechain.
|
||||
func InnerRingNodes() []interop.PublicKey {
|
||||
blockHeight := ledger.CurrentIndex()
|
||||
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.
|
||||
// Work around for environments without notary support.
|
||||
func InnerRingNodesFromNetmap(sc interop.Hash160) []interop.PublicKey {
|
||||
|
@ -47,7 +47,7 @@ func InnerRingNodesFromNetmap(sc interop.Hash160) []interop.PublicKey {
|
|||
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 {
|
||||
return neo.GetCommittee()
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ func CommitteeAddress() []byte {
|
|||
return Multiaddress(committee, true)
|
||||
}
|
||||
|
||||
// Multiaddress returns default multi signature account address for N keys.
|
||||
// If committee set to true, then it is `M = N/2+1` committee account.
|
||||
// Multiaddress returns default multisignature account address for N keys.
|
||||
// If committee set to true, it is `M = N/2+1` committee account.
|
||||
func Multiaddress(n []interop.PublicKey, committee bool) []byte {
|
||||
threshold := len(n)*2/3 + 1
|
||||
if committee {
|
||||
|
|
|
@ -39,7 +39,7 @@ func ContainerFeeTransferDetails(cid []byte) []byte {
|
|||
return append(containerFeePrefix, cid...)
|
||||
}
|
||||
|
||||
// AbortWithMessage calls `runtime.Log` with passed message
|
||||
// AbortWithMessage calls `runtime.Log` with the passed message
|
||||
// and calls `ABORT` opcode.
|
||||
func AbortWithMessage(msg string) {
|
||||
runtime.Log(msg)
|
||||
|
|
|
@ -13,7 +13,7 @@ type Ballot struct {
|
|||
// ID of the voting decision.
|
||||
ID []byte
|
||||
|
||||
// Public keys of already voted inner ring nodes.
|
||||
// Public keys of the already voted inner ring nodes.
|
||||
Voters []interop.PublicKey
|
||||
|
||||
// Height of block with the last vote.
|
||||
|
@ -28,8 +28,8 @@ func InitVote(ctx storage.Context) {
|
|||
SetSerialized(ctx, voteKey, []Ballot{})
|
||||
}
|
||||
|
||||
// Vote adds ballot for the decision with specific 'id' and returns amount
|
||||
// on unique voters for that decision.
|
||||
// Vote adds ballot for the decision with a specific 'id' and returns the amount
|
||||
// of unique voters for that decision.
|
||||
func Vote(ctx storage.Context, id, from []byte) int {
|
||||
var (
|
||||
newCandidates []Ballot
|
||||
|
@ -96,7 +96,7 @@ func RemoveVotes(ctx storage.Context, id []byte) {
|
|||
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 {
|
||||
data := storage.Get(ctx, voteKey)
|
||||
if data != nil {
|
||||
|
@ -106,13 +106,13 @@ func getBallots(ctx storage.Context) []Ballot {
|
|||
return []Ballot{}
|
||||
}
|
||||
|
||||
// BytesEqual compares two slice of bytes by wrapping them into strings,
|
||||
// which is necessary with new util.Equal interop behaviour, see neo-go#1176.
|
||||
// BytesEqual compares two slices of bytes by wrapping them into strings,
|
||||
// which is necessary with new util.Equals interop behaviour, see neo-go#1176.
|
||||
func BytesEqual(a []byte, b []byte) bool {
|
||||
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.
|
||||
func InvokeID(args []interface{}, prefix []byte) []byte {
|
||||
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
|
||||
without signature collection (1 invoke transfer).
|
||||
|
||||
IR1, IR2, IR3, IR4 -(4 invokes)-> [ Container Contract ] -(1 invoke)-> [ Balance Contract ]
|
||||
|
||||
We can do 1 invoke transfer if:
|
||||
- invoke happened from inner ring node,
|
||||
- it is indirect invocation from other smart-contract.
|
||||
- invokation has happened from inner ring node,
|
||||
- it is indirect invocation from another smart-contract.
|
||||
|
||||
However there is a possible attack, when malicious inner ring node creates
|
||||
malicious smart-contract in morph chain to do indirect call.
|
||||
However, there is a possible attack, when a malicious inner ring node creates
|
||||
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.
|
||||
*/
|
||||
|
||||
|
|
|
@ -3,31 +3,31 @@ package common
|
|||
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
|
||||
|
||||
var (
|
||||
// ErrAlphabetWitnessFailed appears when method must be
|
||||
// called by Alphabet but was not.
|
||||
// ErrAlphabetWitnessFailed appears when the method must be
|
||||
// called by the Alphabet but was not.
|
||||
ErrAlphabetWitnessFailed = "alphabet witness check failed"
|
||||
// ErrOwnerWitnessFailed appears when method must be called
|
||||
// by owner of some assets but was not.
|
||||
// ErrOwnerWitnessFailed appears when the method must be called
|
||||
// by an owner of some assets but was not.
|
||||
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.
|
||||
ErrWitnessFailed = "witness check failed"
|
||||
)
|
||||
|
||||
// CheckAlphabetWitness checks witness of the passed caller.
|
||||
// Panics with ErrAlphabetWitnessFailed message on fail.
|
||||
// It panics with ErrAlphabetWitnessFailed message on fail.
|
||||
func CheckAlphabetWitness(caller []byte) {
|
||||
checkWitnessWithPanic(caller, ErrAlphabetWitnessFailed)
|
||||
}
|
||||
|
||||
// CheckOwnerWitness checks witness of the passed caller.
|
||||
// Panics with ErrOwnerWitnessFailed message on fail.
|
||||
// It panics with ErrOwnerWitnessFailed message on fail.
|
||||
func CheckOwnerWitness(caller []byte) {
|
||||
checkWitnessWithPanic(caller, ErrOwnerWitnessFailed)
|
||||
}
|
||||
|
||||
// CheckWitness checks witness of the passed caller.
|
||||
// Panics with ErrWitnessFailed message on fail.
|
||||
// It panics with ErrWitnessFailed message on fail.
|
||||
func CheckWitness(caller []byte) {
|
||||
checkWitnessWithPanic(caller, ErrWitnessFailed)
|
||||
}
|
||||
|
|
|
@ -63,11 +63,11 @@ const (
|
|||
singleEstimatePrefix = "est"
|
||||
estimateKeyPrefix = "cnr"
|
||||
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
|
||||
// TotalCleanupDelta contains number of epochs after which estimation
|
||||
// will be removed by epoch tick cleanup if any node didn't updated
|
||||
// container size and/or container was removed. Must be greater than CleanupDelta.
|
||||
// TotalCleanupDelta contains the number of the epochs after which estimation
|
||||
// will be removed by epoch tick cleanup if any of the nodes hasn't updated
|
||||
// container size and/or container has been removed. It must be greater than CleanupDelta.
|
||||
TotalCleanupDelta = CleanupDelta + 1
|
||||
|
||||
// NotFoundError is returned if container is missing.
|
||||
|
@ -84,7 +84,7 @@ var (
|
|||
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{}) {
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,8 @@ func registerNiceNameTLD(addrNNS interop.Hash160, nnsRoot string) {
|
|||
}
|
||||
}
|
||||
|
||||
// Update method updates contract source code and manifest. Can be invoked
|
||||
// only by committee.
|
||||
// Update method updates contract source code and manifest. It can be invoked
|
||||
// by committee only.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
panic("only committee can update contract")
|
||||
|
@ -157,13 +157,13 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
runtime.Log("container contract updated")
|
||||
}
|
||||
|
||||
// Put method creates new container if it was invoked by Alphabet nodes
|
||||
// of the Inner Ring. Otherwise it produces containerPut notification.
|
||||
// Put method creates a new container if it has been invoked by Alphabet nodes
|
||||
// of the Inner Ring. Otherwise, it produces containerPut notification.
|
||||
//
|
||||
// Container should be stable marshaled Container structure from API.
|
||||
// Signature is a RFC6979 signature of Container.
|
||||
// PublicKey contains public key of the signer.
|
||||
// Token is optional and should be stable marshaled SessionToken structure from
|
||||
// Container should be a stable marshaled Container structure from API.
|
||||
// Signature is a RFC6979 signature of the Container.
|
||||
// PublicKey contains the public key of the signer.
|
||||
// Token is optional and should be a stable marshaled SessionToken structure from
|
||||
// API.
|
||||
func Put(container []byte, signature interop.Signature, publicKey interop.PublicKey, token []byte) {
|
||||
PutNamed(container, signature, publicKey, token, "", "")
|
||||
|
@ -279,7 +279,7 @@ func PutNamed(container []byte, signature interop.Signature,
|
|||
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.
|
||||
func checkNiceNameAvailable(nnsContractAddr interop.Hash160, domain string) bool {
|
||||
isAvail := contract.Call(nnsContractAddr, "isAvailable",
|
||||
|
@ -303,15 +303,15 @@ func checkNiceNameAvailable(nnsContractAddr interop.Hash160, domain string) bool
|
|||
return false
|
||||
}
|
||||
|
||||
// Delete method removes container from contract storage if it was
|
||||
// invoked by Alphabet nodes of the Inner Ring. Otherwise it produces
|
||||
// Delete method removes a container from the contract storage if it has been
|
||||
// invoked by Alphabet nodes of the Inner Ring. Otherwise, it produces
|
||||
// containerDelete notification.
|
||||
//
|
||||
// Signature is a RFC6979 signature of container ID.
|
||||
// Token is optional and should be stable marshaled SessionToken structure from
|
||||
// Signature is a RFC6979 signature of the container ID.
|
||||
// Token is optional and should be a stable marshaled SessionToken structure from
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -348,8 +348,8 @@ func Delete(containerID []byte, signature interop.Signature, token []byte) {
|
|||
if len(domain) != 0 {
|
||||
storage.Delete(ctx, key)
|
||||
// We should do `getRecord` first because NNS record could be deleted
|
||||
// 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.
|
||||
// by other means (expiration, manual), thus leading to failing `deleteRecord`
|
||||
// and inability to delete a container. We should also check if we own the record in case.
|
||||
nnsContractAddr := storage.Get(ctx, nnsContractKey).(interop.Hash160)
|
||||
res := contract.Call(nnsContractAddr, "getRecords", contract.ReadStates|contract.AllowCall, domain, 16 /* TXT */)
|
||||
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)
|
||||
}
|
||||
|
||||
// Get method returns structure that contains stable marshaled Container structure,
|
||||
// signature, public key of the container creator and stable marshaled SessionToken
|
||||
// Get method returns a structure that contains a stable marshaled Container structure,
|
||||
// the signature, the public key of the container creator and a stable marshaled SessionToken
|
||||
// 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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
cnt := getContainer(ctx, containerID)
|
||||
|
@ -375,9 +375,9 @@ func Get(containerID []byte) Container {
|
|||
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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
owner := getOwnerByID(ctx, containerID)
|
||||
|
@ -387,7 +387,7 @@ func Owner(containerID []byte) []byte {
|
|||
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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
||||
|
@ -406,17 +406,17 @@ func List(owner []byte) [][]byte {
|
|||
return list
|
||||
}
|
||||
|
||||
// SetEACL method sets new extended ACL table related to the contract
|
||||
// if it was invoked by Alphabet nodes of the Inner Ring. Otherwise it produces
|
||||
// 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
|
||||
// setEACL notification.
|
||||
//
|
||||
// EACL should be stable marshaled EACLTable structure from API.
|
||||
// Signature is a RFC6979 signature of Container.
|
||||
// PublicKey contains public key of the signer.
|
||||
// Token is optional and should be stable marshaled SessionToken structure from
|
||||
// EACL should be a stable marshaled EACLTable structure from API.
|
||||
// Signature is a RFC6979 signature of the Container.
|
||||
// PublicKey contains the public key of the signer.
|
||||
// Token is optional and should be a stable marshaled SessionToken structure from
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
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)
|
||||
}
|
||||
|
||||
// EACL method returns structure that contains stable marshaled EACLTable structure,
|
||||
// signature, public key of the extended ACL setter and stable marshaled SessionToken
|
||||
// EACL method returns a structure that contains a stable marshaled EACLTable structure,
|
||||
// the signature, the public key of the extended ACL setter and a stable marshaled SessionToken
|
||||
// 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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
||||
|
@ -486,10 +486,10 @@ func EACL(containerID []byte) ExtendedACL {
|
|||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
|
||||
|
@ -516,13 +516,13 @@ func PutContainerSize(epoch int, cid []byte, usedSize int, pubKey interop.Public
|
|||
runtime.Log("saved container size estimation")
|
||||
}
|
||||
|
||||
// GetContainerSize method returns container ID and slice of container
|
||||
// estimations. Container estimation includes public key of the Storage Node
|
||||
// that registered estimation and value of estimation.
|
||||
// GetContainerSize method returns the container ID and a slice of container
|
||||
// estimations. Container estimation includes the public key of the Storage Node
|
||||
// that registered estimation and value of estimation.
|
||||
//
|
||||
// Use ID obtained from ListContainerSizes method. Estimations are removed
|
||||
// from contract storage every epoch, see NewEpoch method, therefore method
|
||||
// can return different results in different epochs.
|
||||
// Use the ID obtained from ListContainerSizes method. Estimations are removed
|
||||
// from contract storage every epoch, see NewEpoch method; therefore, this method
|
||||
// can return different results during different epochs.
|
||||
func GetContainerSize(id []byte) containerSizes {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
||||
|
@ -535,8 +535,8 @@ func GetContainerSize(id []byte) containerSizes {
|
|||
return getContainerSizeEstimation(ctx, id, cid)
|
||||
}
|
||||
|
||||
// ListContainerSizes method returns IDs of container size estimations
|
||||
// that has been registered for specified epoch.
|
||||
// ListContainerSizes method returns the IDs of container size estimations
|
||||
// that has been registered for the specified epoch.
|
||||
func ListContainerSizes(epoch int) [][]byte {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
||||
|
@ -568,7 +568,7 @@ func ListContainerSizes(epoch int) [][]byte {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -591,7 +591,7 @@ func NewEpoch(epochNum int) {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -629,7 +629,7 @@ func StartContainerEstimation(epoch int) {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -666,7 +666,7 @@ func StopContainerEstimation(epoch int) {
|
|||
runtime.Log("notification has been produced")
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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
|
||||
// announce container size estimation of previous epoch.
|
||||
// announces container size estimation of the previous epoch.
|
||||
func isStorageNode(ctx storage.Context, key interop.PublicKey) bool {
|
||||
netmapContractAddr := storage.Get(ctx, netmapContractKey).(interop.Hash160)
|
||||
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
|
||||
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.
|
||||
Alphabet nodes approve it by invoking the same Put or SetEACL methods with
|
||||
the same arguments.
|
||||
|
||||
Contract notifications
|
||||
|
||||
containerPut notification. This notification is produced when user wants to
|
||||
create new container. Alphabet nodes of the Inner Ring catch notification and
|
||||
validate container data, signature and token if it is present.
|
||||
containerPut notification. This notification is produced when a user wants to
|
||||
create a new container. Alphabet nodes of the Inner Ring catch the notification and
|
||||
validate container data, signature and token if present.
|
||||
|
||||
containerPut:
|
||||
- name: container
|
||||
|
@ -23,9 +23,9 @@ validate container data, signature and token if it is present.
|
|||
- name: token
|
||||
type: ByteArray
|
||||
|
||||
containerDelete notification. This notification is produced when container owner
|
||||
wants to delete container. Alphabet nodes of the Inner Ring catch notification
|
||||
and validate container ownership, signature and token if it is present.
|
||||
containerDelete notification. This notification is produced when a container owner
|
||||
wants to delete a container. Alphabet nodes of the Inner Ring catch the notification
|
||||
and validate container ownership, signature and token if present.
|
||||
|
||||
containerDelete:
|
||||
- name: containerID
|
||||
|
@ -35,9 +35,9 @@ and validate container ownership, signature and token if it is present.
|
|||
- name: token
|
||||
type: ByteArray
|
||||
|
||||
setEACL notification. This notification is produced when container owner wants
|
||||
to update extended ACL of the container. Alphabet nodes of the Inner Ring catch
|
||||
notification and validate container ownership, signature and token if it is
|
||||
setEACL notification. This notification is produced when a container owner wants
|
||||
to update an extended ACL of a container. Alphabet nodes of the Inner Ring catch
|
||||
the notification and validate container ownership, signature and token if
|
||||
present.
|
||||
|
||||
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
|
||||
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.
|
||||
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
|
||||
configuration are mirrored in side chain with notifications.
|
||||
Network configuration is also stored in NeoFS contract. All changes in
|
||||
configuration are mirrored in the sidechain with notifications.
|
||||
|
||||
Contract notifications
|
||||
|
||||
Deposit notification. This notification is produced when user transfers native
|
||||
GAS to the NeoFS contract address. The same amount of NEOFS token will be
|
||||
minted in Balance contract in the side chain.
|
||||
minted in Balance contract in the sidechain.
|
||||
|
||||
Deposit:
|
||||
- name: from
|
||||
|
@ -28,8 +28,8 @@ minted in Balance contract in the side chain.
|
|||
- name: txHash
|
||||
type: Hash256
|
||||
|
||||
Withdraw notification. This notification is produced when user wants to
|
||||
withdraw GAS from internal NeoFS balance and has payed fee for that.
|
||||
Withdraw notification. This notification is produced when a user wants to
|
||||
withdraw GAS from the internal NeoFS balance and has paid fee for that.
|
||||
|
||||
Withdraw:
|
||||
- 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
|
||||
successfully transferred assets back to the user after withdraw.
|
||||
has successfully transferred assets back to the user after withdraw.
|
||||
|
||||
Cheque:
|
||||
- name: id
|
||||
|
@ -53,8 +53,8 @@ successfully transferred assets back to the user after withdraw.
|
|||
- name: lockAccount
|
||||
type: ByteArray
|
||||
|
||||
Bind notification. This notification is produced when user wants to bind
|
||||
public keys with user account (OwnerID). Keys argument is array of ByteArray.
|
||||
Bind notification. This notification is produced when a user wants to bind
|
||||
public keys with the user account (OwnerID). Keys argument is an array of ByteArray.
|
||||
|
||||
Bind:
|
||||
- name: user
|
||||
|
@ -62,8 +62,8 @@ public keys with user account (OwnerID). Keys argument is array of ByteArray.
|
|||
- name: keys
|
||||
type: Array
|
||||
|
||||
Unbind notification. This notification is produced when user wants to unbind
|
||||
public keys with user account (OwnerID). Keys argument is an array of ByteArray.
|
||||
Unbind notification. This notification is produced when a user wants to unbind
|
||||
public keys with the user account (OwnerID). Keys argument is an array of ByteArray.
|
||||
|
||||
Unbind:
|
||||
- name: user
|
||||
|
@ -72,7 +72,7 @@ public keys with user account (OwnerID). Keys argument is an array of ByteArray.
|
|||
type: Array
|
||||
|
||||
AlphabetUpdate notification. This notification is produced when Alphabet nodes
|
||||
updated it's list in the contract. Alphabet argument is an array of ByteArray. It
|
||||
have updated their lists in the contract. Alphabet argument is an array of ByteArray. It
|
||||
contains public keys of new alphabet nodes.
|
||||
|
||||
AlphabetUpdate:
|
||||
|
|
|
@ -103,8 +103,8 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
runtime.Log("neofs: contract initialized")
|
||||
}
|
||||
|
||||
// Update method updates contract source code and manifest. Can be invoked
|
||||
// only by side chain committee.
|
||||
// Update method updates contract source code and manifest. It can be invoked
|
||||
// only by sidechain committee.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
blockHeight := ledger.CurrentIndex()
|
||||
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")
|
||||
}
|
||||
|
||||
// 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.
|
||||
func AlphabetList() []common.IRNode {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
@ -129,14 +129,14 @@ func AlphabetList() []common.IRNode {
|
|||
return nodes
|
||||
}
|
||||
|
||||
// AlphabetAddress returns 2\3n+1 multi signature address of alphabet nodes.
|
||||
// Used in side chain notary disabled environment.
|
||||
// AlphabetAddress returns 2\3n+1 multisignature address of alphabet nodes.
|
||||
// It is used in sidechain notary disabled environment.
|
||||
func AlphabetAddress() interop.Hash160 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
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.
|
||||
func InnerRingCandidates() []common.IRNode {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
@ -150,10 +150,10 @@ func InnerRingCandidates() []common.IRNode {
|
|||
return nodes
|
||||
}
|
||||
|
||||
// InnerRingCandidateRemove removes key from the list of Inner Ring candidates.
|
||||
// Can be invoked by Alphabet nodes or candidate itself.
|
||||
// InnerRingCandidateRemove removes a key from a list of Inner Ring candidates.
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
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.
|
||||
// Can be invoked only by candidate itself.
|
||||
// InnerRingCandidateAdd adds a key to a list of Inner Ring candidates.
|
||||
// It can be invoked only by the candidate itself.
|
||||
//
|
||||
// This method transfers fee from candidate to contract account.
|
||||
// Fee value specified in NeoFS network config with the key InnerRingCandidateFee.
|
||||
// This method transfers fee from a candidate to the contract account.
|
||||
// Fee value is specified in NeoFS network config with the key InnerRingCandidateFee.
|
||||
func InnerRingCandidateAdd(key interop.PublicKey) {
|
||||
ctx := storage.GetContext()
|
||||
|
||||
|
@ -230,7 +230,7 @@ func InnerRingCandidateAdd(key interop.PublicKey) {
|
|||
}
|
||||
|
||||
// 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
|
||||
// break JSON limits for integers when precision is converted.
|
||||
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)
|
||||
}
|
||||
|
||||
// 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.
|
||||
//
|
||||
// This method produces Withdraw notification to lock assets in side chain and
|
||||
// transfers withdraw fee from user account to each Alphabet node. If notary
|
||||
// is enabled in main chain, fee is transferred to Processing contract.
|
||||
// Fee value specified in NeoFS network config with the key WithdrawFee.
|
||||
// This method produces Withdraw notification to lock assets in the sidechain and
|
||||
// transfers withdraw fee from a user account to each Alphabet node. If notary
|
||||
// is enabled in the mainchain, fee is transferred to Processing contract.
|
||||
// Fee value is specified in NeoFS network config with the key WithdrawFee.
|
||||
func Withdraw(user interop.Hash160, amount int) {
|
||||
if !runtime.CheckWitness(user) {
|
||||
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)
|
||||
}
|
||||
|
||||
// Cheque transfers GAS back to the user from contract account, if assets were
|
||||
// successfully locked in NeoFS balance contract. Can be invoked only by
|
||||
// Cheque transfers GAS back to the user from the contract account, if assets were
|
||||
// successfully locked in NeoFS balance contract. It can be invoked only by
|
||||
// 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) {
|
||||
ctx := storage.GetContext()
|
||||
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)
|
||||
}
|
||||
|
||||
// Bind method produces notification to bind specified public keys in NeoFSID
|
||||
// contract in side chain. Can be invoked only by specified user.
|
||||
// Bind method produces notification to bind the specified public keys in NeoFSID
|
||||
// contract in the sidechain. It can be invoked only by specified user.
|
||||
//
|
||||
// This method produces Bind notification. Method panics if keys are not
|
||||
// 33 byte long. User argument must be valid 20 byte script hash.
|
||||
// This method produces Bind notification. This method panics if keys are not
|
||||
// 33 byte long. User argument must be a valid 20 byte script hash.
|
||||
func Bind(user []byte, keys []interop.PublicKey) {
|
||||
if !runtime.CheckWitness(user) {
|
||||
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)
|
||||
}
|
||||
|
||||
// Unbind method produces notification to unbind specified public keys in NeoFSID
|
||||
// contract in side chain. Can be invoked only by specified user.
|
||||
// Unbind method produces notification to unbind the specified public keys in NeoFSID
|
||||
// contract in the sidechain. It can be invoked only by the specified user.
|
||||
//
|
||||
// This method produces Unbind notification. Method panics if keys are not
|
||||
// 33 byte long. User argument must be valid 20 byte script hash.
|
||||
// This method produces Unbind notification. This method panics if keys are not
|
||||
// 33 byte long. User argument must be a valid 20 byte script hash.
|
||||
func Unbind(user []byte, keys []interop.PublicKey) {
|
||||
if !runtime.CheckWitness(user) {
|
||||
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)
|
||||
}
|
||||
|
||||
// AlphabetUpdate updates list of alphabet nodes with provided list of
|
||||
// public keys. Can be invoked only by alphabet nodes.
|
||||
// AlphabetUpdate updates a list of alphabet nodes with the provided list of
|
||||
// public keys. It can be invoked only by alphabet nodes.
|
||||
//
|
||||
// This method used in notary disabled side chain environment. In this case
|
||||
// actual alphabet list should be stored in the NeoFS contract.
|
||||
// This method is used in notary disabled sidechain environment. In this case,
|
||||
// the actual alphabet list should be stored in the NeoFS contract.
|
||||
func AlphabetUpdate(id []byte, args []interop.PublicKey) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -460,14 +460,14 @@ func AlphabetUpdate(id []byte, args []interop.PublicKey) {
|
|||
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.
|
||||
func Config(key []byte) interface{} {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
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.
|
||||
func SetConfig(id, key, val []byte) {
|
||||
ctx := storage.GetContext()
|
||||
|
@ -506,7 +506,7 @@ func SetConfig(id, key, val []byte) {
|
|||
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.
|
||||
func ListConfig() []record {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
@ -532,7 +532,7 @@ func Version() int {
|
|||
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 {
|
||||
data := storage.Get(ctx, alphabetKey)
|
||||
if data != nil {
|
||||
|
@ -542,7 +542,7 @@ func getAlphabetNodes(ctx storage.Context) []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{} {
|
||||
postfix := key.([]byte)
|
||||
storageKey := append(configPrefix, postfix...)
|
||||
|
@ -550,7 +550,7 @@ func getConfig(ctx storage.Context, key interface{}) interface{} {
|
|||
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{}) {
|
||||
postfix := key.([]byte)
|
||||
storageKey := append(configPrefix, postfix...)
|
||||
|
@ -558,7 +558,7 @@ func setConfig(ctx storage.Context, key, val interface{}) {
|
|||
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.
|
||||
func multiaddress(keys []interop.PublicKey) []byte {
|
||||
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.
|
||||
OwnerID is a 25-byte N3 wallet address that can be produced from public key.
|
||||
It is one-way conversion. In simple cases NeoFS verifies ownership by checking
|
||||
signature and relation between public key and OwnerID.
|
||||
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 a public key.
|
||||
It is one-way conversion. In simple cases, NeoFS verifies ownership by checking
|
||||
signature and relation between a public key and an OwnerID.
|
||||
|
||||
In more complex cases, user can use public keys unrelated to OwnerID to maintain
|
||||
secure access to the data. NeoFSID contract stores relation between OwnerID and
|
||||
arbitrary public keys. Data owner can bind or unbind public key with it's account
|
||||
by invoking Bind or Unbind methods of NeoFS contract in main chain. After that,
|
||||
Alphabet nodes produce multi signed AddKey and RemoveKey invocations of NeoFSID
|
||||
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 an OwnerID and
|
||||
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 the mainchain. After that,
|
||||
Alphabet nodes produce multisigned AddKey and RemoveKey invocations of NeoFSID
|
||||
contract.
|
||||
|
||||
Contract notifications
|
||||
|
|
|
@ -60,7 +60,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -72,11 +72,11 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
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.
|
||||
//
|
||||
// This method panics if OwnerID is not ownerSize byte or public key is not 33 byte long.
|
||||
// If key is already bound, ignores it.
|
||||
// This method panics if the OwnerID is not an ownerSize byte or the public key is not 33 byte long.
|
||||
// If the key is already bound, the method ignores it.
|
||||
func AddKey(owner []byte, keys []interop.PublicKey) {
|
||||
// V2 format
|
||||
if len(owner) != ownerSize {
|
||||
|
@ -135,11 +135,11 @@ func AddKey(owner []byte, keys []interop.PublicKey) {
|
|||
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.
|
||||
//
|
||||
// This method panics if OwnerID is not ownerSize byte or public key is not 33 byte long.
|
||||
// If key is already unbound, ignores it.
|
||||
// This method panics if the OwnerID is not an ownerSize byte or the public key is not 33 byte long.
|
||||
// If the key is already unbound, the method ignores it.
|
||||
func RemoveKey(owner []byte, keys []interop.PublicKey) {
|
||||
// V2 format
|
||||
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 {
|
||||
// V2 format
|
||||
if len(owner) != ownerSize {
|
||||
|
@ -207,7 +207,7 @@ func Key(owner []byte) [][]byte {
|
|||
return info.Keys
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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
|
||||
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
|
||||
|
||||
AddPeer notification. This notification is produced when Storage node sends
|
||||
bootstrap request by invoking AddPeer method.
|
||||
AddPeer notification. This notification is produced when a Storage node sends
|
||||
a bootstrap request by invoking AddPeer method.
|
||||
|
||||
AddPeer
|
||||
- name: nodeInfo
|
||||
type: ByteArray
|
||||
|
||||
UpdateState notification. This notification is produced when Storage node wants
|
||||
to change it's state (go offline) by invoking UpdateState method. Supported
|
||||
UpdateState notification. This notification is produced when a Storage node wants
|
||||
to change its state (go offline) by invoking UpdateState method. Supported
|
||||
states: (2) -- offline.
|
||||
|
||||
UpdateState
|
||||
|
@ -24,7 +24,7 @@ states: (2) -- offline.
|
|||
- name: 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.
|
||||
|
||||
NewEpoch
|
||||
|
|
|
@ -122,7 +122,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -134,11 +134,11 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
runtime.Log("netmap contract updated")
|
||||
}
|
||||
|
||||
// InnerRingList method returns slice of structures that contains public key of
|
||||
// Inner Ring node. Should be used only in notary disabled environment.
|
||||
// InnerRingList method returns a slice of structures that contains the public key of
|
||||
// an Inner Ring node. It should be used in notary disabled environment only.
|
||||
//
|
||||
// If notary enabled, then look to NeoFSAlphabet role in native RoleManagement
|
||||
// contract of the side chain.
|
||||
// If notary is enabled, look to NeoFSAlphabet role in native RoleManagement
|
||||
// contract of the sidechain.
|
||||
func InnerRingList() []common.IRNode {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
pubs := getIRNodes(ctx)
|
||||
|
@ -149,11 +149,11 @@ func InnerRingList() []common.IRNode {
|
|||
return nodes
|
||||
}
|
||||
|
||||
// UpdateInnerRing method updates list of Inner Ring node keys. Should be used
|
||||
// only in notary disabled environment. Can be invoked only by Alphabet nodes.
|
||||
// UpdateInnerRing method updates a list of Inner Ring node keys. It should be used
|
||||
// only in notary disabled environment. It can be invoked only by Alphabet nodes.
|
||||
//
|
||||
// If notary enabled, then update NeoFSAlphabet role in native RoleManagement
|
||||
// contract of the side chain. Use notary service to collect multi signature.
|
||||
// If notary is enabled, update NeoFSAlphabet role in native RoleManagement
|
||||
// contract of the sidechain. Use notary service to collect multisignature.
|
||||
func UpdateInnerRing(keys []interop.PublicKey) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -190,8 +190,8 @@ func UpdateInnerRing(keys []interop.PublicKey) {
|
|||
common.SetSerialized(ctx, innerRingKey, keys)
|
||||
}
|
||||
|
||||
// AddPeerIR method tries to add new candidate to the network map.
|
||||
// Should only be invoked in notary-enabled environment by the alphabet.
|
||||
// AddPeerIR method tries to add a new candidate to the network map.
|
||||
// It should only be invoked in notary-enabled environment by the alphabet.
|
||||
func AddPeerIR(nodeInfo []byte) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -207,12 +207,12 @@ func AddPeerIR(nodeInfo []byte) {
|
|||
runtime.Notify("AddPeerSuccess", interop.PublicKey(publicKey))
|
||||
}
|
||||
|
||||
// AddPeer method adds new candidate to the next network map if it was invoked
|
||||
// by Alphabet node. If it was invoked by node candidate, it produces AddPeer
|
||||
// notification. Otherwise method throws panic.
|
||||
// AddPeer method adds a new candidate to the next network map if it was invoked
|
||||
// by Alphabet node. If it was invoked by a node candidate, it produces AddPeer
|
||||
// notification. Otherwise, the method throws panic.
|
||||
//
|
||||
// If the candidate already exists, it's info is updated.
|
||||
// NodeInfo argument contains stable marshaled version of netmap.NodeInfo
|
||||
// If the candidate already exists, its info is updated.
|
||||
// NodeInfo argument contains a stable marshaled version of netmap.NodeInfo
|
||||
// structure.
|
||||
func AddPeer(nodeInfo []byte) {
|
||||
ctx := storage.GetContext()
|
||||
|
@ -262,11 +262,11 @@ func AddPeer(nodeInfo []byte) {
|
|||
runtime.Notify("AddPeerSuccess", interop.PublicKey(publicKey))
|
||||
}
|
||||
|
||||
// UpdateState method updates state of node from the network map candidate list.
|
||||
// For notary-ENABLED environment tx must be signed by both storage node and the alphabet.
|
||||
// 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 alphabet.
|
||||
// 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.
|
||||
// 2. If it was signed by a storage node, emit `UpdateState` notification.
|
||||
// 2. Fail in any other case.
|
||||
|
@ -276,7 +276,7 @@ func AddPeer(nodeInfo []byte) {
|
|||
// | ENABLED | FAIL | FAIL | OK |
|
||||
// | DISABLED | NOTIFICATION | OK | OK (same as alphabet) |
|
||||
// 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.
|
||||
func UpdateState(state int, publicKey interop.PublicKey) {
|
||||
|
@ -324,8 +324,8 @@ func UpdateState(state int, publicKey interop.PublicKey) {
|
|||
runtime.Notify("UpdateStateSuccess", publicKey, state)
|
||||
}
|
||||
|
||||
// UpdateStateIR method tries to change node state in the network map.
|
||||
// Should only be invoked in notary-enabled environment by the alphabet.
|
||||
// UpdateStateIR method tries to change the node state in the network map.
|
||||
// Should only be invoked in notary-enabled environment by alphabet.
|
||||
func UpdateStateIR(state nodeState, publicKey interop.PublicKey) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -344,15 +344,15 @@ func UpdateStateIR(state nodeState, publicKey interop.PublicKey) {
|
|||
runtime.Notify("UpdateStateSuccess", publicKey, state)
|
||||
}
|
||||
|
||||
// NewEpoch method changes epoch number up to provided epochNum argument. Can
|
||||
// be invoked only by Alphabet nodes. If provided epoch number is less or equal
|
||||
// current epoch number, method throws panic.
|
||||
// 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 than the
|
||||
// current epoch number or equals it, the method throws panic.
|
||||
//
|
||||
// When epoch number updated, contract sets storage node candidates as current
|
||||
// network map. Also contract invokes NewEpoch method on Balance and Container
|
||||
// When epoch number is updated, the contract sets storage node candidates as the current
|
||||
// network map. The contract also invokes NewEpoch method on Balance and Container
|
||||
// contracts.
|
||||
//
|
||||
// Produces NewEpoch notification.
|
||||
// It produces NewEpoch notification.
|
||||
func NewEpoch(epochNum int) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -411,41 +411,41 @@ func NewEpoch(epochNum int) {
|
|||
runtime.Notify("NewEpoch", epochNum)
|
||||
}
|
||||
|
||||
// Epoch method returns current epoch number.
|
||||
// Epoch method returns the current epoch number.
|
||||
func Epoch() int {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
return storage.Get(ctx, snapshotBlockKey).(int)
|
||||
}
|
||||
|
||||
// Netmap method returns list of structures that contain byte array of stable
|
||||
// marshalled netmap.NodeInfo structure. These structure contain Storage nodes
|
||||
// of current epoch.
|
||||
// Netmap method returns a list of structures that contain a byte array of a stable
|
||||
// marshalled netmap.NodeInfo structure. These structures contain Storage nodes
|
||||
// of the current epoch.
|
||||
func Netmap() []storageNode {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
id := storage.Get(ctx, snapshotCurrentIDKey).(int)
|
||||
return getSnapshot(ctx, snapshotKeyPrefix+string([]byte{byte(id)}))
|
||||
}
|
||||
|
||||
// NetmapCandidates method returns list of structures that contain node state
|
||||
// and byte array of stable marshalled netmap.NodeInfo structure.
|
||||
// These structure contain Storage node candidates for next epoch.
|
||||
// NetmapCandidates method returns a list of structures that contain the node state
|
||||
// and a byte array of a stable marshalled netmap.NodeInfo structure.
|
||||
// These structures contain Storage node candidates for the next epoch.
|
||||
func NetmapCandidates() []netmapNode {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
return getNetmapNodes(ctx)
|
||||
}
|
||||
|
||||
// Snapshot method returns list of structures that contain node state
|
||||
// (online: 1) and byte array of stable marshalled netmap.NodeInfo structure.
|
||||
// These structure contain Storage nodes of specified epoch.
|
||||
// Snapshot method returns a list of structures that contain the node state
|
||||
// (online: 1) and a byte array of a stable marshalled netmap.NodeInfo structure.
|
||||
// These structures contain Storage nodes of the specified epoch.
|
||||
//
|
||||
// Netmap contract contains only two recent network map snapshot: current and
|
||||
// previous epoch. For diff bigger than 1 or less than 0 method throws panic.
|
||||
// Netmap contract contains only two recent network map snapshots: current and
|
||||
// previous epoch. For diff bigger than 1 or less than 0, the method throws panic.
|
||||
func Snapshot(diff int) []storageNode {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
count := getSnapshotCount(ctx)
|
||||
|
@ -463,9 +463,9 @@ func getSnapshotCount(ctx storage.Context) int {
|
|||
return storage.Get(ctx, snapshotCountKey).(int)
|
||||
}
|
||||
|
||||
// UpdateSnapshotCount updates number of stored snapshots.
|
||||
// If new number is less than the old one, old snapshots are removed.
|
||||
// Otherwise, history is extended to with empty snapshots, so
|
||||
// UpdateSnapshotCount updates the number of the stored snapshots.
|
||||
// If a new number is less than the old one, old snapshots are removed.
|
||||
// Otherwise, history is extended with empty snapshots, so
|
||||
// `Snapshot` method can return invalid results for `diff = new-old` epochs
|
||||
// until `diff` epochs have passed.
|
||||
func UpdateSnapshotCount(count int) {
|
||||
|
@ -545,9 +545,9 @@ func moveSnapshot(ctx storage.Context, from, to int) {
|
|||
storage.Put(ctx, keyTo, data)
|
||||
}
|
||||
|
||||
// SnapshotByEpoch method returns list of structures that contain node state
|
||||
// (online: 1) and byte array of stable marshalled netmap.NodeInfo structure.
|
||||
// These structure contain Storage nodes of specified epoch.
|
||||
// SnapshotByEpoch method returns a list of structures that contain the node state
|
||||
// (online: 1) and a byte array of a stable marshalled netmap.NodeInfo structure.
|
||||
// These structures contain Storage nodes of the specified epoch.
|
||||
//
|
||||
// Netmap contract contains only two recent network map snapshot: current and
|
||||
// previous epoch. For all others epoch method throws panic.
|
||||
|
@ -565,7 +565,7 @@ func Config(key []byte) interface{} {
|
|||
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.
|
||||
func SetConfig(id, key, val []byte) {
|
||||
ctx := storage.GetContext()
|
||||
|
@ -603,7 +603,7 @@ func SetConfig(id, key, val []byte) {
|
|||
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.
|
||||
func ListConfig() []record {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
@ -624,7 +624,7 @@ func ListConfig() []record {
|
|||
return config
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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,
|
||||
thus it's NeoNameService. This token can be minted with new domain name
|
||||
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
|
||||
|
||||
|
@ -26,7 +26,7 @@ import (
|
|||
const (
|
||||
// prefixTotalSupply contains total supply of minted domains.
|
||||
prefixTotalSupply byte = 0x00
|
||||
// prefixBalance contains map from owner to his balance.
|
||||
// prefixBalance contains map from the owner to their balance.
|
||||
prefixBalance byte = 0x01
|
||||
// prefixAccountToken contains map from (owner + token key) to token ID,
|
||||
// where token key = hash160(token ID) and token ID = domain name.
|
||||
|
@ -110,25 +110,25 @@ func Decimals() int {
|
|||
return 0
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
return getTotalSupply(ctx)
|
||||
}
|
||||
|
||||
// OwnerOf returns owner of the specified domain.
|
||||
// OwnerOf returns the owner of the specified domain.
|
||||
func OwnerOf(tokenID []byte) interop.Hash160 {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
ns := getNameState(ctx, tokenID)
|
||||
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{} {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
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 {
|
||||
if !isValid(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)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if !isValid(to) {
|
||||
panic(`invalid receiver`)
|
||||
|
@ -218,7 +218,7 @@ func GetPrice() 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 {
|
||||
fragments := splitAndCheck(name, false)
|
||||
if fragments == nil {
|
||||
|
@ -235,7 +235,7 @@ func IsAvailable(name string) bool {
|
|||
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.
|
||||
func parentExpired(ctx storage.Context, first int, fragments []string) bool {
|
||||
now := runtime.GetTime()
|
||||
|
@ -257,7 +257,7 @@ func parentExpired(ctx storage.Context, first int, fragments []string) bool {
|
|||
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 {
|
||||
fragments := splitAndCheck(name, true)
|
||||
if fragments == nil {
|
||||
|
@ -343,7 +343,7 @@ func Renew(name string) int {
|
|||
return ns.Expiration
|
||||
}
|
||||
|
||||
// UpdateSOA update soa record.
|
||||
// UpdateSOA updates soa record.
|
||||
func UpdateSOA(name, email string, refresh, retry, expire, ttl int) {
|
||||
if len(name) > maxDomainNameLength {
|
||||
panic("invalid domain name format")
|
||||
|
@ -369,7 +369,7 @@ func SetAdmin(name string, admin interop.Hash160) {
|
|||
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) {
|
||||
tokenID := []byte(tokenIDFromName(name))
|
||||
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) {
|
||||
tokenID := []byte(tokenIDFromName(name))
|
||||
if !checkBaseRecords(typ, data) {
|
||||
|
@ -443,7 +443,7 @@ func Resolve(name string, typ RecordType) []string {
|
|||
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 {
|
||||
tokenID := []byte(tokenIDFromName(name))
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
@ -490,7 +490,7 @@ func getTotalSupply(ctx storage.Context) 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) {
|
||||
tsKey := []byte{prefixTotalSupply}
|
||||
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 put record to storage.
|
||||
// storeRecord puts record to storage.
|
||||
func storeRecord(ctx storage.Context, recordKey []byte, name string, typ RecordType, id byte, data string) {
|
||||
rs := RecordState{
|
||||
Name: name,
|
||||
|
@ -644,19 +644,19 @@ func updateSoaSerial(ctx storage.Context, tokenId []byte) {
|
|||
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 {
|
||||
recordKey := append([]byte{prefixRecord}, getTokenKey(tokenId)...)
|
||||
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 {
|
||||
recordKey := getRecordsKey(tokenId, name)
|
||||
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 {
|
||||
recordKey := getRecordsKey(tokenId, name)
|
||||
return append(recordKey, byte(typ), id)
|
||||
|
@ -682,7 +682,7 @@ func checkCommittee() {
|
|||
|
||||
// checkFragment validates root or a part of domain name.
|
||||
// 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 {
|
||||
maxLength := maxDomainNameFragmentLength
|
||||
if isRoot {
|
||||
|
@ -843,7 +843,7 @@ func checkIPv6(data string) bool {
|
|||
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 {
|
||||
fragments := splitAndCheck(name, true)
|
||||
if fragments == nil {
|
||||
|
@ -868,7 +868,7 @@ func tokenIDFromName(name string) string {
|
|||
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.
|
||||
func resolve(ctx storage.Context, res []string, name string, typ RecordType, redirect int) []string {
|
||||
if redirect < 0 {
|
||||
|
|
|
@ -3,7 +3,7 @@ package nns
|
|||
// RecordType is domain name service record types.
|
||||
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 (
|
||||
// A represents address record type.
|
||||
A RecordType = 1
|
||||
|
@ -15,7 +15,7 @@ const (
|
|||
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 (
|
||||
// AAAA represents IPv6 address record type.
|
||||
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
|
||||
service enabled in main chain. Notary service prepares multi signed transaction,
|
||||
however they should contain side chain GAS to be executed. It is inconvenient to
|
||||
Processing contract pays for all multisignature transaction executions when notary
|
||||
service is enabled in the mainchain. Notary service prepares multisigned transactions,
|
||||
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,
|
||||
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
|
||||
NeoFS contract, 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
|
||||
to the user. Address of the Processing contract is uses as the first signer in
|
||||
the multi signature transaction. Therefore NeoVM executes Verify method of the
|
||||
contract and if invocation is verified, then Processing contract pays for the
|
||||
NeoFS contract, a user pays fee directly to this contract. This fee is used to
|
||||
pay for Cheque invocation of NeoFS contract that returns mainchain GAS back
|
||||
to the user. The address of the Processing contract is used as the first signer in
|
||||
the multisignature transaction. Therefore, NeoVM executes Verify method of the
|
||||
contract and if invocation is verified, Processing contract pays for the
|
||||
execution.
|
||||
|
||||
Contract notifications
|
||||
|
|
|
@ -48,8 +48,8 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
runtime.Log("processing contract initialized")
|
||||
}
|
||||
|
||||
// Update method updates contract source code and manifest. Can be invoked
|
||||
// only by side chain committee.
|
||||
// Update method updates contract source code and manifest. It can be invoked
|
||||
// only by the sidechain committee.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
blockHeight := ledger.CurrentIndex()
|
||||
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")
|
||||
}
|
||||
|
||||
// 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.
|
||||
func Verify() bool {
|
||||
ctx := storage.GetContext()
|
||||
|
@ -74,7 +74,7 @@ func Verify() bool {
|
|||
return runtime.CheckWitness(multiaddr)
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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
|
||||
service enabled in side chain. Notary service prepares multi signed transaction,
|
||||
however they should contain side chain GAS to be executed. It is inconvenient to
|
||||
Proxy contract pays for all multisignature transaction executions when notary
|
||||
service is enabled in the sidechain. Notary service prepares multisigned transactions,
|
||||
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,
|
||||
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
|
||||
side chain NEO, proxy contract holds most of the side chain GAS. Alphabet
|
||||
contracts emits half of the available GAS to the proxy contract. Address of the
|
||||
Proxy contract is used as the first signer in the multi signature transaction.
|
||||
Therefore NeoVM executes Verify method of the contract and if invocation is
|
||||
verified, then Proxy contract pays for the execution.
|
||||
sidechain NEO, proxy contract holds most of the sidechain GAS. Alphabet
|
||||
contracts emit half of the available GAS to the proxy contract. The address of the
|
||||
Proxy contract is used as the first signer in a multisignature transaction.
|
||||
Therefore, NeoVM executes Verify method of the contract; and if invocation is
|
||||
verified, Proxy contract pays for the execution.
|
||||
|
||||
Contract notifications
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -40,7 +40,7 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
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.
|
||||
func Verify() bool {
|
||||
alphabet := neo.GetCommittee()
|
||||
|
@ -54,7 +54,7 @@ func Verify() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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
|
||||
progress. Reputation contract provides storage for such structures and simple
|
||||
interface to iterate over available DataAuditResults on specified epoch.
|
||||
|
||||
During settlement process, Alphabet nodes fetch all DataAuditResult structures
|
||||
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
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -52,12 +52,12 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
runtime.Log("reputation contract updated")
|
||||
}
|
||||
|
||||
// Put method saves DataAuditResult in contract storage. Can be invoked only by
|
||||
// Inner Ring nodes. Does not require multi signature invocations.
|
||||
// Put method saves DataAuditResult in contract storage. It can be invoked only by
|
||||
// Inner Ring nodes. It does not require multisignature invocations.
|
||||
//
|
||||
// Epoch is an epoch number when DataAuditResult structure was generated.
|
||||
// PeerID contains public keys of Inner Ring node that produced DataAuditResult.
|
||||
// Value contains stable marshaled structure of DataAuditResult.
|
||||
// Epoch is the epoch number when DataAuditResult structure was generated.
|
||||
// PeerID contains public keys of the Inner Ring node that has produced DataAuditResult.
|
||||
// Value contains a stable marshaled structure of DataAuditResult.
|
||||
func Put(epoch int, peerID []byte, value []byte) {
|
||||
ctx := storage.GetContext()
|
||||
notaryDisabled := storage.Get(ctx, notaryDisabledKey).(bool)
|
||||
|
@ -108,15 +108,15 @@ func Put(epoch int, peerID []byte, value []byte) {
|
|||
storage.Put(ctx, key, value)
|
||||
}
|
||||
|
||||
// Get method returns list of all stable marshaled DataAuditResult structures
|
||||
// produced by specified Inner Ring node in specified epoch.
|
||||
// Get method returns a list of all stable marshaled DataAuditResult structures
|
||||
// produced by the specified Inner Ring node during the specified epoch.
|
||||
func Get(epoch int, peerID []byte) [][]byte {
|
||||
id := storageID(epoch, peerID)
|
||||
return GetByID(id)
|
||||
}
|
||||
|
||||
// GetByID method returns list of all stable marshaled DataAuditResult with
|
||||
// specified id. Use ListByEpoch method to obtain id.
|
||||
// GetByID method returns a list of all stable marshaled DataAuditResult with
|
||||
// the specified id. Use ListByEpoch method to obtain the id.
|
||||
func GetByID(id []byte) [][]byte {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
||||
|
@ -133,7 +133,7 @@ func getReputationKey(prefix byte, id []byte) []byte {
|
|||
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.
|
||||
func ListByEpoch(epoch int) [][]byte {
|
||||
ctx := storage.GetReadOnlyContext()
|
||||
|
@ -150,7 +150,7 @@ func ListByEpoch(epoch int) [][]byte {
|
|||
return result
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
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
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
Put
|
||||
|
|
|
@ -71,7 +71,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
|||
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.
|
||||
func Update(script []byte, manifest []byte, data interface{}) {
|
||||
if !common.HasUpdateAccess() {
|
||||
|
@ -83,7 +83,7 @@ func Update(script []byte, manifest []byte, data interface{}) {
|
|||
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) {
|
||||
// V2 format
|
||||
if len(id) != subnetIDSize {
|
||||
|
@ -129,7 +129,7 @@ func Put(id []byte, ownerKey interop.PublicKey, info []byte) {
|
|||
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 {
|
||||
// V2 format
|
||||
if len(id) != subnetIDSize {
|
||||
|
@ -145,7 +145,7 @@ func Get(id []byte) []byte {
|
|||
return raw.([]byte)
|
||||
}
|
||||
|
||||
// Delete deletes subnet with the specified id.
|
||||
// Delete deletes the subnet with the specified id.
|
||||
func Delete(id []byte) {
|
||||
// V2 format
|
||||
if len(id) != subnetIDSize {
|
||||
|
@ -182,7 +182,7 @@ func Delete(id []byte) {
|
|||
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) {
|
||||
// V2 format
|
||||
if len(subnetID) != subnetIDSize {
|
||||
|
@ -215,7 +215,7 @@ func AddNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
|||
}
|
||||
|
||||
// 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) {
|
||||
// V2 format
|
||||
if len(subnetID) != subnetIDSize {
|
||||
|
@ -247,8 +247,8 @@ func RemoveNodeAdmin(subnetID []byte, adminKey interop.PublicKey) {
|
|||
deleteKeyFromList(ctx, adminKey, stKey)
|
||||
}
|
||||
|
||||
// AddNode adds node to the specified subnetwork.
|
||||
// Must be called by subnet's owner or node administrator
|
||||
// AddNode adds a node to the specified subnetwork.
|
||||
// Must be called by the subnet's owner or the node administrator
|
||||
// only.
|
||||
func AddNode(subnetID []byte, node interop.PublicKey) {
|
||||
// V2 format
|
||||
|
@ -286,8 +286,8 @@ func AddNode(subnetID []byte, node interop.PublicKey) {
|
|||
putKeyInList(ctx, node, stKey)
|
||||
}
|
||||
|
||||
// RemoveNode removes node from the specified subnetwork.
|
||||
// Must be called by subnet's owner or node administrator
|
||||
// RemoveNode removes a node from the specified subnetwork.
|
||||
// Must be called by the subnet's owner or the node administrator
|
||||
// only.
|
||||
func RemoveNode(subnetID []byte, node interop.PublicKey) {
|
||||
// V2 format
|
||||
|
@ -327,8 +327,8 @@ func RemoveNode(subnetID []byte, node interop.PublicKey) {
|
|||
runtime.Notify("RemoveNode", subnetID, node)
|
||||
}
|
||||
|
||||
// NodeAllowed checks if node is included in the
|
||||
// specified subnet or not.
|
||||
// NodeAllowed checks if a node is included in the
|
||||
// specified subnet.
|
||||
func NodeAllowed(subnetID []byte, node interop.PublicKey) bool {
|
||||
// V2 format
|
||||
if len(subnetID) != subnetIDSize {
|
||||
|
@ -353,8 +353,8 @@ func NodeAllowed(subnetID []byte, node interop.PublicKey) bool {
|
|||
return storage.Get(ctx, append(stKey, node...)) != nil
|
||||
}
|
||||
|
||||
// AddClientAdmin adds new client administrator of the specified group in the specified subnetwork.
|
||||
// Must be called by owner only.
|
||||
// AddClientAdmin adds a new client administrator of the specified group in the specified subnetwork.
|
||||
// Must be called by the owner only.
|
||||
func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.PublicKey) {
|
||||
// V2 format
|
||||
if len(subnetID) != subnetIDSize {
|
||||
|
@ -394,7 +394,7 @@ func AddClientAdmin(subnetID []byte, groupID []byte, adminPublicKey interop.Publ
|
|||
|
||||
// RemoveClientAdmin removes client administrator from the
|
||||
// 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) {
|
||||
// V2 format
|
||||
if len(subnetID) != subnetIDSize {
|
||||
|
@ -477,7 +477,7 @@ func AddUser(subnetID []byte, groupID []byte, userID []byte) {
|
|||
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.
|
||||
func RemoveUser(subnetID []byte, groupID []byte, userID []byte) {
|
||||
// V2 format
|
||||
|
@ -522,8 +522,8 @@ func RemoveUser(subnetID []byte, groupID []byte, userID []byte) {
|
|||
deleteKeyFromList(ctx, userID, stKey)
|
||||
}
|
||||
|
||||
// UserAllowed returns bool that indicates if node is included in the
|
||||
// specified subnet or not.
|
||||
// UserAllowed returns bool that indicates if a node is included in the
|
||||
// specified subnet.
|
||||
func UserAllowed(subnetID []byte, user []byte) bool {
|
||||
// V2 format
|
||||
if len(subnetID) != subnetIDSize {
|
||||
|
@ -551,7 +551,7 @@ func UserAllowed(subnetID []byte, user []byte) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Version returns version of the contract.
|
||||
// Version returns the version of the contract.
|
||||
func Version() int {
|
||||
return common.Version
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ func TestVote(t *testing.T) {
|
|||
c.Invoke(t, stackitem.Null{}, method, int64(0), []interface{}{newAlphabetPub})
|
||||
|
||||
// wait one block util
|
||||
// new committee is accepted
|
||||
// a new committee is accepted
|
||||
c.AddNewBlock(t)
|
||||
|
||||
cNewAlphabet.Invoke(t, stackitem.Null{}, "emit")
|
||||
|
|
Loading…
Reference in a new issue