[#722] neofs-adm: Allow to initialize local dump

Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgenii Stratonikov 2022-04-07 15:47:13 +03:00 committed by LeL
parent c55950bd70
commit efb6545bfe
14 changed files with 498 additions and 134 deletions

View file

@ -13,7 +13,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
@ -57,11 +56,19 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
} }
ns, err := getNativeHashes(c) ns, err := getNativeHashes(c)
if err != nil || ns[nativenames.Gas].Equals(util.Uint160{}) { if err != nil {
return errors.New("can't fetch hash of the GAS contract") return fmt.Errorf("can't fetch the list of native contracts: %w", err)
} }
gasHash := ns[nativenames.Gas] gasHash, ok := ns[nativenames.Gas]
if !ok {
return fmt.Errorf("can't find the %s native contract hash", nativenames.Gas)
}
desigHash, ok := ns[nativenames.Designation]
if !ok {
return fmt.Errorf("can't find the %s native contract hash", nativenames.Designation)
}
if !notaryEnabled || dumpStorage || dumpAlphabet || dumpProxy { if !notaryEnabled || dumpStorage || dumpAlphabet || dumpProxy {
nnsCs, err = c.GetContractStateByID(1) nnsCs, err = c.GetContractStateByID(1)
@ -75,7 +82,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
} }
} }
irList, err := fetchIRNodes(c, nmHash) irList, err := fetchIRNodes(c, nmHash, desigHash)
if err != nil { if err != nil {
return err return err
} }
@ -86,7 +93,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
printBalances(cmd, "Inner ring nodes balances:", irList) printBalances(cmd, "Inner ring nodes balances:", irList)
if dumpStorage { if dumpStorage {
res, err := c.InvokeFunction(nmHash, "netmap", []smartcontract.Parameter{}, nil) res, err := invokeFunction(c, nmHash, "netmap", []interface{}{}, nil)
if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 { if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 {
return errors.New("can't fetch the list of storage nodes") return errors.New("can't fetch the list of storage nodes")
} }
@ -170,7 +177,7 @@ func dumpBalances(cmd *cobra.Command, _ []string) error {
return nil return nil
} }
func fetchIRNodes(c Client, nmHash util.Uint160) ([]accBalancePair, error) { func fetchIRNodes(c Client, nmHash, desigHash util.Uint160) ([]accBalancePair, error) {
var irList []accBalancePair var irList []accBalancePair
if notaryEnabled { if notaryEnabled {
@ -179,7 +186,7 @@ func fetchIRNodes(c Client, nmHash util.Uint160) ([]accBalancePair, error) {
return nil, fmt.Errorf("can't get block height: %w", err) return nil, fmt.Errorf("can't get block height: %w", err)
} }
arr, err := c.GetDesignatedByRole(noderoles.NeoFSAlphabet, height) arr, err := getDesignatedByRole(c, desigHash, noderoles.NeoFSAlphabet, height)
if err != nil { if err != nil {
return nil, errors.New("can't fetch list of IR nodes from the netmap contract") return nil, errors.New("can't fetch list of IR nodes from the netmap contract")
} }
@ -189,7 +196,7 @@ func fetchIRNodes(c Client, nmHash util.Uint160) ([]accBalancePair, error) {
irList[i].scriptHash = arr[i].GetScriptHash() irList[i].scriptHash = arr[i].GetScriptHash()
} }
} else { } else {
res, err := c.InvokeFunction(nmHash, "innerRingList", []smartcontract.Parameter{}, nil) res, err := invokeFunction(c, nmHash, "innerRingList", []interface{}{}, nil)
if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 { if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 {
return nil, errors.New("can't fetch list of IR nodes from the netmap contract") return nil, errors.New("can't fetch list of IR nodes from the netmap contract")
} }

View file

@ -9,7 +9,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
@ -49,8 +48,7 @@ func dumpContainers(cmd *cobra.Command, _ []string) error {
} }
} }
res, err := c.InvokeFunction(ch, "list", res, err := invokeFunction(c, ch, "list", []interface{}{""}, nil)
[]smartcontract.Parameter{{Type: smartcontract.StringType, Value: ""}}, nil)
if err != nil { if err != nil {
return fmt.Errorf("%w: %v", errInvalidContainerResponse, err) return fmt.Errorf("%w: %v", errInvalidContainerResponse, err)
} }

View file

@ -8,9 +8,7 @@ import (
"fmt" "fmt"
"text/tabwriter" "text/tabwriter"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
@ -160,8 +158,7 @@ func dumpNetworkConfig(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("can't get netmap contract hash: %w", err) return fmt.Errorf("can't get netmap contract hash: %w", err)
} }
res, err := c.InvokeFunction(nmHash, "listConfig", res, err := invokeFunction(c, nmHash, "listConfig", nil, nil)
[]smartcontract.Parameter{}, []transaction.Signer{{}})
if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 { if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 {
return errors.New("can't fetch list of network config keys from the netmap contract") return errors.New("can't fetch list of network config keys from the netmap contract")
} }

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
@ -29,7 +28,7 @@ func forceNewEpochCmd(cmd *cobra.Command, args []string) error {
return fmt.Errorf("can't get netmap contract hash: %w", err) return fmt.Errorf("can't get netmap contract hash: %w", err)
} }
res, err := wCtx.Client.InvokeFunction(nmHash, "epoch", []smartcontract.Parameter{}, nil) res, err := invokeFunction(wCtx.Client, nmHash, "epoch", nil, nil)
if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 { if err != nil || res.State != vm.HaltState.String() || len(res.Stack) == 0 {
return errors.New("can't fetch current epoch from the netmap contract") return errors.New("can't fetch current epoch from the netmap contract")
} }

View file

@ -51,6 +51,7 @@ func initializeSideChainCmd(cmd *cobra.Command, args []string) error {
if err != nil { if err != nil {
return fmt.Errorf("initialization error: %w", err) return fmt.Errorf("initialization error: %w", err)
} }
defer initCtx.close()
// 1. Transfer funds to committee accounts. // 1. Transfer funds to committee accounts.
cmd.Println("Stage 1: transfer GAS to alphabet nodes.") cmd.Println("Stage 1: transfer GAS to alphabet nodes.")
@ -98,6 +99,16 @@ func initializeSideChainCmd(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func (c *initializeContext) close() {
if local, ok := c.Client.(*localClient); ok {
err := local.dump()
if err != nil {
c.Command.PrintErrf("Can't write dump: %v\n", err)
os.Exit(1)
}
}
}
func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) { func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContext, error) {
walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag)) walletDir := config.ResolveHomePath(viper.GetString(alphabetWalletsFlag))
wallets, err := openAlphabetWallets(walletDir) wallets, err := openAlphabetWallets(walletDir)
@ -110,7 +121,18 @@ func newInitializeContext(cmd *cobra.Command, v *viper.Viper) (*initializeContex
return nil, err return nil, err
} }
c, err := getN3Client(v) var c Client
if v.GetString(localDumpFlag) != "" {
if cmd.Name() != "init" {
return nil, errors.New("dump creation is only supported for `init` command")
}
if v.GetString(endpointFlag) != "" {
return nil, fmt.Errorf("`%s` and `%s` flags are mutually exclusive", endpointFlag, localDumpFlag)
}
c, err = newLocalClient(v, wallets)
} else {
c, err = getN3Client(v)
}
if err != nil { if err != nil {
return nil, fmt.Errorf("can't create N3 client: %w", err) return nil, fmt.Errorf("can't create N3 client: %w", err)
} }
@ -287,6 +309,12 @@ func (c *clientContext) awaitTx(cmd *cobra.Command) error {
return nil return nil
} }
if local, ok := c.Client.(*localClient); ok {
if err := local.putTransactions(); err != nil {
return fmt.Errorf("can't persist transactions: %w", err)
}
}
cmd.Println("Waiting for transactions to persist...") cmd.Println("Waiting for transactions to persist...")
tick := time.NewTicker(c.PollInterval) tick := time.NewTicker(c.PollInterval)
@ -304,8 +332,8 @@ loop:
res, err := c.Client.GetApplicationLog(c.Hashes[i], &at) res, err := c.Client.GetApplicationLog(c.Hashes[i], &at)
if err == nil { if err == nil {
if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vm.HaltState { if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vm.HaltState {
retErr = fmt.Errorf("tx persisted in %s state: %s", retErr = fmt.Errorf("tx %d persisted in %s state: %s",
res.Executions[0].VMState, res.Executions[0].FaultException) i, res.Executions[0].VMState, res.Executions[0].FaultException)
} }
continue loop continue loop
} }
@ -315,8 +343,8 @@ loop:
res, err := c.Client.GetApplicationLog(c.Hashes[i], &at) res, err := c.Client.GetApplicationLog(c.Hashes[i], &at)
if err == nil { if err == nil {
if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vm.HaltState { if retErr == nil && len(res.Executions) > 0 && res.Executions[0].VMState != vm.HaltState {
retErr = fmt.Errorf("tx persisted in %s state: %s", retErr = fmt.Errorf("tx %d persisted in %s state: %s",
res.Executions[0].VMState, res.Executions[0].FaultException) i, res.Executions[0].VMState, res.Executions[0].FaultException)
} }
continue loop continue loop
} }

View file

@ -125,7 +125,7 @@ func (c *initializeContext) deployNNS(method string) error {
mgmtHash = nnsCs.Hash mgmtHash = nnsCs.Hash
} }
res, err := c.Client.InvokeFunction(mgmtHash, method, params, []transaction.Signer{signer}) res, err := invokeFunction(c.Client, mgmtHash, method, params, []transaction.Signer{signer})
if err != nil { if err != nil {
return fmt.Errorf("can't deploy NNS contract: %w", err) return fmt.Errorf("can't deploy NNS contract: %w", err)
} }
@ -161,7 +161,7 @@ func (c *initializeContext) updateContracts() error {
totalGasCost := int64(0) totalGasCost := int64(0)
w := io2.NewBufBinWriter() w := io2.NewBufBinWriter()
var keysParam []smartcontract.Parameter var keysParam []interface{}
// Update script size for a single-node committee is close to the maximum allowed size of 65535. // Update script size for a single-node committee is close to the maximum allowed size of 65535.
// Because of this we want to reuse alphabet contract NEF and manifest for different updates. // Because of this we want to reuse alphabet contract NEF and manifest for different updates.
@ -184,10 +184,7 @@ func (c *initializeContext) updateContracts() error {
return fmt.Errorf("can't resolve hash for contract update: %w", err) return fmt.Errorf("can't resolve hash for contract update: %w", err)
} }
keysParam = append(keysParam, smartcontract.Parameter{ keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes())
Type: smartcontract.PublicKeyType,
Value: acc.PrivateKey().PublicKey().Bytes(),
})
params := c.getAlphabetDeployItems(i, len(c.Wallets)) params := c.getAlphabetDeployItems(i, len(c.Wallets))
emit.Array(w.BinWriter, params...) emit.Array(w.BinWriter, params...)
@ -243,7 +240,7 @@ func (c *initializeContext) updateContracts() error {
Scopes: transaction.Global, Scopes: transaction.Global,
} }
res, err := c.Client.InvokeFunction(invokeHash, method, params, []transaction.Signer{signer}) res, err := invokeFunction(c.Client, invokeHash, method, params, []transaction.Signer{signer})
if err != nil { if err != nil {
return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) return fmt.Errorf("can't deploy %s contract: %w", ctrName, err)
} }
@ -287,7 +284,7 @@ func (c *initializeContext) deployContracts() error {
mgmtHash := c.nativeHash(nativenames.Management) mgmtHash := c.nativeHash(nativenames.Management)
alphaCs := c.getContract(alphabetContract) alphaCs := c.getContract(alphabetContract)
var keysParam []smartcontract.Parameter var keysParam []interface{}
// alphabet contracts should be deployed by individual nodes to get different hashes. // alphabet contracts should be deployed by individual nodes to get different hashes.
for i, acc := range c.Accounts { for i, acc := range c.Accounts {
@ -298,15 +295,12 @@ func (c *initializeContext) deployContracts() error {
} }
invokeHash := mgmtHash invokeHash := mgmtHash
keysParam = append(keysParam, smartcontract.Parameter{ keysParam = append(keysParam, acc.PrivateKey().PublicKey().Bytes())
Type: smartcontract.PublicKeyType,
Value: acc.PrivateKey().PublicKey().Bytes(),
})
params := getContractDeployParameters(alphaCs.RawNEF, alphaCs.RawManifest, params := getContractDeployParameters(alphaCs.RawNEF, alphaCs.RawManifest,
c.getAlphabetDeployParameters(i, len(c.Wallets))) c.getAlphabetDeployItems(i, len(c.Wallets)))
res, err := c.Client.InvokeFunction(invokeHash, deployMethodName, params, []transaction.Signer{{ res, err := invokeFunction(c.Client, invokeHash, deployMethodName, params, []transaction.Signer{{
Account: acc.Contract.ScriptHash(), Account: acc.Contract.ScriptHash(),
Scopes: transaction.CalledByEntry, Scopes: transaction.CalledByEntry,
}}) }})
@ -344,7 +338,7 @@ func (c *initializeContext) deployContracts() error {
Scopes: transaction.Global, Scopes: transaction.Global,
} }
res, err := c.Client.InvokeFunction(invokeHash, deployMethodName, params, []transaction.Signer{signer}) res, err := invokeFunction(c.Client, invokeHash, deployMethodName, params, []transaction.Signer{signer})
if err != nil { if err != nil {
return fmt.Errorf("can't deploy %s contract: %w", ctrName, err) return fmt.Errorf("can't deploy %s contract: %w", ctrName, err)
} }
@ -497,43 +491,29 @@ func readContractsFromArchive(file io.Reader, names []string) (map[string]*contr
return m, nil return m, nil
} }
func getContractDeployParameters(rawNef, rawManif []byte, deployData []smartcontract.Parameter) []smartcontract.Parameter { func getContractDeployParameters(rawNef, rawManif []byte, deployData []interface{}) []interface{} {
return []smartcontract.Parameter{ return []interface{}{rawNef, rawManif, deployData}
{
Type: smartcontract.ByteArrayType,
Value: rawNef,
},
{
Type: smartcontract.ByteArrayType,
Value: rawManif,
},
{
Type: smartcontract.ArrayType,
Value: deployData,
},
}
} }
func (c *initializeContext) getContractDeployData(ctrName string, keysParam []smartcontract.Parameter) []smartcontract.Parameter { func (c *initializeContext) getContractDeployData(ctrName string, keysParam []interface{}) []interface{} {
items := make([]smartcontract.Parameter, 1, 6) items := make([]interface{}, 1, 6)
items[0] = newContractParameter(smartcontract.BoolType, false) // notaryDisabled is false items[0] = false // notaryDisabled is false
switch ctrName { switch ctrName {
case neofsContract: case neofsContract:
items = append(items, items = append(items,
newContractParameter(smartcontract.Hash160Type, c.Contracts[processingContract].Hash), c.Contracts[processingContract].Hash,
newContractParameter(smartcontract.ArrayType, keysParam), keysParam,
newContractParameter(smartcontract.ArrayType, smartcontract.Parameter{})) smartcontract.Parameter{})
case processingContract: case processingContract:
items = append(items, newContractParameter(smartcontract.Hash160Type, c.Contracts[neofsContract].Hash)) items = append(items, c.Contracts[neofsContract].Hash)
return items[1:] // no notary info return items[1:] // no notary info
case auditContract: case auditContract:
items = append(items, items = append(items, c.Contracts[netmapContract].Hash)
newContractParameter(smartcontract.Hash160Type, c.Contracts[netmapContract].Hash))
case balanceContract: case balanceContract:
items = append(items, items = append(items,
newContractParameter(smartcontract.Hash160Type, c.Contracts[netmapContract].Hash), c.Contracts[netmapContract].Hash,
newContractParameter(smartcontract.Hash160Type, c.Contracts[containerContract].Hash)) c.Contracts[containerContract].Hash)
case containerContract: case containerContract:
// In case if NNS is updated multiple times, we can't calculate // In case if NNS is updated multiple times, we can't calculate
// it's actual hash based on local data, thus query chain. // it's actual hash based on local data, thus query chain.
@ -542,43 +522,33 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []sm
panic("NNS is not yet deployed") panic("NNS is not yet deployed")
} }
items = append(items, items = append(items,
newContractParameter(smartcontract.Hash160Type, c.Contracts[netmapContract].Hash), c.Contracts[netmapContract].Hash,
newContractParameter(smartcontract.Hash160Type, c.Contracts[balanceContract].Hash), c.Contracts[balanceContract].Hash,
newContractParameter(smartcontract.Hash160Type, c.Contracts[neofsIDContract].Hash), c.Contracts[neofsIDContract].Hash,
newContractParameter(smartcontract.Hash160Type, nnsCs.Hash), nnsCs.Hash,
newContractParameter(smartcontract.StringType, "container")) "container")
case neofsIDContract: case neofsIDContract:
items = append(items, items = append(items,
newContractParameter(smartcontract.Hash160Type, c.Contracts[netmapContract].Hash), c.Contracts[netmapContract].Hash,
newContractParameter(smartcontract.Hash160Type, c.Contracts[containerContract].Hash)) c.Contracts[containerContract].Hash)
case netmapContract: case netmapContract:
configParam := []smartcontract.Parameter{ configParam := []interface{}{
{Type: smartcontract.StringType, Value: netmapEpochKey}, netmapEpochKey, viper.GetInt64(epochDurationInitFlag),
{Type: smartcontract.IntegerType, Value: viper.GetInt64(epochDurationInitFlag)}, netmapMaxObjectSizeKey, viper.GetInt64(maxObjectSizeInitFlag),
{Type: smartcontract.StringType, Value: netmapMaxObjectSizeKey}, netmapAuditFeeKey, viper.GetInt64(auditFeeInitFlag),
{Type: smartcontract.IntegerType, Value: viper.GetInt64(maxObjectSizeInitFlag)}, netmapContainerFeeKey, viper.GetInt64(containerFeeInitFlag),
{Type: smartcontract.StringType, Value: netmapAuditFeeKey}, netmapContainerAliasFeeKey, viper.GetInt64(containerAliasFeeInitFlag),
{Type: smartcontract.IntegerType, Value: viper.GetInt64(auditFeeInitFlag)}, netmapEigenTrustIterationsKey, int64(defaultEigenTrustIterations),
{Type: smartcontract.StringType, Value: netmapContainerFeeKey}, netmapEigenTrustAlphaKey, defaultEigenTrustAlpha,
{Type: smartcontract.IntegerType, Value: viper.GetInt64(containerFeeInitFlag)}, netmapBasicIncomeRateKey, viper.GetInt64(incomeRateInitFlag),
{Type: smartcontract.StringType, Value: netmapContainerAliasFeeKey}, netmapInnerRingCandidateFeeKey, viper.GetInt64(candidateFeeInitFlag),
{Type: smartcontract.IntegerType, Value: viper.GetInt64(containerAliasFeeInitFlag)}, netmapWithdrawFeeKey, viper.GetInt64(withdrawFeeInitFlag),
{Type: smartcontract.StringType, Value: netmapEigenTrustIterationsKey},
{Type: smartcontract.IntegerType, Value: int64(defaultEigenTrustIterations)},
{Type: smartcontract.StringType, Value: netmapEigenTrustAlphaKey},
{Type: smartcontract.StringType, Value: defaultEigenTrustAlpha},
{Type: smartcontract.StringType, Value: netmapBasicIncomeRateKey},
{Type: smartcontract.IntegerType, Value: viper.GetInt64(incomeRateInitFlag)},
{Type: smartcontract.StringType, Value: netmapInnerRingCandidateFeeKey},
{Type: smartcontract.IntegerType, Value: viper.GetInt64(candidateFeeInitFlag)},
{Type: smartcontract.StringType, Value: netmapWithdrawFeeKey},
{Type: smartcontract.IntegerType, Value: viper.GetInt64(withdrawFeeInitFlag)},
} }
items = append(items, items = append(items,
newContractParameter(smartcontract.Hash160Type, c.Contracts[balanceContract].Hash), c.Contracts[balanceContract].Hash,
newContractParameter(smartcontract.Hash160Type, c.Contracts[containerContract].Hash), c.Contracts[containerContract].Hash,
newContractParameter(smartcontract.ArrayType, keysParam), keysParam,
newContractParameter(smartcontract.ArrayType, configParam)) configParam)
case proxyContract: case proxyContract:
items = nil items = nil
case reputationContract: case reputationContract:
@ -589,18 +559,6 @@ func (c *initializeContext) getContractDeployData(ctrName string, keysParam []sm
return items return items
} }
func (c *initializeContext) getAlphabetDeployParameters(i, n int) []smartcontract.Parameter {
items := c.getAlphabetDeployItems(i, n)
return []smartcontract.Parameter{
newContractParameter(smartcontract.BoolType, items[0]),
newContractParameter(smartcontract.Hash160Type, items[1]),
newContractParameter(smartcontract.Hash160Type, items[2]),
newContractParameter(smartcontract.StringType, items[3]),
newContractParameter(smartcontract.IntegerType, items[4]),
newContractParameter(smartcontract.IntegerType, items[5]),
}
}
func (c *initializeContext) getAlphabetDeployItems(i, n int) []interface{} { func (c *initializeContext) getAlphabetDeployItems(i, n int) []interface{} {
items := make([]interface{}, 6) items := make([]interface{}, 6)
items[0] = false items[0] = false

View file

@ -12,7 +12,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/client" "github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
@ -165,8 +164,8 @@ func (c *initializeContext) nnsRegisterDomain(nnsHash, expectedHash util.Uint160
} }
func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160) (bool, error) { func (c *initializeContext) nnsRootRegistered(nnsHash util.Uint160) (bool, error) {
params := []smartcontract.Parameter{{Type: smartcontract.StringType, Value: "name.neofs"}} params := []interface{}{"name.neofs"}
res, err := c.Client.InvokeFunction(nnsHash, "isAvailable", params, nil) res, err := invokeFunction(c.Client, nnsHash, "isAvailable", params, nil)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -185,16 +184,7 @@ func nnsResolveHash(c Client, nnsHash util.Uint160, domain string) (util.Uint160
} }
func nnsResolve(c Client, nnsHash util.Uint160, domain string) (stackitem.Item, error) { func nnsResolve(c Client, nnsHash util.Uint160, domain string) (stackitem.Item, error) {
result, err := c.InvokeFunction(nnsHash, "resolve", []smartcontract.Parameter{ result, err := invokeFunction(c, nnsHash, "resolve", []interface{}{domain, int64(nns.TXT)}, nil)
{
Type: smartcontract.StringType,
Value: domain,
},
{
Type: smartcontract.IntegerType,
Value: int64(nns.TXT),
},
}, nil)
if err != nil { if err != nil {
return nil, fmt.Errorf("`resolve`: %w", err) return nil, fmt.Errorf("`resolve`: %w", err)
} }
@ -244,11 +234,24 @@ func parseNNSResolveResult(res stackitem.Item) (util.Uint160, error) {
return util.Uint160DecodeStringLE(string(bs)) return util.Uint160DecodeStringLE(string(bs))
} }
var errNNSIsAvailableInvalid = errors.New("`isAvailable`: invalid response")
func nnsIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) { func nnsIsAvailable(c Client, nnsHash util.Uint160, name string) (bool, error) {
switch ct := c.(type) { switch ct := c.(type) {
case *client.Client: case *client.Client:
return ct.NNSIsAvailable(nnsHash, name) return ct.NNSIsAvailable(nnsHash, name)
default: default:
panic("unimplemented") res, err := invokeFunction(c, nnsHash, "isAvailable", []interface{}{name}, nil)
if err != nil {
return false, err
}
if len(res.Stack) == 0 {
return false, errNNSIsAvailableInvalid
}
b, err := res.Stack[0].TryBool()
if err != nil {
return b, errNNSIsAvailableInvalid
}
return b, nil
} }
} }

View file

@ -1,6 +1,7 @@
package morph package morph
import ( import (
"errors"
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/core/native" "github.com/nspcc-dev/neo-go/pkg/core/native"
@ -8,7 +9,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/client" "github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
@ -23,7 +23,7 @@ const initialAlphabetNEOAmount = native.NEOTotalSupply
func (c *initializeContext) registerCandidates() error { func (c *initializeContext) registerCandidates() error {
neoHash := c.nativeHash(nativenames.Neo) neoHash := c.nativeHash(nativenames.Neo)
res, err := c.Client.InvokeFunction(neoHash, "getCandidates", []smartcontract.Parameter{}, nil) res, err := invokeFunction(c.Client, neoHash, "getCandidates", nil, nil)
if err != nil { if err != nil {
return err return err
} }
@ -34,7 +34,7 @@ func (c *initializeContext) registerCandidates() error {
} }
} }
regPrice, err := getCandidateRegisterPrice(c.Client) regPrice, err := c.getCandidateRegisterPrice()
if err != nil { if err != nil {
return fmt.Errorf("can't fetch registration price: %w", err) return fmt.Errorf("can't fetch registration price: %w", err)
} }
@ -84,11 +84,25 @@ func (c *initializeContext) transferNEOFinished(neoHash util.Uint160) (bool, err
return bal < native.NEOTotalSupply, err return bal < native.NEOTotalSupply, err
} }
func getCandidateRegisterPrice(c Client) (int64, error) { var errGetPriceInvalid = errors.New("`getRegisterPrice`: invalid response")
switch ct := c.(type) {
func (c *initializeContext) getCandidateRegisterPrice() (int64, error) {
switch ct := c.Client.(type) {
case *client.Client: case *client.Client:
return ct.GetCandidateRegisterPrice() return ct.GetCandidateRegisterPrice()
default: default:
panic("unimplemented") neoHash := c.nativeHash(nativenames.Neo)
res, err := invokeFunction(c.Client, neoHash, "getRegisterPrice", nil, nil)
if err != nil {
return 0, err
}
if len(res.Stack) == 0 {
return 0, errGetPriceInvalid
}
bi, err := res.Stack[0].TryInteger()
if err != nil || !bi.IsInt64() {
return 0, errGetPriceInvalid
}
return bi.Int64(), nil
} }
} }

View file

@ -42,6 +42,7 @@ func (c *initializeContext) setRolesFinished() (bool, error) {
return false, err return false, err
} }
pubs, err := c.Client.GetDesignatedByRole(noderoles.NeoFSAlphabet, height) h := c.nativeHash(nativenames.Designation)
pubs, err := getDesignatedByRole(c.Client, h, noderoles.NeoFSAlphabet, height)
return len(pubs) == len(c.Wallets), err return len(pubs) == len(c.Wallets), err
} }

View file

@ -0,0 +1,357 @@
package morph
import (
"bytes"
"crypto/elliptic"
"errors"
"fmt"
"os"
"sort"
"github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/block"
"github.com/nspcc-dev/neo-go/pkg/core/chaindump"
"github.com/nspcc-dev/neo-go/pkg/core/fee"
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/spf13/viper"
"go.uber.org/zap"
)
type localClient struct {
bc *core.Blockchain
transactions []*transaction.Transaction
dumpPath string
accounts []*wallet.Account
}
func newLocalClient(v *viper.Viper, wallets []*wallet.Wallet) (*localClient, error) {
cfg, err := config.LoadFile(v.GetString(protoConfigPath))
if err != nil {
return nil, err
}
bc, err := core.NewBlockchain(storage.NewMemoryStore(), cfg.ProtocolConfiguration, zap.NewNop())
if err != nil {
return nil, err
}
defer func() { go bc.Run() }()
m := smartcontract.GetDefaultHonestNodeCount(cfg.ProtocolConfiguration.ValidatorsCount)
accounts := make([]*wallet.Account, len(wallets))
for i := range accounts {
accounts[i], err = getWalletAccount(wallets[i], consensusAccountName)
if err != nil {
return nil, err
}
}
indexMap := make(map[string]int)
for i, pub := range cfg.ProtocolConfiguration.StandbyCommittee {
indexMap[pub] = i
}
sort.Slice(accounts, func(i, j int) bool {
pi := accounts[i].PrivateKey().PublicKey().Bytes()
pj := accounts[j].PrivateKey().PublicKey().Bytes()
return indexMap[string(pi)] < indexMap[string(pj)]
})
sort.Slice(accounts[:cfg.ProtocolConfiguration.ValidatorsCount], func(i, j int) bool {
pi := accounts[i].PrivateKey().PublicKey().Bytes()
pj := accounts[j].PrivateKey().PublicKey().Bytes()
return bytes.Compare(pi, pj) == -1
})
return &localClient{
bc: bc,
dumpPath: v.GetString(localDumpFlag),
accounts: accounts[:m],
}, nil
}
func (l *localClient) GetBlockCount() (uint32, error) {
return l.bc.BlockHeight(), nil
}
func (l *localClient) GetContractStateByID(id int32) (*state.Contract, error) {
h, err := l.bc.GetContractScriptHash(id)
if err != nil {
return nil, err
}
return l.GetContractStateByHash(h)
}
func (l *localClient) GetContractStateByHash(h util.Uint160) (*state.Contract, error) {
if cs := l.bc.GetContractState(h); cs != nil {
return cs, nil
}
return nil, storage.ErrKeyNotFound
}
func (l *localClient) GetNativeContracts() ([]state.NativeContract, error) {
return l.bc.GetNatives(), nil
}
func (l *localClient) GetNetwork() (netmode.Magic, error) {
return l.bc.GetConfig().Magic, nil
}
func (l *localClient) GetApplicationLog(h util.Uint256, t *trigger.Type) (*result.ApplicationLog, error) {
aer, err := l.bc.GetAppExecResults(h, *t)
if err != nil {
return nil, err
}
a := result.NewApplicationLog(h, aer, *t)
return &a, nil
}
func (l *localClient) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee int64, netFee int64, cosigners []client.SignerAccount) (*transaction.Transaction, error) {
signers, accounts, err := getSigners(acc, cosigners)
if err != nil {
return nil, fmt.Errorf("failed to construct tx signers: %w", err)
}
if sysFee < 0 {
res, err := l.InvokeScript(script, signers)
if err != nil {
return nil, fmt.Errorf("can't add system fee to transaction: %w", err)
}
if res.State != "HALT" {
return nil, fmt.Errorf("can't add system fee to transaction: bad vm state: %s due to an error: %s", res.State, res.FaultException)
}
sysFee = res.GasConsumed
}
tx := transaction.New(script, sysFee)
tx.Signers = signers
tx.ValidUntilBlock = l.bc.BlockHeight() + 2
err = l.addNetworkFee(tx, netFee, accounts...)
if err != nil {
return nil, fmt.Errorf("failed to add network fee: %w", err)
}
return tx, nil
}
// addNetworkFee adds network fee for each witness script and optional extra
// network fee to transaction. `accs` is an array signer's accounts.
// Copied from neo-go with minor corrections (no need to support contract signers):
// https://github.com/nspcc-dev/neo-go/blob/6ff11baa1b9e4c71ef0d1de43b92a8c541ca732c/pkg/rpc/client/rpc.go#L960
func (l *localClient) addNetworkFee(tx *transaction.Transaction, extraFee int64, accs ...*wallet.Account) error {
if len(tx.Signers) != len(accs) {
return errors.New("number of signers must match number of scripts")
}
size := io.GetVarSize(tx)
ef := l.bc.GetBaseExecFee()
for i := range tx.Signers {
netFee, sizeDelta := fee.Calculate(ef, accs[i].Contract.Script)
tx.NetworkFee += netFee
size += sizeDelta
}
tx.NetworkFee += int64(size)*l.bc.FeePerByte() + extraFee
return nil
}
// getSigners returns an array of transaction signers and corresponding accounts from
// given sender and cosigners. If cosigners list already contains sender, the sender
// will be placed at the start of the list.
// Copied from neo-go with minor corrections:
// https://github.com/nspcc-dev/neo-go/blob/6ff11baa1b9e4c71ef0d1de43b92a8c541ca732c/pkg/rpc/client/rpc.go#L735
func getSigners(sender *wallet.Account, cosigners []client.SignerAccount) ([]transaction.Signer, []*wallet.Account, error) {
var (
signers []transaction.Signer
accounts []*wallet.Account
)
from := sender.Contract.ScriptHash()
s := transaction.Signer{
Account: from,
Scopes: transaction.None,
}
for _, c := range cosigners {
if c.Signer.Account == from {
s = c.Signer
continue
}
signers = append(signers, c.Signer)
accounts = append(accounts, c.Account)
}
signers = append([]transaction.Signer{s}, signers...)
accounts = append([]*wallet.Account{sender}, accounts...)
return signers, accounts, nil
}
func (l *localClient) NEP17BalanceOf(h util.Uint160, acc util.Uint160) (int64, error) {
res, err := invokeFunction(l, h, "balanceOf", []interface{}{acc}, nil)
if err != nil {
return 0, err
}
if res.State != vm.HaltState.String() || len(res.Stack) == 0 {
return 0, fmt.Errorf("`balance`: invalid response (empty: %t): %s",
len(res.Stack) == 0, res.FaultException)
}
bi, err := res.Stack[0].TryInteger()
if err != nil || !bi.IsInt64() {
return 0, fmt.Errorf("`balance`: invalid response")
}
return bi.Int64(), nil
}
func (l *localClient) InvokeScript(script []byte, signers []transaction.Signer) (*result.Invoke, error) {
lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash())
if err != nil {
return nil, err
}
tx := transaction.New(script, 0)
tx.Signers = signers
tx.ValidUntilBlock = l.bc.BlockHeight() + 2
ic := l.bc.GetTestVM(trigger.Application, tx, &block.Block{
Header: block.Header{
Index: lastBlock.Index + 1,
Timestamp: lastBlock.Timestamp + 1,
},
})
ic.VM.GasLimit = 100_0000_0000
ic.VM.LoadScriptWithFlags(script, callflag.All)
var errStr string
if err := ic.VM.Run(); err != nil {
errStr = err.Error()
}
return &result.Invoke{
State: ic.VM.State().String(),
GasConsumed: ic.VM.GasConsumed(),
Script: script,
Stack: ic.VM.Estack().ToArray(),
FaultException: errStr,
}, nil
}
func (l *localClient) SendRawTransaction(tx *transaction.Transaction) (util.Uint256, error) {
l.transactions = append(l.transactions, tx)
return tx.Hash(), nil
}
func (l *localClient) putTransactions() error {
// 1. Prepare new block.
lastBlock, err := l.bc.GetBlock(l.bc.CurrentBlockHash())
if err != nil {
panic(err)
}
defer func() { l.transactions = l.transactions[:0] }()
b := &block.Block{
Header: block.Header{
NextConsensus: l.accounts[0].Contract.ScriptHash(),
Script: transaction.Witness{
VerificationScript: l.accounts[0].Contract.Script,
},
Timestamp: lastBlock.Timestamp + 1,
},
Transactions: l.transactions,
}
if l.bc.GetConfig().StateRootInHeader {
b.StateRootEnabled = true
b.PrevStateRoot = l.bc.GetStateModule().CurrentLocalStateRoot()
}
b.PrevHash = lastBlock.Hash()
b.Index = lastBlock.Index + 1
b.RebuildMerkleRoot()
// 2. Sign prepared block.
var invocationScript []byte
magic := l.bc.GetConfig().Magic
for _, acc := range l.accounts {
sign := acc.PrivateKey().SignHashable(uint32(magic), b)
invocationScript = append(invocationScript, byte(opcode.PUSHDATA1), 64)
invocationScript = append(invocationScript, sign...)
}
b.Script.InvocationScript = invocationScript
// 3. Persist block.
return l.bc.AddBlock(b)
}
func invokeFunction(c Client, h util.Uint160, method string, parameters []interface{}, signers []transaction.Signer) (*result.Invoke, error) {
w := io.NewBufBinWriter()
emit.Array(w.BinWriter, parameters...)
emit.AppCallNoArgs(w.BinWriter, h, method, callflag.All)
if w.Err != nil {
panic(fmt.Sprintf("BUG: invalid parameters for '%s': %v", method, w.Err))
}
return c.InvokeScript(w.Bytes(), signers)
}
var errGetDesignatedByRoleResponse = errors.New("`getDesignatedByRole`: invalid response")
func getDesignatedByRole(c Client, h util.Uint160, role noderoles.Role, u uint32) (keys.PublicKeys, error) {
res, err := invokeFunction(c, h, "getDesignatedByRole", []interface{}{int64(role), int64(u)}, nil)
if err != nil {
return nil, err
}
if res.State != vm.HaltState.String() || len(res.Stack) == 0 {
return nil, errGetDesignatedByRoleResponse
}
arr, ok := res.Stack[0].Value().([]stackitem.Item)
if !ok {
return nil, errGetDesignatedByRoleResponse
}
pubs := make(keys.PublicKeys, len(arr))
for i := range arr {
bs, err := arr[i].TryBytes()
if err != nil {
return nil, errGetDesignatedByRoleResponse
}
pubs[i], err = keys.NewPublicKeyFromBytes(bs, elliptic.P256())
if err != nil {
return nil, errGetDesignatedByRoleResponse
}
}
return pubs, nil
}
func (l *localClient) dump() (err error) {
defer l.bc.Close()
f, err := os.Create(l.dumpPath)
if err != nil {
return err
}
defer func() {
closeErr := f.Close()
if err == nil && closeErr != nil {
err = closeErr
}
}()
w := io.NewBinWriterFromIO(f)
err = chaindump.Dump(l.bc, w, 0, l.bc.BlockHeight())
return
}

View file

@ -7,13 +7,10 @@ import (
"time" "time"
"github.com/nspcc-dev/neo-go/pkg/config/netmode" "github.com/nspcc-dev/neo-go/pkg/config/netmode"
"github.com/nspcc-dev/neo-go/pkg/core/native/noderoles"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/rpc/client" "github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger" "github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet" "github.com/nspcc-dev/neo-go/pkg/wallet"
@ -25,7 +22,6 @@ import (
// and sending signed transactions to chain. // and sending signed transactions to chain.
type Client interface { type Client interface {
GetBlockCount() (uint32, error) GetBlockCount() (uint32, error)
GetDesignatedByRole(noderoles.Role, uint32) (keys.PublicKeys, error)
GetContractStateByID(int32) (*state.Contract, error) GetContractStateByID(int32) (*state.Contract, error)
GetContractStateByHash(util.Uint160) (*state.Contract, error) GetContractStateByHash(util.Uint160) (*state.Contract, error)
GetNativeContracts() ([]state.NativeContract, error) GetNativeContracts() ([]state.NativeContract, error)
@ -33,7 +29,6 @@ type Client interface {
GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error) GetApplicationLog(util.Uint256, *trigger.Type) (*result.ApplicationLog, error)
CreateTxFromScript([]byte, *wallet.Account, int64, int64, []client.SignerAccount) (*transaction.Transaction, error) CreateTxFromScript([]byte, *wallet.Account, int64, int64, []client.SignerAccount) (*transaction.Transaction, error)
NEP17BalanceOf(util.Uint160, util.Uint160) (int64, error) NEP17BalanceOf(util.Uint160, util.Uint160) (int64, error)
InvokeFunction(util.Uint160, string, []smartcontract.Parameter, []transaction.Signer) (*result.Invoke, error)
InvokeScript([]byte, []transaction.Signer) (*result.Invoke, error) InvokeScript([]byte, []transaction.Signer) (*result.Invoke, error)
SendRawTransaction(*transaction.Transaction) (util.Uint256, error) SendRawTransaction(*transaction.Transaction) (util.Uint256, error)
} }

View file

@ -35,6 +35,8 @@ const (
refillGasAmountFlag = "gas" refillGasAmountFlag = "gas"
walletAccountFlag = "account" walletAccountFlag = "account"
notaryDepositTillFlag = "till" notaryDepositTillFlag = "till"
localDumpFlag = "local-dump"
protoConfigPath = "protocol"
) )
var ( var (
@ -68,6 +70,8 @@ var (
_ = viper.BindPFlag(containerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag)) _ = viper.BindPFlag(containerFeeInitFlag, cmd.Flags().Lookup(containerFeeCLIFlag))
_ = viper.BindPFlag(containerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag)) _ = viper.BindPFlag(containerAliasFeeInitFlag, cmd.Flags().Lookup(containerAliasFeeCLIFlag))
_ = viper.BindPFlag(withdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag)) _ = viper.BindPFlag(withdrawFeeInitFlag, cmd.Flags().Lookup(withdrawFeeCLIFlag))
_ = viper.BindPFlag(protoConfigPath, cmd.Flags().Lookup(protoConfigPath))
_ = viper.BindPFlag(localDumpFlag, cmd.Flags().Lookup(localDumpFlag))
}, },
RunE: initializeSideChainCmd, RunE: initializeSideChainCmd,
} }
@ -197,6 +201,8 @@ func init() {
// Defaults are taken from neo-preodolenie. // Defaults are taken from neo-preodolenie.
initCmd.Flags().Uint64(containerFeeCLIFlag, 1000, "container registration fee") initCmd.Flags().Uint64(containerFeeCLIFlag, 1000, "container registration fee")
initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "container alias fee") initCmd.Flags().Uint64(containerAliasFeeCLIFlag, 500, "container alias fee")
initCmd.Flags().String(protoConfigPath, "", "path to the consensus node configuration")
initCmd.Flags().String(localDumpFlag, "", "path to the blocks dump file")
RootCmd.AddCommand(generateStorageCmd) RootCmd.AddCommand(generateStorageCmd)
generateStorageCmd.Flags().String(alphabetWalletsFlag, "", "path to alphabet wallets dir") generateStorageCmd.Flags().String(alphabetWalletsFlag, "", "path to alphabet wallets dir")

1
go.mod
View file

@ -49,6 +49,7 @@ require (
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/holiman/uint256 v1.2.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/ipfs/go-cid v0.0.7 // indirect github.com/ipfs/go-cid v0.0.7 // indirect
github.com/magiconair/properties v1.8.5 // indirect github.com/magiconair/properties v1.8.5 // indirect

BIN
go.sum

Binary file not shown.