mirror of https://github.com/poanetwork/gecko.git
Merge branch 'master' into custom-genesis
This commit is contained in:
commit
10779d168d
|
@ -18,6 +18,9 @@ awscpu
|
|||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# ignore GoLand metafiles directory
|
||||
.idea/
|
||||
|
||||
*logs/
|
||||
|
||||
.vscode*
|
||||
|
|
|
@ -54,7 +54,7 @@ The Gecko binary, named `ava`, is in the `build` directory.
|
|||
- Build the docker image of latest gecko branch by `scripts/build_image.sh`.
|
||||
- Check the built image by `docker image ls`, you should see some image tagged
|
||||
`gecko-xxxxxxxx`, where `xxxxxxxx` is the commit id of the Gecko source it was built from.
|
||||
- Test Gecko by `docker run -ti -p 9651:9651 gecko-xxxxxxxx /gecko/build/ava
|
||||
- Test Gecko by `docker run -ti -p 9650:9650 -p 9651:9651 gecko-xxxxxxxx /gecko/build/ava
|
||||
--public-ip=127.0.0.1 --snow-sample-size=1 --snow-quorum-size=1 --staking-tls-enabled=false`. (For a production deployment,
|
||||
you may want to extend the docker image with required credentials for
|
||||
staking and TLS.)
|
||||
|
|
|
@ -391,7 +391,7 @@ func (m *manager) createAvalancheChain(
|
|||
Context: ctx,
|
||||
Validators: validators,
|
||||
Beacons: beacons,
|
||||
Alpha: (beacons.Len() + 1) / 2,
|
||||
Alpha: beacons.Len()/2 + 1, // must be > 50%
|
||||
Sender: &sender,
|
||||
},
|
||||
VtxBlocked: vtxBlocker,
|
||||
|
@ -471,7 +471,7 @@ func (m *manager) createSnowmanChain(
|
|||
Context: ctx,
|
||||
Validators: validators,
|
||||
Beacons: beacons,
|
||||
Alpha: (beacons.Len() + 1) / 2,
|
||||
Alpha: beacons.Len()/2 + 1, // must be > 50%
|
||||
Sender: &sender,
|
||||
},
|
||||
Blocked: blocked,
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
|
@ -44,64 +45,76 @@ func init() {
|
|||
loggingConfig, err := logging.DefaultConfig()
|
||||
errs.Add(err)
|
||||
|
||||
fs := flag.NewFlagSet("gecko", flag.ContinueOnError)
|
||||
|
||||
// NetworkID:
|
||||
networkName := flag.String("network-id", genesis.LocalName, "Network ID this node will connect to")
|
||||
networkName := fs.String("network-id", genesis.LocalName, "Network ID this node will connect to")
|
||||
|
||||
// Ava fees:
|
||||
flag.Uint64Var(&Config.AvaTxFee, "ava-tx-fee", 0, "Ava transaction fee, in $nAva")
|
||||
fs.Uint64Var(&Config.AvaTxFee, "ava-tx-fee", 0, "Ava transaction fee, in $nAva")
|
||||
|
||||
// Assertions:
|
||||
flag.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution")
|
||||
fs.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution")
|
||||
|
||||
// Crypto:
|
||||
flag.BoolVar(&Config.EnableCrypto, "signature-verification-enabled", true, "Turn on signature verification")
|
||||
fs.BoolVar(&Config.EnableCrypto, "signature-verification-enabled", true, "Turn on signature verification")
|
||||
|
||||
// Database:
|
||||
db := flag.Bool("db-enabled", true, "Turn on persistent storage")
|
||||
dbDir := flag.String("db-dir", "db", "Database directory for Ava state")
|
||||
db := fs.Bool("db-enabled", true, "Turn on persistent storage")
|
||||
dbDir := fs.String("db-dir", "db", "Database directory for Ava state")
|
||||
|
||||
// IP:
|
||||
consensusIP := flag.String("public-ip", "", "Public IP of this node")
|
||||
consensusIP := fs.String("public-ip", "", "Public IP of this node")
|
||||
|
||||
// HTTP Server:
|
||||
httpPort := flag.Uint("http-port", 9650, "Port of the HTTP server")
|
||||
flag.BoolVar(&Config.EnableHTTPS, "http-tls-enabled", false, "Upgrade the HTTP server to HTTPs")
|
||||
flag.StringVar(&Config.HTTPSKeyFile, "http-tls-key-file", "", "TLS private key file for the HTTPs server")
|
||||
flag.StringVar(&Config.HTTPSCertFile, "http-tls-cert-file", "", "TLS certificate file for the HTTPs server")
|
||||
httpPort := fs.Uint("http-port", 9650, "Port of the HTTP server")
|
||||
fs.BoolVar(&Config.EnableHTTPS, "http-tls-enabled", false, "Upgrade the HTTP server to HTTPs")
|
||||
fs.StringVar(&Config.HTTPSKeyFile, "http-tls-key-file", "", "TLS private key file for the HTTPs server")
|
||||
fs.StringVar(&Config.HTTPSCertFile, "http-tls-cert-file", "", "TLS certificate file for the HTTPs server")
|
||||
|
||||
// Bootstrapping:
|
||||
bootstrapIPs := flag.String("bootstrap-ips", "", "Comma separated list of bootstrap peer ips to connect to. Example: 127.0.0.1:9630,127.0.0.1:9631")
|
||||
bootstrapIDs := flag.String("bootstrap-ids", "", "Comma separated list of bootstrap peer ids to connect to. Example: JR4dVmy6ffUGAKCBDkyCbeZbyHQBeDsET,8CrVPQZ4VSqgL8zTdvL14G8HqAfrBr4z")
|
||||
bootstrapIPs := fs.String("bootstrap-ips", "", "Comma separated list of bootstrap peer ips to connect to. Example: 127.0.0.1:9630,127.0.0.1:9631")
|
||||
bootstrapIDs := fs.String("bootstrap-ids", "", "Comma separated list of bootstrap peer ids to connect to. Example: JR4dVmy6ffUGAKCBDkyCbeZbyHQBeDsET,8CrVPQZ4VSqgL8zTdvL14G8HqAfrBr4z")
|
||||
|
||||
// Staking:
|
||||
consensusPort := flag.Uint("staking-port", 9651, "Port of the consensus server")
|
||||
flag.BoolVar(&Config.EnableStaking, "staking-tls-enabled", true, "Require TLS to authenticate staking connections")
|
||||
flag.StringVar(&Config.StakingKeyFile, "staking-tls-key-file", "", "TLS private key file for staking connections")
|
||||
flag.StringVar(&Config.StakingCertFile, "staking-tls-cert-file", "", "TLS certificate file for staking connections")
|
||||
consensusPort := fs.Uint("staking-port", 9651, "Port of the consensus server")
|
||||
fs.BoolVar(&Config.EnableStaking, "staking-tls-enabled", true, "Require TLS to authenticate staking connections")
|
||||
fs.StringVar(&Config.StakingKeyFile, "staking-tls-key-file", "", "TLS private key file for staking connections")
|
||||
fs.StringVar(&Config.StakingCertFile, "staking-tls-cert-file", "", "TLS certificate file for staking connections")
|
||||
|
||||
// Logging:
|
||||
logsDir := flag.String("log-dir", "", "Logging directory for Ava")
|
||||
logLevel := flag.String("log-level", "info", "The log level. Should be one of {verbo, debug, info, warn, error, fatal, off}")
|
||||
logDisplayLevel := flag.String("log-display-level", "", "The log display level. If left blank, will inherit the value of log-level. Otherwise, should be one of {verbo, debug, info, warn, error, fatal, off}")
|
||||
logsDir := fs.String("log-dir", "", "Logging directory for Ava")
|
||||
logLevel := fs.String("log-level", "info", "The log level. Should be one of {verbo, debug, info, warn, error, fatal, off}")
|
||||
logDisplayLevel := fs.String("log-display-level", "", "The log display level. If left blank, will inherit the value of log-level. Otherwise, should be one of {verbo, debug, info, warn, error, fatal, off}")
|
||||
|
||||
flag.IntVar(&Config.ConsensusParams.K, "snow-sample-size", 20, "Number of nodes to query for each network poll")
|
||||
flag.IntVar(&Config.ConsensusParams.Alpha, "snow-quorum-size", 18, "Alpha value to use for required number positive results")
|
||||
flag.IntVar(&Config.ConsensusParams.BetaVirtuous, "snow-virtuous-commit-threshold", 20, "Beta value to use for virtuous transactions")
|
||||
flag.IntVar(&Config.ConsensusParams.BetaRogue, "snow-rogue-commit-threshold", 30, "Beta value to use for rogue transactions")
|
||||
flag.IntVar(&Config.ConsensusParams.Parents, "snow-avalanche-num-parents", 5, "Number of vertexes for reference from each new vertex")
|
||||
flag.IntVar(&Config.ConsensusParams.BatchSize, "snow-avalanche-batch-size", 30, "Number of operations to batch in each new vertex")
|
||||
fs.IntVar(&Config.ConsensusParams.K, "snow-sample-size", 20, "Number of nodes to query for each network poll")
|
||||
fs.IntVar(&Config.ConsensusParams.Alpha, "snow-quorum-size", 18, "Alpha value to use for required number positive results")
|
||||
fs.IntVar(&Config.ConsensusParams.BetaVirtuous, "snow-virtuous-commit-threshold", 20, "Beta value to use for virtuous transactions")
|
||||
fs.IntVar(&Config.ConsensusParams.BetaRogue, "snow-rogue-commit-threshold", 30, "Beta value to use for rogue transactions")
|
||||
fs.IntVar(&Config.ConsensusParams.Parents, "snow-avalanche-num-parents", 5, "Number of vertexes for reference from each new vertex")
|
||||
fs.IntVar(&Config.ConsensusParams.BatchSize, "snow-avalanche-batch-size", 30, "Number of operations to batch in each new vertex")
|
||||
|
||||
// Enable/Disable APIs:
|
||||
flag.BoolVar(&Config.AdminAPIEnabled, "api-admin-enabled", true, "If true, this node exposes the Admin API")
|
||||
flag.BoolVar(&Config.KeystoreAPIEnabled, "api-keystore-enabled", true, "If true, this node exposes the Keystore API")
|
||||
flag.BoolVar(&Config.MetricsAPIEnabled, "api-metrics-enabled", true, "If true, this node exposes the Metrics API")
|
||||
flag.BoolVar(&Config.IPCEnabled, "api-ipcs-enabled", false, "If true, IPCs can be opened")
|
||||
fs.BoolVar(&Config.AdminAPIEnabled, "api-admin-enabled", true, "If true, this node exposes the Admin API")
|
||||
fs.BoolVar(&Config.KeystoreAPIEnabled, "api-keystore-enabled", true, "If true, this node exposes the Keystore API")
|
||||
fs.BoolVar(&Config.MetricsAPIEnabled, "api-metrics-enabled", true, "If true, this node exposes the Metrics API")
|
||||
fs.BoolVar(&Config.IPCEnabled, "api-ipcs-enabled", false, "If true, IPCs can be opened")
|
||||
|
||||
// Throughput Server
|
||||
throughputPort := flag.Uint("xput-server-port", 9652, "Port of the deprecated throughput test server")
|
||||
flag.BoolVar(&Config.ThroughputServerEnabled, "xput-server-enabled", false, "If true, throughput test server is created")
|
||||
throughputPort := fs.Uint("xput-server-port", 9652, "Port of the deprecated throughput test server")
|
||||
fs.BoolVar(&Config.ThroughputServerEnabled, "xput-server-enabled", false, "If true, throughput test server is created")
|
||||
|
||||
flag.Parse()
|
||||
ferr := fs.Parse(os.Args[1:])
|
||||
|
||||
if ferr == flag.ErrHelp {
|
||||
// display usage/help text and exit successfully
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if ferr != nil {
|
||||
// other type of error occurred when parsing args
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
networkID, err := genesis.NetworkID(*networkName)
|
||||
errs.Add(err)
|
||||
|
|
|
@ -119,7 +119,7 @@ func (b *bootstrapper) fetch(vtxID ids.ID) {
|
|||
b.sendRequest(vtxID)
|
||||
return
|
||||
}
|
||||
b.addVertex(vtx)
|
||||
b.storeVertex(vtx)
|
||||
}
|
||||
|
||||
func (b *bootstrapper) sendRequest(vtxID ids.ID) {
|
||||
|
@ -138,6 +138,14 @@ func (b *bootstrapper) sendRequest(vtxID ids.ID) {
|
|||
}
|
||||
|
||||
func (b *bootstrapper) addVertex(vtx avalanche.Vertex) {
|
||||
b.storeVertex(vtx)
|
||||
|
||||
if numPending := b.pending.Len(); numPending == 0 {
|
||||
b.finish()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *bootstrapper) storeVertex(vtx avalanche.Vertex) {
|
||||
vts := []avalanche.Vertex{vtx}
|
||||
|
||||
for len(vts) > 0 {
|
||||
|
@ -181,9 +189,6 @@ func (b *bootstrapper) addVertex(vtx avalanche.Vertex) {
|
|||
|
||||
numPending := b.pending.Len()
|
||||
b.numPendingRequests.Set(float64(numPending))
|
||||
if numPending == 0 {
|
||||
b.finish()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *bootstrapper) finish() {
|
||||
|
|
|
@ -957,3 +957,53 @@ func TestBootstrapperFilterAccepted(t *testing.T) {
|
|||
t.Fatalf("Vtx shouldn't be accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapperPartialFetch(t *testing.T) {
|
||||
config, _, sender, state, _ := newConfig(t)
|
||||
|
||||
vtxID0 := ids.Empty.Prefix(0)
|
||||
vtxID1 := ids.Empty.Prefix(1)
|
||||
|
||||
vtxBytes0 := []byte{0}
|
||||
|
||||
vtx0 := &Vtx{
|
||||
id: vtxID0,
|
||||
height: 0,
|
||||
status: choices.Processing,
|
||||
bytes: vtxBytes0,
|
||||
}
|
||||
|
||||
bs := bootstrapper{}
|
||||
bs.metrics.Initialize(config.Context.Log, fmt.Sprintf("gecko_%s", config.Context.ChainID), prometheus.NewRegistry())
|
||||
bs.Initialize(config)
|
||||
|
||||
acceptedIDs := ids.Set{}
|
||||
acceptedIDs.Add(
|
||||
vtxID0,
|
||||
vtxID1,
|
||||
)
|
||||
|
||||
state.getVertex = func(vtxID ids.ID) (avalanche.Vertex, error) {
|
||||
switch {
|
||||
case vtxID.Equals(vtxID0):
|
||||
return vtx0, nil
|
||||
case vtxID.Equals(vtxID1):
|
||||
return nil, errUnknownVertex
|
||||
default:
|
||||
t.Fatal(errUnknownVertex)
|
||||
panic(errUnknownVertex)
|
||||
}
|
||||
}
|
||||
|
||||
sender.CantGet = false
|
||||
|
||||
bs.ForceAccepted(acceptedIDs)
|
||||
|
||||
if bs.finished {
|
||||
t.Fatalf("should have requested a vertex")
|
||||
}
|
||||
|
||||
if bs.pending.Len() != 1 {
|
||||
t.Fatalf("wrong number pending")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,7 +113,7 @@ func (b *bootstrapper) fetch(blkID ids.ID) {
|
|||
b.sendRequest(blkID)
|
||||
return
|
||||
}
|
||||
b.addBlock(blk)
|
||||
b.storeBlock(blk)
|
||||
}
|
||||
|
||||
func (b *bootstrapper) sendRequest(blkID ids.ID) {
|
||||
|
@ -132,6 +132,14 @@ func (b *bootstrapper) sendRequest(blkID ids.ID) {
|
|||
}
|
||||
|
||||
func (b *bootstrapper) addBlock(blk snowman.Block) {
|
||||
b.storeBlock(blk)
|
||||
|
||||
if numPending := b.pending.Len(); numPending == 0 {
|
||||
b.finish()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *bootstrapper) storeBlock(blk snowman.Block) {
|
||||
status := blk.Status()
|
||||
blkID := blk.ID()
|
||||
for status == choices.Processing {
|
||||
|
@ -161,9 +169,6 @@ func (b *bootstrapper) addBlock(blk snowman.Block) {
|
|||
|
||||
numPending := b.pending.Len()
|
||||
b.numPendingRequests.Set(float64(numPending))
|
||||
if numPending == 0 {
|
||||
b.finish()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *bootstrapper) finish() {
|
||||
|
|
|
@ -425,3 +425,54 @@ func TestBootstrapperFilterAccepted(t *testing.T) {
|
|||
t.Fatalf("Blk shouldn't be accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapperPartialFetch(t *testing.T) {
|
||||
config, _, sender, vm := newConfig(t)
|
||||
|
||||
blkID0 := ids.Empty.Prefix(0)
|
||||
blkID1 := ids.Empty.Prefix(1)
|
||||
|
||||
blkBytes0 := []byte{0}
|
||||
|
||||
blk0 := &Blk{
|
||||
id: blkID0,
|
||||
height: 0,
|
||||
status: choices.Accepted,
|
||||
bytes: blkBytes0,
|
||||
}
|
||||
|
||||
bs := bootstrapper{}
|
||||
bs.metrics.Initialize(config.Context.Log, fmt.Sprintf("gecko_%s", config.Context.ChainID), prometheus.NewRegistry())
|
||||
bs.Initialize(config)
|
||||
|
||||
acceptedIDs := ids.Set{}
|
||||
acceptedIDs.Add(
|
||||
blkID0,
|
||||
blkID1,
|
||||
)
|
||||
|
||||
vm.GetBlockF = func(blkID ids.ID) (snowman.Block, error) {
|
||||
switch {
|
||||
case blkID.Equals(blkID0):
|
||||
return blk0, nil
|
||||
case blkID.Equals(blkID1):
|
||||
return nil, errUnknownBlock
|
||||
default:
|
||||
t.Fatal(errUnknownBlock)
|
||||
panic(errUnknownBlock)
|
||||
}
|
||||
}
|
||||
|
||||
sender.CantGet = false
|
||||
bs.onFinished = func() {}
|
||||
|
||||
bs.ForceAccepted(acceptedIDs)
|
||||
|
||||
if bs.finished {
|
||||
t.Fatalf("should have requested a block")
|
||||
}
|
||||
|
||||
if bs.pending.Len() != 1 {
|
||||
t.Fatalf("wrong number pending")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,6 +324,11 @@ func (c codec) unmarshal(p *wrappers.Packer, field reflect.Value) error {
|
|||
if !ok {
|
||||
return errUnmarshalUnregisteredType
|
||||
}
|
||||
// Ensure struct actually does implement the interface
|
||||
fieldType := field.Type()
|
||||
if !typ.Implements(fieldType) {
|
||||
return fmt.Errorf("%s does not implement interface %s", typ, fieldType)
|
||||
}
|
||||
concreteInstancePtr := reflect.New(typ) // instance of the proper type
|
||||
// Unmarshal into the struct
|
||||
if err := c.unmarshal(p, concreteInstancePtr.Elem()); err != nil {
|
||||
|
|
|
@ -538,3 +538,42 @@ func TestTooLargeUnmarshal(t *testing.T) {
|
|||
t.Fatalf("Should have errored due to too many bytes provided")
|
||||
}
|
||||
}
|
||||
|
||||
type outerInterface interface {
|
||||
ToInt() int
|
||||
}
|
||||
|
||||
type outer struct {
|
||||
Interface outerInterface `serialize:"true"`
|
||||
}
|
||||
|
||||
type innerInterface struct{}
|
||||
|
||||
func (it *innerInterface) ToInt() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
type innerNoInterface struct{}
|
||||
|
||||
// Ensure deserializing structs into the wrong interface errors gracefully
|
||||
func TestUnmarshalInvalidInterface(t *testing.T) {
|
||||
codec := NewDefault()
|
||||
|
||||
codec.RegisterType(&innerInterface{})
|
||||
codec.RegisterType(&innerNoInterface{})
|
||||
|
||||
{
|
||||
bytes := []byte{0, 0, 0, 0}
|
||||
s := outer{}
|
||||
if err := codec.Unmarshal(bytes, &s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
{
|
||||
bytes := []byte{0, 0, 0, 1}
|
||||
s := outer{}
|
||||
if err := codec.Unmarshal(bytes, &s); err == nil {
|
||||
t.Fatalf("should have errored")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
stdnet "net"
|
||||
|
||||
|
@ -28,35 +29,47 @@ func init() {
|
|||
loggingConfig, err := logging.DefaultConfig()
|
||||
errs.Add(err)
|
||||
|
||||
fs := flag.NewFlagSet("xputtest", flag.ContinueOnError)
|
||||
|
||||
// NetworkID:
|
||||
networkName := flag.String("network-id", genesis.LocalName, "Network ID this node will connect to")
|
||||
networkName := fs.String("network-id", genesis.LocalName, "Network ID this node will connect to")
|
||||
|
||||
// Ava fees:
|
||||
flag.Uint64Var(&config.AvaTxFee, "ava-tx-fee", 0, "Ava transaction fee, in $nAva")
|
||||
fs.Uint64Var(&config.AvaTxFee, "ava-tx-fee", 0, "Ava transaction fee, in $nAva")
|
||||
|
||||
// Assertions:
|
||||
flag.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution")
|
||||
fs.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution")
|
||||
|
||||
// Crypto:
|
||||
flag.BoolVar(&config.EnableCrypto, "signature-verification-enabled", true, "Turn on signature verification")
|
||||
fs.BoolVar(&config.EnableCrypto, "signature-verification-enabled", true, "Turn on signature verification")
|
||||
|
||||
// Remote Server:
|
||||
ip := flag.String("ip", "127.0.0.1", "IP address of the remote server socket")
|
||||
port := flag.Uint("port", 9652, "Port of the remote server socket")
|
||||
ip := fs.String("ip", "127.0.0.1", "IP address of the remote server socket")
|
||||
port := fs.Uint("port", 9652, "Port of the remote server socket")
|
||||
|
||||
// Logging:
|
||||
logsDir := flag.String("log-dir", "", "Logging directory for Ava")
|
||||
logLevel := flag.String("log-level", "info", "The log level. Should be one of {all, debug, info, warn, error, fatal, off}")
|
||||
logsDir := fs.String("log-dir", "", "Logging directory for Ava")
|
||||
logLevel := fs.String("log-level", "info", "The log level. Should be one of {all, debug, info, warn, error, fatal, off}")
|
||||
|
||||
// Test Variables:
|
||||
spchain := flag.Bool("sp-chain", false, "Execute simple payment chain transactions")
|
||||
spdag := flag.Bool("sp-dag", false, "Execute simple payment dag transactions")
|
||||
avm := flag.Bool("avm", false, "Execute avm transactions")
|
||||
flag.IntVar(&config.Key, "key", 0, "Index of the genesis key list to use")
|
||||
flag.IntVar(&config.NumTxs, "num-txs", 25000, "Total number of transaction to issue")
|
||||
flag.IntVar(&config.MaxOutstandingTxs, "max-outstanding", 1000, "Maximum number of transactions to leave outstanding")
|
||||
spchain := fs.Bool("sp-chain", false, "Execute simple payment chain transactions")
|
||||
spdag := fs.Bool("sp-dag", false, "Execute simple payment dag transactions")
|
||||
avm := fs.Bool("avm", false, "Execute avm transactions")
|
||||
fs.IntVar(&config.Key, "key", 0, "Index of the genesis key list to use")
|
||||
fs.IntVar(&config.NumTxs, "num-txs", 25000, "Total number of transaction to issue")
|
||||
fs.IntVar(&config.MaxOutstandingTxs, "max-outstanding", 1000, "Maximum number of transactions to leave outstanding")
|
||||
|
||||
flag.Parse()
|
||||
ferr := fs.Parse(os.Args[1:])
|
||||
|
||||
if ferr == flag.ErrHelp {
|
||||
// display usage/help text and exit successfully
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if ferr != nil {
|
||||
// other type of error occurred when parsing args
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
networkID, err := genesis.NetworkID(*networkName)
|
||||
errs.Add(err)
|
||||
|
|
Loading…
Reference in New Issue