mirror of https://github.com/poanetwork/gecko.git
Merge branch 'master' of github.com:ava-labs/gecko-internal
This commit is contained in:
commit
a20a54af4e
|
@ -10,129 +10,35 @@ import (
|
|||
|
||||
"github.com/ava-labs/gecko/api"
|
||||
"github.com/ava-labs/gecko/chains"
|
||||
"github.com/ava-labs/gecko/genesis"
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/network"
|
||||
"github.com/ava-labs/gecko/snow/engine/common"
|
||||
"github.com/ava-labs/gecko/utils/logging"
|
||||
"github.com/ava-labs/gecko/version"
|
||||
|
||||
cjson "github.com/ava-labs/gecko/utils/json"
|
||||
)
|
||||
|
||||
// Admin is the API service for node admin management
|
||||
type Admin struct {
|
||||
version version.Version
|
||||
nodeID ids.ShortID
|
||||
networkID uint32
|
||||
log logging.Logger
|
||||
networking network.Network
|
||||
performance Performance
|
||||
chainManager chains.Manager
|
||||
httpServer *api.Server
|
||||
}
|
||||
|
||||
// NewService returns a new admin API service
|
||||
func NewService(version version.Version, nodeID ids.ShortID, networkID uint32, log logging.Logger, chainManager chains.Manager, peers network.Network, httpServer *api.Server) *common.HTTPHandler {
|
||||
func NewService(log logging.Logger, chainManager chains.Manager, peers network.Network, httpServer *api.Server) *common.HTTPHandler {
|
||||
newServer := rpc.NewServer()
|
||||
codec := cjson.NewCodec()
|
||||
newServer.RegisterCodec(codec, "application/json")
|
||||
newServer.RegisterCodec(codec, "application/json;charset=UTF-8")
|
||||
newServer.RegisterService(&Admin{
|
||||
version: version,
|
||||
nodeID: nodeID,
|
||||
networkID: networkID,
|
||||
log: log,
|
||||
chainManager: chainManager,
|
||||
networking: peers,
|
||||
httpServer: httpServer,
|
||||
}, "admin")
|
||||
return &common.HTTPHandler{Handler: newServer}
|
||||
}
|
||||
|
||||
// GetNodeVersionReply are the results from calling GetNodeVersion
|
||||
type GetNodeVersionReply struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// GetNodeVersion returns the version this node is running
|
||||
func (service *Admin) GetNodeVersion(_ *http.Request, _ *struct{}, reply *GetNodeVersionReply) error {
|
||||
service.log.Info("Admin: GetNodeVersion called")
|
||||
|
||||
reply.Version = service.version.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNodeIDReply are the results from calling GetNodeID
|
||||
type GetNodeIDReply struct {
|
||||
NodeID ids.ShortID `json:"nodeID"`
|
||||
}
|
||||
|
||||
// GetNodeID returns the node ID of this node
|
||||
func (service *Admin) GetNodeID(_ *http.Request, _ *struct{}, reply *GetNodeIDReply) error {
|
||||
service.log.Info("Admin: GetNodeID called")
|
||||
|
||||
reply.NodeID = service.nodeID
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNetworkIDReply are the results from calling GetNetworkID
|
||||
type GetNetworkIDReply struct {
|
||||
NetworkID cjson.Uint32 `json:"networkID"`
|
||||
}
|
||||
|
||||
// GetNetworkID returns the network ID this node is running on
|
||||
func (service *Admin) GetNetworkID(_ *http.Request, _ *struct{}, reply *GetNetworkIDReply) error {
|
||||
service.log.Info("Admin: GetNetworkID called")
|
||||
|
||||
reply.NetworkID = cjson.Uint32(service.networkID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNetworkNameReply is the result from calling GetNetworkName
|
||||
type GetNetworkNameReply struct {
|
||||
NetworkName string `json:"networkName"`
|
||||
}
|
||||
|
||||
// GetNetworkName returns the network name this node is running on
|
||||
func (service *Admin) GetNetworkName(_ *http.Request, _ *struct{}, reply *GetNetworkNameReply) error {
|
||||
service.log.Info("Admin: GetNetworkName called")
|
||||
|
||||
reply.NetworkName = genesis.NetworkName(service.networkID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBlockchainIDArgs are the arguments for calling GetBlockchainID
|
||||
type GetBlockchainIDArgs struct {
|
||||
Alias string `json:"alias"`
|
||||
}
|
||||
|
||||
// GetBlockchainIDReply are the results from calling GetBlockchainID
|
||||
type GetBlockchainIDReply struct {
|
||||
BlockchainID string `json:"blockchainID"`
|
||||
}
|
||||
|
||||
// GetBlockchainID returns the blockchain ID that resolves the alias that was supplied
|
||||
func (service *Admin) GetBlockchainID(_ *http.Request, args *GetBlockchainIDArgs, reply *GetBlockchainIDReply) error {
|
||||
service.log.Info("Admin: GetBlockchainID called")
|
||||
|
||||
bID, err := service.chainManager.Lookup(args.Alias)
|
||||
reply.BlockchainID = bID.String()
|
||||
return err
|
||||
}
|
||||
|
||||
// PeersReply are the results from calling Peers
|
||||
type PeersReply struct {
|
||||
Peers []network.PeerID `json:"peers"`
|
||||
}
|
||||
|
||||
// Peers returns the list of current validators
|
||||
func (service *Admin) Peers(_ *http.Request, _ *struct{}, reply *PeersReply) error {
|
||||
service.log.Info("Admin: Peers called")
|
||||
reply.Peers = service.networking.Peers()
|
||||
return nil
|
||||
}
|
||||
|
||||
// StartCPUProfilerArgs are the arguments for calling StartCPUProfiler
|
||||
type StartCPUProfilerArgs struct {
|
||||
Filename string `json:"filename"`
|
||||
|
|
|
@ -7,11 +7,13 @@ import (
|
|||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/AppsFlyer/go-sundheit"
|
||||
health "github.com/AppsFlyer/go-sundheit"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
|
||||
"github.com/ava-labs/gecko/snow/engine/common"
|
||||
"github.com/ava-labs/gecko/utils/json"
|
||||
"github.com/ava-labs/gecko/utils/logging"
|
||||
"github.com/gorilla/rpc/v2"
|
||||
)
|
||||
|
||||
// defaultCheckOpts is a Check whose properties represent a default Check
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package info
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
|
||||
"github.com/ava-labs/gecko/chains"
|
||||
"github.com/ava-labs/gecko/genesis"
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/network"
|
||||
"github.com/ava-labs/gecko/snow/engine/common"
|
||||
"github.com/ava-labs/gecko/utils/logging"
|
||||
"github.com/ava-labs/gecko/version"
|
||||
|
||||
cjson "github.com/ava-labs/gecko/utils/json"
|
||||
)
|
||||
|
||||
// Info is the API service for unprivileged info on a node
|
||||
type Info struct {
|
||||
version version.Version
|
||||
nodeID ids.ShortID
|
||||
networkID uint32
|
||||
log logging.Logger
|
||||
networking network.Network
|
||||
chainManager chains.Manager
|
||||
}
|
||||
|
||||
// NewService returns a new admin API service
|
||||
func NewService(log logging.Logger, version version.Version, nodeID ids.ShortID, networkID uint32, chainManager chains.Manager, peers network.Network) *common.HTTPHandler {
|
||||
newServer := rpc.NewServer()
|
||||
codec := cjson.NewCodec()
|
||||
newServer.RegisterCodec(codec, "application/json")
|
||||
newServer.RegisterCodec(codec, "application/json;charset=UTF-8")
|
||||
newServer.RegisterService(&Info{
|
||||
version: version,
|
||||
nodeID: nodeID,
|
||||
networkID: networkID,
|
||||
log: log,
|
||||
chainManager: chainManager,
|
||||
networking: peers,
|
||||
}, "info")
|
||||
return &common.HTTPHandler{Handler: newServer}
|
||||
}
|
||||
|
||||
// GetNodeVersionReply are the results from calling GetNodeVersion
|
||||
type GetNodeVersionReply struct {
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// GetNodeVersion returns the version this node is running
|
||||
func (service *Info) GetNodeVersion(_ *http.Request, _ *struct{}, reply *GetNodeVersionReply) error {
|
||||
service.log.Info("Info: GetNodeVersion called")
|
||||
|
||||
reply.Version = service.version.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNodeIDReply are the results from calling GetNodeID
|
||||
type GetNodeIDReply struct {
|
||||
NodeID ids.ShortID `json:"nodeID"`
|
||||
}
|
||||
|
||||
// GetNodeID returns the node ID of this node
|
||||
func (service *Info) GetNodeID(_ *http.Request, _ *struct{}, reply *GetNodeIDReply) error {
|
||||
service.log.Info("Info: GetNodeID called")
|
||||
|
||||
reply.NodeID = service.nodeID
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNetworkIDReply are the results from calling GetNetworkID
|
||||
type GetNetworkIDReply struct {
|
||||
NetworkID cjson.Uint32 `json:"networkID"`
|
||||
}
|
||||
|
||||
// GetNetworkID returns the network ID this node is running on
|
||||
func (service *Info) GetNetworkID(_ *http.Request, _ *struct{}, reply *GetNetworkIDReply) error {
|
||||
service.log.Info("Info: GetNetworkID called")
|
||||
|
||||
reply.NetworkID = cjson.Uint32(service.networkID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetNetworkNameReply is the result from calling GetNetworkName
|
||||
type GetNetworkNameReply struct {
|
||||
NetworkName string `json:"networkName"`
|
||||
}
|
||||
|
||||
// GetNetworkName returns the network name this node is running on
|
||||
func (service *Info) GetNetworkName(_ *http.Request, _ *struct{}, reply *GetNetworkNameReply) error {
|
||||
service.log.Info("Info: GetNetworkName called")
|
||||
|
||||
reply.NetworkName = genesis.NetworkName(service.networkID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetBlockchainIDArgs are the arguments for calling GetBlockchainID
|
||||
type GetBlockchainIDArgs struct {
|
||||
Alias string `json:"alias"`
|
||||
}
|
||||
|
||||
// GetBlockchainIDReply are the results from calling GetBlockchainID
|
||||
type GetBlockchainIDReply struct {
|
||||
BlockchainID string `json:"blockchainID"`
|
||||
}
|
||||
|
||||
// GetBlockchainID returns the blockchain ID that resolves the alias that was supplied
|
||||
func (service *Info) GetBlockchainID(_ *http.Request, args *GetBlockchainIDArgs, reply *GetBlockchainIDReply) error {
|
||||
service.log.Info("Info: GetBlockchainID called")
|
||||
|
||||
bID, err := service.chainManager.Lookup(args.Alias)
|
||||
reply.BlockchainID = bID.String()
|
||||
return err
|
||||
}
|
||||
|
||||
// PeersReply are the results from calling Peers
|
||||
type PeersReply struct {
|
||||
Peers []network.PeerID `json:"peers"`
|
||||
}
|
||||
|
||||
// Peers returns the list of current validators
|
||||
func (service *Info) Peers(_ *http.Request, _ *struct{}, reply *PeersReply) error {
|
||||
service.log.Info("Info: Peers called")
|
||||
|
||||
reply.Peers = service.networking.Peers()
|
||||
return nil
|
||||
}
|
|
@ -12,6 +12,8 @@ import (
|
|||
|
||||
"github.com/gorilla/rpc/v2"
|
||||
|
||||
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||||
|
||||
"github.com/ava-labs/gecko/chains/atomic"
|
||||
"github.com/ava-labs/gecko/database"
|
||||
"github.com/ava-labs/gecko/database/encdb"
|
||||
|
@ -19,12 +21,11 @@ import (
|
|||
"github.com/ava-labs/gecko/database/prefixdb"
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/snow/engine/common"
|
||||
"github.com/ava-labs/gecko/utils/codec"
|
||||
"github.com/ava-labs/gecko/utils/formatting"
|
||||
"github.com/ava-labs/gecko/utils/logging"
|
||||
"github.com/ava-labs/gecko/utils/codec"
|
||||
|
||||
jsoncodec "github.com/ava-labs/gecko/utils/json"
|
||||
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -4,9 +4,10 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/ava-labs/gecko/snow/engine/common"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
|
||||
"github.com/ava-labs/gecko/snow/engine/common"
|
||||
)
|
||||
|
||||
// NewService returns a new prometheus service
|
||||
|
|
|
@ -10,9 +10,9 @@ import (
|
|||
"github.com/ava-labs/gecko/database"
|
||||
"github.com/ava-labs/gecko/database/prefixdb"
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/utils/codec"
|
||||
"github.com/ava-labs/gecko/utils/hashing"
|
||||
"github.com/ava-labs/gecko/utils/logging"
|
||||
"github.com/ava-labs/gecko/utils/codec"
|
||||
)
|
||||
|
||||
type rcLock struct {
|
||||
|
|
|
@ -13,8 +13,8 @@ import (
|
|||
"github.com/ava-labs/gecko/database"
|
||||
"github.com/ava-labs/gecko/database/nodb"
|
||||
"github.com/ava-labs/gecko/utils"
|
||||
"github.com/ava-labs/gecko/utils/hashing"
|
||||
"github.com/ava-labs/gecko/utils/codec"
|
||||
"github.com/ava-labs/gecko/utils/hashing"
|
||||
)
|
||||
|
||||
// Database encrypts all values that are provided
|
||||
|
|
|
@ -6,14 +6,15 @@ package leveldb
|
|||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/ava-labs/gecko/database"
|
||||
"github.com/ava-labs/gecko/utils"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
"github.com/syndtr/goleveldb/leveldb/errors"
|
||||
"github.com/syndtr/goleveldb/leveldb/filter"
|
||||
"github.com/syndtr/goleveldb/leveldb/iterator"
|
||||
"github.com/syndtr/goleveldb/leveldb/opt"
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
|
||||
"github.com/ava-labs/gecko/database"
|
||||
"github.com/ava-labs/gecko/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -17,7 +17,7 @@ func (*Database) Has([]byte) (bool, error) { return false, database.ErrClosed }
|
|||
func (*Database) Get([]byte) ([]byte, error) { return nil, database.ErrClosed }
|
||||
|
||||
// Put returns nil
|
||||
func (*Database) Put(_ []byte, _ []byte) error { return database.ErrClosed }
|
||||
func (*Database) Put(_, _ []byte) error { return database.ErrClosed }
|
||||
|
||||
// Delete returns nil
|
||||
func (*Database) Delete([]byte) error { return database.ErrClosed }
|
||||
|
|
|
@ -27,7 +27,7 @@ func NewClient(client rpcdbproto.DatabaseClient) *DatabaseClient {
|
|||
return &DatabaseClient{client: client}
|
||||
}
|
||||
|
||||
// Has returns false, nil
|
||||
// Has attempts to return if the database has a key with the provided value.
|
||||
func (db *DatabaseClient) Has(key []byte) (bool, error) {
|
||||
resp, err := db.client.Has(context.Background(), &rpcdbproto.HasRequest{
|
||||
Key: key,
|
||||
|
@ -38,7 +38,7 @@ func (db *DatabaseClient) Has(key []byte) (bool, error) {
|
|||
return resp.Has, nil
|
||||
}
|
||||
|
||||
// Get returns nil, error
|
||||
// Get attempts to return the value that was mapped to the key that was provided
|
||||
func (db *DatabaseClient) Get(key []byte) ([]byte, error) {
|
||||
resp, err := db.client.Get(context.Background(), &rpcdbproto.GetRequest{
|
||||
Key: key,
|
||||
|
@ -49,7 +49,7 @@ func (db *DatabaseClient) Get(key []byte) ([]byte, error) {
|
|||
return resp.Value, nil
|
||||
}
|
||||
|
||||
// Put returns nil
|
||||
// Put attempts to set the value this key maps to
|
||||
func (db *DatabaseClient) Put(key, value []byte) error {
|
||||
_, err := db.client.Put(context.Background(), &rpcdbproto.PutRequest{
|
||||
Key: key,
|
||||
|
@ -58,7 +58,7 @@ func (db *DatabaseClient) Put(key, value []byte) error {
|
|||
return updateError(err)
|
||||
}
|
||||
|
||||
// Delete returns nil
|
||||
// Delete attempts to remove any mapping from the key
|
||||
func (db *DatabaseClient) Delete(key []byte) error {
|
||||
_, err := db.client.Delete(context.Background(), &rpcdbproto.DeleteRequest{
|
||||
Key: key,
|
||||
|
@ -99,7 +99,7 @@ func (db *DatabaseClient) NewIteratorWithStartAndPrefix(start, prefix []byte) da
|
|||
}
|
||||
}
|
||||
|
||||
// Stat returns an error
|
||||
// Stat attempts to return the statistic of this database
|
||||
func (db *DatabaseClient) Stat(property string) (string, error) {
|
||||
resp, err := db.client.Stat(context.Background(), &rpcdbproto.StatRequest{
|
||||
Property: property,
|
||||
|
@ -110,7 +110,7 @@ func (db *DatabaseClient) Stat(property string) (string, error) {
|
|||
return resp.Stat, nil
|
||||
}
|
||||
|
||||
// Compact returns nil
|
||||
// Compact attempts to optimize the space utilization in the provided range
|
||||
func (db *DatabaseClient) Compact(start, limit []byte) error {
|
||||
_, err := db.client.Compact(context.Background(), &rpcdbproto.CompactRequest{
|
||||
Start: start,
|
||||
|
@ -119,7 +119,7 @@ func (db *DatabaseClient) Compact(start, limit []byte) error {
|
|||
return updateError(err)
|
||||
}
|
||||
|
||||
// Close returns nil
|
||||
// Close attempts to close the database
|
||||
func (db *DatabaseClient) Close() error {
|
||||
_, err := db.client.Close(context.Background(), &rpcdbproto.CloseRequest{})
|
||||
return updateError(err)
|
||||
|
@ -207,7 +207,8 @@ type iterator struct {
|
|||
err error
|
||||
}
|
||||
|
||||
// Next returns false
|
||||
// Next attempts to move the iterator to the next element and returns if this
|
||||
// succeeded
|
||||
func (it *iterator) Next() bool {
|
||||
resp, err := it.db.client.IteratorNext(context.Background(), &rpcdbproto.IteratorNextRequest{
|
||||
Id: it.id,
|
||||
|
@ -221,7 +222,7 @@ func (it *iterator) Next() bool {
|
|||
return resp.FoundNext
|
||||
}
|
||||
|
||||
// Error returns any errors
|
||||
// Error returns any that occurred while iterating
|
||||
func (it *iterator) Error() error {
|
||||
if it.err != nil {
|
||||
return it.err
|
||||
|
@ -234,19 +235,21 @@ func (it *iterator) Error() error {
|
|||
return it.err
|
||||
}
|
||||
|
||||
// Key returns nil
|
||||
// Key returns the key of the current element
|
||||
func (it *iterator) Key() []byte { return it.key }
|
||||
|
||||
// Value returns nil
|
||||
// Value returns the value of the current element
|
||||
func (it *iterator) Value() []byte { return it.value }
|
||||
|
||||
// Release does nothing
|
||||
// Release frees any resources held by the iterator
|
||||
func (it *iterator) Release() {
|
||||
it.db.client.IteratorRelease(context.Background(), &rpcdbproto.IteratorReleaseRequest{
|
||||
Id: it.id,
|
||||
})
|
||||
}
|
||||
|
||||
// updateError sets the error value to the errors required by the Database
|
||||
// interface
|
||||
func updateError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
|
|
|
@ -34,16 +34,16 @@ func NewServer(db database.Database) *DatabaseServer {
|
|||
}
|
||||
}
|
||||
|
||||
// Has ...
|
||||
// Has delegates the Has call to the managed database and returns the result
|
||||
func (db *DatabaseServer) Has(_ context.Context, req *rpcdbproto.HasRequest) (*rpcdbproto.HasResponse, error) {
|
||||
has, err := db.db.Has(req.Key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &rpcdbproto.HasResponse{Has: has}, nil
|
||||
return &rpcdbproto.HasResponse{Has: has}, err
|
||||
}
|
||||
|
||||
// Get ...
|
||||
// Get delegates the Get call to the managed database and returns the result
|
||||
func (db *DatabaseServer) Get(_ context.Context, req *rpcdbproto.GetRequest) (*rpcdbproto.GetResponse, error) {
|
||||
value, err := db.db.Get(req.Key)
|
||||
if err != nil {
|
||||
|
@ -52,17 +52,18 @@ func (db *DatabaseServer) Get(_ context.Context, req *rpcdbproto.GetRequest) (*r
|
|||
return &rpcdbproto.GetResponse{Value: value}, nil
|
||||
}
|
||||
|
||||
// Put ...
|
||||
// Put delegates the Put call to the managed database and returns the result
|
||||
func (db *DatabaseServer) Put(_ context.Context, req *rpcdbproto.PutRequest) (*rpcdbproto.PutResponse, error) {
|
||||
return &rpcdbproto.PutResponse{}, db.db.Put(req.Key, req.Value)
|
||||
}
|
||||
|
||||
// Delete ...
|
||||
// Delete delegates the Delete call to the managed database and returns the
|
||||
// result
|
||||
func (db *DatabaseServer) Delete(_ context.Context, req *rpcdbproto.DeleteRequest) (*rpcdbproto.DeleteResponse, error) {
|
||||
return &rpcdbproto.DeleteResponse{}, db.db.Delete(req.Key)
|
||||
}
|
||||
|
||||
// Stat ...
|
||||
// Stat delegates the Stat call to the managed database and returns the result
|
||||
func (db *DatabaseServer) Stat(_ context.Context, req *rpcdbproto.StatRequest) (*rpcdbproto.StatResponse, error) {
|
||||
stat, err := db.db.Stat(req.Property)
|
||||
if err != nil {
|
||||
|
@ -71,17 +72,19 @@ func (db *DatabaseServer) Stat(_ context.Context, req *rpcdbproto.StatRequest) (
|
|||
return &rpcdbproto.StatResponse{Stat: stat}, nil
|
||||
}
|
||||
|
||||
// Compact ...
|
||||
// Compact delegates the Compact call to the managed database and returns the
|
||||
// result
|
||||
func (db *DatabaseServer) Compact(_ context.Context, req *rpcdbproto.CompactRequest) (*rpcdbproto.CompactResponse, error) {
|
||||
return &rpcdbproto.CompactResponse{}, db.db.Compact(req.Start, req.Limit)
|
||||
}
|
||||
|
||||
// Close ...
|
||||
func (db *DatabaseServer) Close(_ context.Context, _ *rpcdbproto.CloseRequest) (*rpcdbproto.CloseResponse, error) {
|
||||
// Close delegates the Close call to the managed database and returns the result
|
||||
func (db *DatabaseServer) Close(context.Context, *rpcdbproto.CloseRequest) (*rpcdbproto.CloseResponse, error) {
|
||||
return &rpcdbproto.CloseResponse{}, db.db.Close()
|
||||
}
|
||||
|
||||
// WriteBatch ...
|
||||
// WriteBatch takes in a set of key-value pairs and atomically writes them to
|
||||
// the internal database
|
||||
func (db *DatabaseServer) WriteBatch(_ context.Context, req *rpcdbproto.WriteBatchRequest) (*rpcdbproto.WriteBatchResponse, error) {
|
||||
db.batch.Reset()
|
||||
|
||||
|
@ -100,7 +103,8 @@ func (db *DatabaseServer) WriteBatch(_ context.Context, req *rpcdbproto.WriteBat
|
|||
return &rpcdbproto.WriteBatchResponse{}, db.batch.Write()
|
||||
}
|
||||
|
||||
// NewIteratorWithStartAndPrefix ...
|
||||
// NewIteratorWithStartAndPrefix allocates an iterator and returns the iterator
|
||||
// ID
|
||||
func (db *DatabaseServer) NewIteratorWithStartAndPrefix(_ context.Context, req *rpcdbproto.NewIteratorWithStartAndPrefixRequest) (*rpcdbproto.NewIteratorWithStartAndPrefixResponse, error) {
|
||||
id := db.nextIteratorID
|
||||
it := db.db.NewIteratorWithStartAndPrefix(req.Start, req.Prefix)
|
||||
|
@ -110,7 +114,7 @@ func (db *DatabaseServer) NewIteratorWithStartAndPrefix(_ context.Context, req *
|
|||
return &rpcdbproto.NewIteratorWithStartAndPrefixResponse{Id: id}, nil
|
||||
}
|
||||
|
||||
// IteratorNext ...
|
||||
// IteratorNext attempts to call next on the requested iterator
|
||||
func (db *DatabaseServer) IteratorNext(_ context.Context, req *rpcdbproto.IteratorNextRequest) (*rpcdbproto.IteratorNextResponse, error) {
|
||||
it, exists := db.iterators[req.Id]
|
||||
if !exists {
|
||||
|
@ -123,7 +127,7 @@ func (db *DatabaseServer) IteratorNext(_ context.Context, req *rpcdbproto.Iterat
|
|||
}, nil
|
||||
}
|
||||
|
||||
// IteratorError ...
|
||||
// IteratorError attempts to report any errors that occurred during iteration
|
||||
func (db *DatabaseServer) IteratorError(_ context.Context, req *rpcdbproto.IteratorErrorRequest) (*rpcdbproto.IteratorErrorResponse, error) {
|
||||
it, exists := db.iterators[req.Id]
|
||||
if !exists {
|
||||
|
@ -132,7 +136,7 @@ func (db *DatabaseServer) IteratorError(_ context.Context, req *rpcdbproto.Itera
|
|||
return &rpcdbproto.IteratorErrorResponse{}, it.Error()
|
||||
}
|
||||
|
||||
// IteratorRelease ...
|
||||
// IteratorRelease attempts to release the resources allocated to an iterator
|
||||
func (db *DatabaseServer) IteratorRelease(_ context.Context, req *rpcdbproto.IteratorReleaseRequest) (*rpcdbproto.IteratorReleaseResponse, error) {
|
||||
it, exists := db.iterators[req.Id]
|
||||
if exists {
|
||||
|
|
|
@ -18,27 +18,27 @@ import (
|
|||
// Aliases returns the default aliases based on the network ID
|
||||
func Aliases(networkID uint32) (map[string][]string, map[[32]byte][]string, map[[32]byte][]string, error) {
|
||||
generalAliases := map[string][]string{
|
||||
"vm/" + platformvm.ID.String(): []string{"vm/platform"},
|
||||
"vm/" + avm.ID.String(): []string{"vm/avm"},
|
||||
"vm/" + EVMID.String(): []string{"vm/evm"},
|
||||
"vm/" + spdagvm.ID.String(): []string{"vm/spdag"},
|
||||
"vm/" + spchainvm.ID.String(): []string{"vm/spchain"},
|
||||
"vm/" + timestampvm.ID.String(): []string{"vm/timestamp"},
|
||||
"bc/" + ids.Empty.String(): []string{"P", "platform", "bc/P", "bc/platform"},
|
||||
"vm/" + platformvm.ID.String(): {"vm/platform"},
|
||||
"vm/" + avm.ID.String(): {"vm/avm"},
|
||||
"vm/" + EVMID.String(): {"vm/evm"},
|
||||
"vm/" + spdagvm.ID.String(): {"vm/spdag"},
|
||||
"vm/" + spchainvm.ID.String(): {"vm/spchain"},
|
||||
"vm/" + timestampvm.ID.String(): {"vm/timestamp"},
|
||||
"bc/" + ids.Empty.String(): {"P", "platform", "bc/P", "bc/platform"},
|
||||
}
|
||||
chainAliases := map[[32]byte][]string{
|
||||
ids.Empty.Key(): []string{"P", "platform"},
|
||||
ids.Empty.Key(): {"P", "platform"},
|
||||
}
|
||||
vmAliases := map[[32]byte][]string{
|
||||
platformvm.ID.Key(): []string{"platform"},
|
||||
avm.ID.Key(): []string{"avm"},
|
||||
EVMID.Key(): []string{"evm"},
|
||||
spdagvm.ID.Key(): []string{"spdag"},
|
||||
spchainvm.ID.Key(): []string{"spchain"},
|
||||
timestampvm.ID.Key(): []string{"timestamp"},
|
||||
secp256k1fx.ID.Key(): []string{"secp256k1fx"},
|
||||
nftfx.ID.Key(): []string{"nftfx"},
|
||||
propertyfx.ID.Key(): []string{"propertyfx"},
|
||||
platformvm.ID.Key(): {"platform"},
|
||||
avm.ID.Key(): {"avm"},
|
||||
EVMID.Key(): {"evm"},
|
||||
spdagvm.ID.Key(): {"spdag"},
|
||||
spchainvm.ID.Key(): {"spchain"},
|
||||
timestampvm.ID.Key(): {"timestamp"},
|
||||
secp256k1fx.ID.Key(): {"secp256k1fx"},
|
||||
nftfx.ID.Key(): {"nftfx"},
|
||||
propertyfx.ID.Key(): {"propertyfx"},
|
||||
}
|
||||
|
||||
genesisBytes, err := Genesis(networkID)
|
||||
|
|
|
@ -9,12 +9,12 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/utils/codec"
|
||||
"github.com/ava-labs/gecko/utils/formatting"
|
||||
"github.com/ava-labs/gecko/utils/json"
|
||||
"github.com/ava-labs/gecko/utils/units"
|
||||
"github.com/ava-labs/gecko/utils/wrappers"
|
||||
"github.com/ava-labs/gecko/vms/avm"
|
||||
"github.com/ava-labs/gecko/utils/codec"
|
||||
"github.com/ava-labs/gecko/vms/nftfx"
|
||||
"github.com/ava-labs/gecko/vms/platformvm"
|
||||
"github.com/ava-labs/gecko/vms/propertyfx"
|
||||
|
@ -156,7 +156,7 @@ func FromConfig(networkID uint32, config *Config) ([]byte, error) {
|
|||
|
||||
// Specify the chains that exist upon this network's creation
|
||||
platformvmArgs.Chains = []platformvm.APIChain{
|
||||
platformvm.APIChain{
|
||||
{
|
||||
GenesisData: avmReply.Bytes,
|
||||
SubnetID: platformvm.DefaultSubnetID,
|
||||
VMID: avm.ID,
|
||||
|
@ -167,25 +167,25 @@ func FromConfig(networkID uint32, config *Config) ([]byte, error) {
|
|||
},
|
||||
Name: "X-Chain",
|
||||
},
|
||||
platformvm.APIChain{
|
||||
{
|
||||
GenesisData: formatting.CB58{Bytes: config.EVMBytes},
|
||||
SubnetID: platformvm.DefaultSubnetID,
|
||||
VMID: EVMID,
|
||||
Name: "C-Chain",
|
||||
},
|
||||
platformvm.APIChain{
|
||||
{
|
||||
GenesisData: spdagvmReply.Bytes,
|
||||
SubnetID: platformvm.DefaultSubnetID,
|
||||
VMID: spdagvm.ID,
|
||||
Name: "Simple DAG Payments",
|
||||
},
|
||||
platformvm.APIChain{
|
||||
{
|
||||
GenesisData: spchainvmReply.Bytes,
|
||||
SubnetID: platformvm.DefaultSubnetID,
|
||||
VMID: spchainvm.ID,
|
||||
Name: "Simple Chain Payments",
|
||||
},
|
||||
platformvm.APIChain{
|
||||
{
|
||||
GenesisData: formatting.CB58{Bytes: []byte{}}, // There is no genesis data
|
||||
SubnetID: platformvm.DefaultSubnetID,
|
||||
VMID: timestampvm.ID,
|
||||
|
|
7
go.sum
7
go.sum
|
@ -64,6 +64,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
|
||||
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
|
||||
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
|
@ -122,6 +123,7 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l
|
|||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
|
||||
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
|
||||
|
@ -177,8 +179,10 @@ github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn
|
|||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo=
|
||||
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
|
||||
github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
|
||||
|
@ -230,6 +234,7 @@ github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8
|
|||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
|
||||
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
|
@ -345,6 +350,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
|
|||
gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
||||
|
@ -354,6 +360,7 @@ gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLv
|
|||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9 h1:ITeyKbRetrVzqR3U1eY+ywgp7IBspGd1U/bkwd1gWu4=
|
||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
|
||||
gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
|
|
|
@ -226,6 +226,7 @@ func init() {
|
|||
|
||||
// Enable/Disable APIs:
|
||||
fs.BoolVar(&Config.AdminAPIEnabled, "api-admin-enabled", true, "If true, this node exposes the Admin API")
|
||||
fs.BoolVar(&Config.InfoAPIEnabled, "api-info-enabled", true, "If true, this node exposes the Info 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.HealthAPIEnabled, "api-health-enabled", true, "If true, this node exposes the Health API")
|
||||
|
|
|
@ -51,6 +51,7 @@ type Config struct {
|
|||
|
||||
// Enable/Disable APIs
|
||||
AdminAPIEnabled bool
|
||||
InfoAPIEnabled bool
|
||||
KeystoreAPIEnabled bool
|
||||
MetricsAPIEnabled bool
|
||||
HealthAPIEnabled bool
|
||||
|
|
12
node/node.go
12
node/node.go
|
@ -18,6 +18,7 @@ import (
|
|||
"github.com/ava-labs/gecko/api"
|
||||
"github.com/ava-labs/gecko/api/admin"
|
||||
"github.com/ava-labs/gecko/api/health"
|
||||
"github.com/ava-labs/gecko/api/info"
|
||||
"github.com/ava-labs/gecko/api/ipcs"
|
||||
"github.com/ava-labs/gecko/api/keystore"
|
||||
"github.com/ava-labs/gecko/api/metrics"
|
||||
|
@ -461,11 +462,19 @@ func (n *Node) initMetricsAPI() {
|
|||
func (n *Node) initAdminAPI() {
|
||||
if n.Config.AdminAPIEnabled {
|
||||
n.Log.Info("initializing Admin API")
|
||||
service := admin.NewService(Version, n.ID, n.Config.NetworkID, n.Log, n.chainManager, n.Net, &n.APIServer)
|
||||
service := admin.NewService(n.Log, n.chainManager, n.Net, &n.APIServer)
|
||||
n.APIServer.AddRoute(service, &sync.RWMutex{}, "admin", "", n.HTTPLog)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Node) initInfoAPI() {
|
||||
if n.Config.InfoAPIEnabled {
|
||||
n.Log.Info("initializing Info API")
|
||||
service := info.NewService(n.Log, Version, n.ID, n.Config.NetworkID, n.chainManager, n.Net)
|
||||
n.APIServer.AddRoute(service, &sync.RWMutex{}, "info", "", n.HTTPLog)
|
||||
}
|
||||
}
|
||||
|
||||
// initHealthAPI initializes the Health API service
|
||||
// Assumes n.Log, n.ConsensusAPI, and n.ValidatorAPI already initialized
|
||||
func (n *Node) initHealthAPI() {
|
||||
|
@ -562,6 +571,7 @@ func (n *Node) Initialize(Config *Config, logger logging.Logger, logFactory logg
|
|||
n.initChainManager() // Set up the chain manager
|
||||
|
||||
n.initAdminAPI() // Start the Admin API
|
||||
n.initInfoAPI() // Start the Info API
|
||||
n.initHealthAPI() // Start the Health API
|
||||
n.initIPCAPI() // Start the IPC API
|
||||
|
||||
|
|
|
@ -125,14 +125,14 @@ func TestParametersAnotherInvalidBetaRogue(t *testing.T) {
|
|||
|
||||
func TestParametersInvalidConcurrentRepolls(t *testing.T) {
|
||||
tests := []Parameters{
|
||||
Parameters{
|
||||
{
|
||||
K: 1,
|
||||
Alpha: 1,
|
||||
BetaVirtuous: 1,
|
||||
BetaRogue: 1,
|
||||
ConcurrentRepolls: 2,
|
||||
},
|
||||
Parameters{
|
||||
{
|
||||
K: 1,
|
||||
Alpha: 1,
|
||||
BetaVirtuous: 1,
|
||||
|
|
|
@ -107,6 +107,9 @@ func (b *bootstrapper) fetch(vtxID ids.ID) error {
|
|||
|
||||
// Make sure we don't already have this vertex
|
||||
if _, err := b.State.GetVertex(vtxID); err == nil {
|
||||
if numPending := b.outstandingRequests.Len(); numPending == 0 && b.processedStartingAcceptedFrontier {
|
||||
return b.finish()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -124,15 +127,12 @@ func (b *bootstrapper) fetch(vtxID ids.ID) error {
|
|||
|
||||
// Process vertices
|
||||
func (b *bootstrapper) process(vtx avalanche.Vertex) error {
|
||||
toProcess := []avalanche.Vertex{vtx}
|
||||
for len(toProcess) > 0 {
|
||||
newLen := len(toProcess) - 1
|
||||
vtx := toProcess[newLen]
|
||||
toProcess = toProcess[:newLen]
|
||||
if _, ok := b.processedCache.Get(vtx.ID()); ok { // already processed this
|
||||
continue
|
||||
}
|
||||
|
||||
toProcess := newMaxVertexHeap()
|
||||
if _, ok := b.processedCache.Get(vtx.ID()); !ok { // only process if we haven't already
|
||||
toProcess.Push(vtx)
|
||||
}
|
||||
for toProcess.Len() > 0 {
|
||||
vtx := toProcess.Pop()
|
||||
switch vtx.Status() {
|
||||
case choices.Unknown:
|
||||
if err := b.fetch(vtx.ID()); err != nil {
|
||||
|
@ -168,7 +168,9 @@ func (b *bootstrapper) process(vtx avalanche.Vertex) error {
|
|||
}
|
||||
}
|
||||
for _, parent := range vtx.Parents() {
|
||||
toProcess = append(toProcess, parent)
|
||||
if _, ok := b.processedCache.Get(parent.ID()); !ok { // already processed this
|
||||
toProcess.Push(parent)
|
||||
}
|
||||
}
|
||||
b.processedCache.Put(vtx.ID(), nil)
|
||||
}
|
||||
|
|
|
@ -805,3 +805,113 @@ func TestBootstrapperIncompleteMultiPut(t *testing.T) {
|
|||
t.Fatal("should be accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapperFinalized(t *testing.T) {
|
||||
config, peerID, sender, state, vm := newConfig(t)
|
||||
|
||||
vtxID0 := ids.Empty.Prefix(0)
|
||||
vtxID1 := ids.Empty.Prefix(1)
|
||||
|
||||
vtxBytes0 := []byte{0}
|
||||
vtxBytes1 := []byte{1}
|
||||
|
||||
vtx0 := &Vtx{
|
||||
id: vtxID0,
|
||||
height: 0,
|
||||
status: choices.Unknown,
|
||||
bytes: vtxBytes0,
|
||||
}
|
||||
vtx1 := &Vtx{
|
||||
id: vtxID1,
|
||||
height: 1,
|
||||
parents: []avalanche.Vertex{vtx0},
|
||||
status: choices.Unknown,
|
||||
bytes: vtxBytes1,
|
||||
}
|
||||
|
||||
bs := bootstrapper{}
|
||||
bs.metrics.Initialize(config.Context.Log, fmt.Sprintf("gecko_%s", config.Context.ChainID), prometheus.NewRegistry())
|
||||
bs.Initialize(config)
|
||||
finished := new(bool)
|
||||
bs.onFinished = func() error { *finished = true; return nil }
|
||||
|
||||
acceptedIDs := ids.Set{}
|
||||
acceptedIDs.Add(vtxID0)
|
||||
acceptedIDs.Add(vtxID1)
|
||||
|
||||
parsedVtx0 := false
|
||||
parsedVtx1 := false
|
||||
state.getVertex = func(vtxID ids.ID) (avalanche.Vertex, error) {
|
||||
switch {
|
||||
case vtxID.Equals(vtxID0):
|
||||
if parsedVtx0 {
|
||||
return vtx0, nil
|
||||
}
|
||||
return nil, errUnknownVertex
|
||||
case vtxID.Equals(vtxID1):
|
||||
if parsedVtx1 {
|
||||
return vtx1, nil
|
||||
}
|
||||
return nil, errUnknownVertex
|
||||
default:
|
||||
t.Fatal(errUnknownVertex)
|
||||
panic(errUnknownVertex)
|
||||
}
|
||||
}
|
||||
state.parseVertex = func(vtxBytes []byte) (avalanche.Vertex, error) {
|
||||
switch {
|
||||
case bytes.Equal(vtxBytes, vtxBytes0):
|
||||
vtx0.status = choices.Processing
|
||||
parsedVtx0 = true
|
||||
return vtx0, nil
|
||||
case bytes.Equal(vtxBytes, vtxBytes1):
|
||||
vtx1.status = choices.Processing
|
||||
parsedVtx1 = true
|
||||
return vtx1, nil
|
||||
}
|
||||
t.Fatal(errUnknownVertex)
|
||||
return nil, errUnknownVertex
|
||||
}
|
||||
|
||||
requestIDs := map[[32]byte]uint32{}
|
||||
sender.GetAncestorsF = func(vdr ids.ShortID, reqID uint32, vtxID ids.ID) {
|
||||
if !vdr.Equals(peerID) {
|
||||
t.Fatalf("Should have requested block from %s, requested from %s", peerID, vdr)
|
||||
}
|
||||
requestIDs[vtxID.Key()] = reqID
|
||||
}
|
||||
|
||||
vm.CantBootstrapping = false
|
||||
|
||||
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request vtx0 and vtx1
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
reqID, ok := requestIDs[vtxID1.Key()]
|
||||
if !ok {
|
||||
t.Fatalf("should have requested vtx1")
|
||||
}
|
||||
|
||||
vm.CantBootstrapped = false
|
||||
|
||||
if err := bs.MultiPut(peerID, reqID, [][]byte{vtxBytes1, vtxBytes0}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
reqID, ok = requestIDs[vtxID0.Key()]
|
||||
if !ok {
|
||||
t.Fatalf("should have requested vtx0")
|
||||
}
|
||||
|
||||
if err := bs.GetAncestorsFailed(peerID, reqID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !*finished {
|
||||
t.Fatalf("Bootstrapping should have finished")
|
||||
} else if vtx0.Status() != choices.Accepted {
|
||||
t.Fatalf("Vertex should be accepted")
|
||||
} else if vtx1.Status() != choices.Accepted {
|
||||
t.Fatalf("Vertex should be accepted")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,6 +115,9 @@ func (b *bootstrapper) fetch(blkID ids.ID) error {
|
|||
|
||||
// Make sure we don't already have this block
|
||||
if _, err := b.VM.GetBlock(blkID); err == nil {
|
||||
if numPending := b.outstandingRequests.Len(); numPending == 0 && b.processedStartingAcceptedFrontier {
|
||||
return b.finish()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -622,3 +622,128 @@ func TestBootstrapperFilterAccepted(t *testing.T) {
|
|||
t.Fatalf("Blk shouldn't be accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBootstrapperFinalized(t *testing.T) {
|
||||
config, peerID, sender, vm := newConfig(t)
|
||||
|
||||
blkID0 := ids.Empty.Prefix(0)
|
||||
blkID1 := ids.Empty.Prefix(1)
|
||||
blkID2 := ids.Empty.Prefix(2)
|
||||
|
||||
blkBytes0 := []byte{0}
|
||||
blkBytes1 := []byte{1}
|
||||
blkBytes2 := []byte{2}
|
||||
|
||||
blk0 := &Blk{
|
||||
id: blkID0,
|
||||
height: 0,
|
||||
status: choices.Accepted,
|
||||
bytes: blkBytes0,
|
||||
}
|
||||
blk1 := &Blk{
|
||||
parent: blk0,
|
||||
id: blkID1,
|
||||
height: 1,
|
||||
status: choices.Unknown,
|
||||
bytes: blkBytes1,
|
||||
}
|
||||
blk2 := &Blk{
|
||||
parent: blk1,
|
||||
id: blkID2,
|
||||
height: 2,
|
||||
status: choices.Unknown,
|
||||
bytes: blkBytes2,
|
||||
}
|
||||
|
||||
bs := bootstrapper{}
|
||||
bs.metrics.Initialize(config.Context.Log, fmt.Sprintf("gecko_%s", config.Context.ChainID), prometheus.NewRegistry())
|
||||
bs.Initialize(config)
|
||||
finished := new(bool)
|
||||
bs.onFinished = func() error { *finished = true; return nil }
|
||||
|
||||
acceptedIDs := ids.Set{}
|
||||
acceptedIDs.Add(blkID1)
|
||||
acceptedIDs.Add(blkID2)
|
||||
|
||||
parsedBlk1 := false
|
||||
parsedBlk2 := false
|
||||
vm.GetBlockF = func(blkID ids.ID) (snowman.Block, error) {
|
||||
switch {
|
||||
case blkID.Equals(blkID0):
|
||||
return blk0, nil
|
||||
case blkID.Equals(blkID1):
|
||||
if parsedBlk1 {
|
||||
return blk1, nil
|
||||
}
|
||||
return nil, errUnknownBlock
|
||||
case blkID.Equals(blkID2):
|
||||
if parsedBlk2 {
|
||||
return blk2, nil
|
||||
}
|
||||
return nil, errUnknownBlock
|
||||
default:
|
||||
t.Fatal(errUnknownBlock)
|
||||
panic(errUnknownBlock)
|
||||
}
|
||||
}
|
||||
vm.ParseBlockF = func(blkBytes []byte) (snowman.Block, error) {
|
||||
switch {
|
||||
case bytes.Equal(blkBytes, blkBytes0):
|
||||
return blk0, nil
|
||||
case bytes.Equal(blkBytes, blkBytes1):
|
||||
blk1.status = choices.Processing
|
||||
parsedBlk1 = true
|
||||
return blk1, nil
|
||||
case bytes.Equal(blkBytes, blkBytes2):
|
||||
blk2.status = choices.Processing
|
||||
parsedBlk2 = true
|
||||
return blk2, nil
|
||||
}
|
||||
t.Fatal(errUnknownBlock)
|
||||
return nil, errUnknownBlock
|
||||
}
|
||||
|
||||
requestIDs := map[[32]byte]uint32{}
|
||||
sender.GetAncestorsF = func(vdr ids.ShortID, reqID uint32, vtxID ids.ID) {
|
||||
if !vdr.Equals(peerID) {
|
||||
t.Fatalf("Should have requested block from %s, requested from %s", peerID, vdr)
|
||||
}
|
||||
requestIDs[vtxID.Key()] = reqID
|
||||
}
|
||||
|
||||
vm.CantBootstrapping = false
|
||||
|
||||
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request blk0 and blk1
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
reqID, ok := requestIDs[blkID2.Key()]
|
||||
if !ok {
|
||||
t.Fatalf("should have requested blk2")
|
||||
}
|
||||
|
||||
vm.CantBootstrapped = false
|
||||
|
||||
if err := bs.MultiPut(peerID, reqID, [][]byte{blkBytes2, blkBytes1}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
reqID, ok = requestIDs[blkID1.Key()]
|
||||
if !ok {
|
||||
t.Fatalf("should have requested blk1")
|
||||
}
|
||||
|
||||
if err := bs.GetAncestorsFailed(peerID, reqID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !*finished {
|
||||
t.Fatalf("Bootstrapping should have finished")
|
||||
} else if blk0.Status() != choices.Accepted {
|
||||
t.Fatalf("Block should be accepted")
|
||||
} else if blk1.Status() != choices.Accepted {
|
||||
t.Fatalf("Block should be accepted")
|
||||
} else if blk2.Status() != choices.Accepted {
|
||||
t.Fatalf("Block should be accepted")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ type Block struct {
|
|||
func (b *Block) Initialize(bytes []byte, vm *SnowmanVM) {
|
||||
b.VM = vm
|
||||
b.Metadata.Initialize(bytes)
|
||||
status := b.VM.State.GetStatus(vm.DB, b.ID())
|
||||
b.SetStatus(status)
|
||||
b.SetStatus(choices.Unknown) // don't set status until it is queried
|
||||
}
|
||||
|
||||
// ParentID returns [b]'s parent's ID
|
||||
|
@ -55,7 +54,6 @@ func (b *Block) Parent() snowman.Block {
|
|||
// Recall that b.vm.DB.Commit() must be called to persist to the DB
|
||||
func (b *Block) Accept() error {
|
||||
b.SetStatus(choices.Accepted) // Change state of this block
|
||||
|
||||
blkID := b.ID()
|
||||
|
||||
// Persist data
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/ava-labs/gecko/snow/choices"
|
||||
"github.com/ava-labs/gecko/snow/consensus/snowman"
|
||||
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
|
||||
"github.com/ava-labs/gecko/database/memdb"
|
||||
"github.com/ava-labs/gecko/database/versiondb"
|
||||
)
|
||||
|
||||
func TestBlock(t *testing.T) {
|
||||
parentID := ids.NewID([32]byte{1, 2, 3, 4, 5})
|
||||
db := versiondb.New(memdb.New())
|
||||
state, err := NewSnowmanState(func([]byte) (snowman.Block, error) { return nil, nil })
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
b := NewBlock(parentID)
|
||||
|
||||
b.Initialize([]byte{1, 2, 3}, &SnowmanVM{
|
||||
DB: db,
|
||||
State: state,
|
||||
})
|
||||
|
||||
// should be unknown until someone queries for it
|
||||
if status := b.Metadata.status; status != choices.Unknown {
|
||||
t.Fatalf("status should be unknown but is %s", status)
|
||||
}
|
||||
|
||||
// querying should change status to processing
|
||||
if status := b.Status(); status != choices.Processing {
|
||||
t.Fatalf("status should be processing but is %s", status)
|
||||
}
|
||||
|
||||
b.Accept()
|
||||
if status := b.Status(); status != choices.Accepted {
|
||||
t.Fatalf("status should be accepted but is %s", status)
|
||||
}
|
||||
|
||||
b.Reject()
|
||||
if status := b.Status(); status != choices.Rejected {
|
||||
t.Fatalf("status should be rejected but is %s", status)
|
||||
}
|
||||
}
|
|
@ -128,19 +128,10 @@ func (s *state) Get(db database.Database, typeID uint64, key ids.ID) (interface{
|
|||
// The unique ID of this key/typeID pair
|
||||
uID := s.uniqueID(key, typeID)
|
||||
|
||||
// See if exists in database
|
||||
exists, err := db.Has(uID.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, database.ErrNotFound
|
||||
}
|
||||
|
||||
// Get the value from the database
|
||||
valueBytes, err := db.Get(uID.Bytes())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("problem getting value from database: %w", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Unmarshal the value from bytes and return it
|
||||
|
|
|
@ -128,7 +128,7 @@ func (tx *addDefaultSubnetDelegatorTx) SemanticVerify(db database.Database) (*ve
|
|||
// The account if this block's proposal is committed and the validator is
|
||||
// added to the pending validator set. (Increase the account's nonce;
|
||||
// decrease its balance.)
|
||||
newAccount, err := account.Remove(0, tx.Nonce) // Remove also removes the fee
|
||||
newAccount, err := account.Remove(tx.Wght, tx.Nonce) // Remove also removes the fee
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, permError{err}
|
||||
}
|
||||
|
|
|
@ -386,4 +386,52 @@ func TestAddDefaultSubnetDelegatorTxSemanticVerify(t *testing.T) {
|
|||
t.Fatal("should have failed verification because payer account has no $AVA to pay fee")
|
||||
}
|
||||
txFee = txFeeSaved // Reset tx fee
|
||||
|
||||
// Case 8: fail verification for spending more funds than it has
|
||||
tx, err = vm.newAddDefaultSubnetDelegatorTx(
|
||||
defaultNonce+1,
|
||||
defaultBalance*2, // weight
|
||||
uint64(defaultValidateStartTime.Unix()), // start time
|
||||
uint64(defaultValidateEndTime.Unix()), // end time
|
||||
defaultKey.PublicKey().Address(), // node ID
|
||||
defaultKey.PublicKey().Address(), // destination
|
||||
testNetworkID, // network ID
|
||||
defaultKey, // tx fee payer
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, _, _, _, err = tx.SemanticVerify(vm.DB)
|
||||
if err == nil {
|
||||
t.Fatal("should have failed verification because payer account spent twice the account's balance")
|
||||
}
|
||||
|
||||
// Case 9: Confirm balance is correct
|
||||
tx, err = vm.newAddDefaultSubnetDelegatorTx(
|
||||
defaultNonce+1,
|
||||
defaultStakeAmount, // weight
|
||||
uint64(defaultValidateStartTime.Unix()), // start time
|
||||
uint64(defaultValidateEndTime.Unix()), // end time
|
||||
defaultKey.PublicKey().Address(), // node ID
|
||||
defaultKey.PublicKey().Address(), // destination
|
||||
testNetworkID, // network ID
|
||||
defaultKey, // tx fee payer
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
onCommitDB, _, _, _, err := tx.SemanticVerify(vm.DB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
account, err := tx.vm.getAccount(onCommitDB, defaultKey.PublicKey().Address())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
balance := account.Balance
|
||||
|
||||
if balance != defaultBalance-(defaultStakeAmount+txFee) {
|
||||
t.Fatalf("balance was not updated correctly after subnet delegator tx")
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue