Merge branch 'master' into custom-genesis

This commit is contained in:
Stephen Buttolph 2020-03-27 12:11:19 -04:00 committed by GitHub
commit 10779d168d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 243 additions and 59 deletions

3
.gitignore vendored
View File

@ -18,6 +18,9 @@ awscpu
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out
# ignore GoLand metafiles directory
.idea/
*logs/ *logs/
.vscode* .vscode*

View File

@ -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`. - 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 - 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. `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, --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 you may want to extend the docker image with required credentials for
staking and TLS.) staking and TLS.)

View File

@ -391,7 +391,7 @@ func (m *manager) createAvalancheChain(
Context: ctx, Context: ctx,
Validators: validators, Validators: validators,
Beacons: beacons, Beacons: beacons,
Alpha: (beacons.Len() + 1) / 2, Alpha: beacons.Len()/2 + 1, // must be > 50%
Sender: &sender, Sender: &sender,
}, },
VtxBlocked: vtxBlocker, VtxBlocked: vtxBlocker,
@ -471,7 +471,7 @@ func (m *manager) createSnowmanChain(
Context: ctx, Context: ctx,
Validators: validators, Validators: validators,
Beacons: beacons, Beacons: beacons,
Alpha: (beacons.Len() + 1) / 2, Alpha: beacons.Len()/2 + 1, // must be > 50%
Sender: &sender, Sender: &sender,
}, },
Blocked: blocked, Blocked: blocked,

View File

@ -8,6 +8,7 @@ import (
"flag" "flag"
"fmt" "fmt"
"net" "net"
"os"
"path" "path"
"strings" "strings"
@ -44,64 +45,76 @@ func init() {
loggingConfig, err := logging.DefaultConfig() loggingConfig, err := logging.DefaultConfig()
errs.Add(err) errs.Add(err)
fs := flag.NewFlagSet("gecko", flag.ContinueOnError)
// NetworkID: // 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: // 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: // Assertions:
flag.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution") fs.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution")
// Crypto: // 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: // Database:
db := flag.Bool("db-enabled", true, "Turn on persistent storage") db := fs.Bool("db-enabled", true, "Turn on persistent storage")
dbDir := flag.String("db-dir", "db", "Database directory for Ava state") dbDir := fs.String("db-dir", "db", "Database directory for Ava state")
// IP: // IP:
consensusIP := flag.String("public-ip", "", "Public IP of this node") consensusIP := fs.String("public-ip", "", "Public IP of this node")
// HTTP Server: // HTTP Server:
httpPort := flag.Uint("http-port", 9650, "Port of the HTTP server") httpPort := fs.Uint("http-port", 9650, "Port of the HTTP server")
flag.BoolVar(&Config.EnableHTTPS, "http-tls-enabled", false, "Upgrade the HTTP server to HTTPs") fs.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") fs.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") fs.StringVar(&Config.HTTPSCertFile, "http-tls-cert-file", "", "TLS certificate file for the HTTPs server")
// Bootstrapping: // 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") 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 := flag.String("bootstrap-ids", "", "Comma separated list of bootstrap peer ids to connect to. Example: JR4dVmy6ffUGAKCBDkyCbeZbyHQBeDsET,8CrVPQZ4VSqgL8zTdvL14G8HqAfrBr4z") bootstrapIDs := fs.String("bootstrap-ids", "", "Comma separated list of bootstrap peer ids to connect to. Example: JR4dVmy6ffUGAKCBDkyCbeZbyHQBeDsET,8CrVPQZ4VSqgL8zTdvL14G8HqAfrBr4z")
// Staking: // Staking:
consensusPort := flag.Uint("staking-port", 9651, "Port of the consensus server") consensusPort := fs.Uint("staking-port", 9651, "Port of the consensus server")
flag.BoolVar(&Config.EnableStaking, "staking-tls-enabled", true, "Require TLS to authenticate staking connections") fs.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") fs.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") fs.StringVar(&Config.StakingCertFile, "staking-tls-cert-file", "", "TLS certificate file for staking connections")
// Logging: // Logging:
logsDir := flag.String("log-dir", "", "Logging directory for Ava") logsDir := fs.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}") logLevel := fs.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}") 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") fs.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") fs.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") fs.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") fs.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") fs.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.BatchSize, "snow-avalanche-batch-size", 30, "Number of operations to batch in each new vertex")
// Enable/Disable APIs: // Enable/Disable APIs:
flag.BoolVar(&Config.AdminAPIEnabled, "api-admin-enabled", true, "If true, this node exposes the Admin API") fs.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") fs.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") fs.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.IPCEnabled, "api-ipcs-enabled", false, "If true, IPCs can be opened")
// Throughput Server // Throughput Server
throughputPort := flag.Uint("xput-server-port", 9652, "Port of the deprecated throughput test server") throughputPort := fs.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") 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) networkID, err := genesis.NetworkID(*networkName)
errs.Add(err) errs.Add(err)

View File

@ -119,7 +119,7 @@ func (b *bootstrapper) fetch(vtxID ids.ID) {
b.sendRequest(vtxID) b.sendRequest(vtxID)
return return
} }
b.addVertex(vtx) b.storeVertex(vtx)
} }
func (b *bootstrapper) sendRequest(vtxID ids.ID) { 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) { 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} vts := []avalanche.Vertex{vtx}
for len(vts) > 0 { for len(vts) > 0 {
@ -181,9 +189,6 @@ func (b *bootstrapper) addVertex(vtx avalanche.Vertex) {
numPending := b.pending.Len() numPending := b.pending.Len()
b.numPendingRequests.Set(float64(numPending)) b.numPendingRequests.Set(float64(numPending))
if numPending == 0 {
b.finish()
}
} }
func (b *bootstrapper) finish() { func (b *bootstrapper) finish() {

View File

@ -957,3 +957,53 @@ func TestBootstrapperFilterAccepted(t *testing.T) {
t.Fatalf("Vtx shouldn't be accepted") 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")
}
}

View File

@ -113,7 +113,7 @@ func (b *bootstrapper) fetch(blkID ids.ID) {
b.sendRequest(blkID) b.sendRequest(blkID)
return return
} }
b.addBlock(blk) b.storeBlock(blk)
} }
func (b *bootstrapper) sendRequest(blkID ids.ID) { 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) { 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() status := blk.Status()
blkID := blk.ID() blkID := blk.ID()
for status == choices.Processing { for status == choices.Processing {
@ -161,9 +169,6 @@ func (b *bootstrapper) addBlock(blk snowman.Block) {
numPending := b.pending.Len() numPending := b.pending.Len()
b.numPendingRequests.Set(float64(numPending)) b.numPendingRequests.Set(float64(numPending))
if numPending == 0 {
b.finish()
}
} }
func (b *bootstrapper) finish() { func (b *bootstrapper) finish() {

View File

@ -425,3 +425,54 @@ func TestBootstrapperFilterAccepted(t *testing.T) {
t.Fatalf("Blk shouldn't be accepted") 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")
}
}

View File

@ -324,6 +324,11 @@ func (c codec) unmarshal(p *wrappers.Packer, field reflect.Value) error {
if !ok { if !ok {
return errUnmarshalUnregisteredType 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 concreteInstancePtr := reflect.New(typ) // instance of the proper type
// Unmarshal into the struct // Unmarshal into the struct
if err := c.unmarshal(p, concreteInstancePtr.Elem()); err != nil { if err := c.unmarshal(p, concreteInstancePtr.Elem()); err != nil {

View File

@ -538,3 +538,42 @@ func TestTooLargeUnmarshal(t *testing.T) {
t.Fatalf("Should have errored due to too many bytes provided") 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")
}
}
}

View File

@ -6,6 +6,7 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"os"
stdnet "net" stdnet "net"
@ -28,35 +29,47 @@ func init() {
loggingConfig, err := logging.DefaultConfig() loggingConfig, err := logging.DefaultConfig()
errs.Add(err) errs.Add(err)
fs := flag.NewFlagSet("xputtest", flag.ContinueOnError)
// NetworkID: // 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: // 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: // Assertions:
flag.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution") fs.BoolVar(&loggingConfig.Assertions, "assertions-enabled", true, "Turn on assertion execution")
// Crypto: // 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: // Remote Server:
ip := flag.String("ip", "127.0.0.1", "IP address of the remote server socket") ip := fs.String("ip", "127.0.0.1", "IP address of the remote server socket")
port := flag.Uint("port", 9652, "Port of the remote server socket") port := fs.Uint("port", 9652, "Port of the remote server socket")
// Logging: // Logging:
logsDir := flag.String("log-dir", "", "Logging directory for Ava") logsDir := fs.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}") logLevel := fs.String("log-level", "info", "The log level. Should be one of {all, debug, info, warn, error, fatal, off}")
// Test Variables: // Test Variables:
spchain := flag.Bool("sp-chain", false, "Execute simple payment chain transactions") spchain := fs.Bool("sp-chain", false, "Execute simple payment chain transactions")
spdag := flag.Bool("sp-dag", false, "Execute simple payment dag transactions") spdag := fs.Bool("sp-dag", false, "Execute simple payment dag transactions")
avm := flag.Bool("avm", false, "Execute avm transactions") avm := fs.Bool("avm", false, "Execute avm transactions")
flag.IntVar(&config.Key, "key", 0, "Index of the genesis key list to use") fs.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") fs.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") 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) networkID, err := genesis.NetworkID(*networkName)
errs.Add(err) errs.Add(err)