Merge pull request #58 from ava-labs/bootstrap-improvements-merged

Bootstrap improvements merged
This commit is contained in:
Stephen Buttolph 2020-06-07 01:20:52 -04:00 committed by GitHub
commit 9ffe0fe47a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1150 additions and 156 deletions

View File

@ -10,6 +10,7 @@ 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"
@ -46,38 +47,45 @@ func NewService(nodeID ids.ShortID, networkID uint32, log logging.Logger, chainM
return &common.HTTPHandler{Handler: newServer}
}
// GetNodeIDArgs are the arguments for calling GetNodeID
type GetNodeIDArgs struct{}
// 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(r *http.Request, args *GetNodeIDArgs, reply *GetNodeIDReply) error {
func (service *Admin) GetNodeID(_ *http.Request, _ *struct{}, reply *GetNodeIDReply) error {
service.log.Debug("Admin: GetNodeID called")
reply.NodeID = service.nodeID
return nil
}
// GetNetworkIDArgs are the arguments for calling GetNetworkID
type GetNetworkIDArgs struct{}
// 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(r *http.Request, args *GetNetworkIDArgs, reply *GetNetworkIDReply) error {
func (service *Admin) GetNetworkID(_ *http.Request, _ *struct{}, reply *GetNetworkIDReply) error {
service.log.Debug("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.Debug("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"`
@ -89,7 +97,7 @@ type GetBlockchainIDReply struct {
}
// GetBlockchainID returns the blockchain ID that resolves the alias that was supplied
func (service *Admin) GetBlockchainID(r *http.Request, args *GetBlockchainIDArgs, reply *GetBlockchainIDReply) error {
func (service *Admin) GetBlockchainID(_ *http.Request, args *GetBlockchainIDArgs, reply *GetBlockchainIDReply) error {
service.log.Debug("Admin: GetBlockchainID called")
bID, err := service.chainManager.Lookup(args.Alias)
@ -97,16 +105,13 @@ func (service *Admin) GetBlockchainID(r *http.Request, args *GetBlockchainIDArgs
return err
}
// PeersArgs are the arguments for calling Peers
type PeersArgs struct{}
// 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(r *http.Request, args *PeersArgs, reply *PeersReply) error {
func (service *Admin) Peers(_ *http.Request, _ *struct{}, reply *PeersReply) error {
service.log.Debug("Admin: Peers called")
reply.Peers = service.networking.Peers()
return nil
@ -123,22 +128,19 @@ type StartCPUProfilerReply struct {
}
// StartCPUProfiler starts a cpu profile writing to the specified file
func (service *Admin) StartCPUProfiler(r *http.Request, args *StartCPUProfilerArgs, reply *StartCPUProfilerReply) error {
func (service *Admin) StartCPUProfiler(_ *http.Request, args *StartCPUProfilerArgs, reply *StartCPUProfilerReply) error {
service.log.Debug("Admin: StartCPUProfiler called with %s", args.Filename)
reply.Success = true
return service.performance.StartCPUProfiler(args.Filename)
}
// StopCPUProfilerArgs are the arguments for calling StopCPUProfiler
type StopCPUProfilerArgs struct{}
// StopCPUProfilerReply are the results from calling StopCPUProfiler
type StopCPUProfilerReply struct {
Success bool `json:"success"`
}
// StopCPUProfiler stops the cpu profile
func (service *Admin) StopCPUProfiler(r *http.Request, args *StopCPUProfilerArgs, reply *StopCPUProfilerReply) error {
func (service *Admin) StopCPUProfiler(_ *http.Request, _ *struct{}, reply *StopCPUProfilerReply) error {
service.log.Debug("Admin: StopCPUProfiler called")
reply.Success = true
return service.performance.StopCPUProfiler()
@ -155,7 +157,7 @@ type MemoryProfileReply struct {
}
// MemoryProfile runs a memory profile writing to the specified file
func (service *Admin) MemoryProfile(r *http.Request, args *MemoryProfileArgs, reply *MemoryProfileReply) error {
func (service *Admin) MemoryProfile(_ *http.Request, args *MemoryProfileArgs, reply *MemoryProfileReply) error {
service.log.Debug("Admin: MemoryProfile called with %s", args.Filename)
reply.Success = true
return service.performance.MemoryProfile(args.Filename)
@ -172,7 +174,7 @@ type LockProfileReply struct {
}
// LockProfile runs a mutex profile writing to the specified file
func (service *Admin) LockProfile(r *http.Request, args *LockProfileArgs, reply *LockProfileReply) error {
func (service *Admin) LockProfile(_ *http.Request, args *LockProfileArgs, reply *LockProfileReply) error {
service.log.Debug("Admin: LockProfile called with %s", args.Filename)
reply.Success = true
return service.performance.LockProfile(args.Filename)
@ -190,7 +192,7 @@ type AliasReply struct {
}
// Alias attempts to alias an HTTP endpoint to a new name
func (service *Admin) Alias(r *http.Request, args *AliasArgs, reply *AliasReply) error {
func (service *Admin) Alias(_ *http.Request, args *AliasArgs, reply *AliasReply) error {
service.log.Debug("Admin: Alias called with URL: %s, Alias: %s", args.Endpoint, args.Alias)
reply.Success = true
return service.httpServer.AddAliasesWithReadLock(args.Endpoint, args.Alias)
@ -233,7 +235,7 @@ type StacktraceReply struct {
}
// Stacktrace returns the current global stacktrace
func (service *Admin) Stacktrace(_ *http.Request, _ *StacktraceArgs, reply *StacktraceReply) error {
func (service *Admin) Stacktrace(_ *http.Request, _ *struct{}, reply *StacktraceReply) error {
reply.Stacktrace = logging.Stacktrace{Global: true}.String()
return nil
}

View File

@ -429,7 +429,13 @@ func (m *manager) createAvalancheChain(
// Asynchronously passes messages from the network to the consensus engine
handler := &router.Handler{}
handler.Initialize(&engine, msgChan, defaultChannelSize)
handler.Initialize(
&engine,
msgChan,
defaultChannelSize,
fmt.Sprintf("%s_handler", consensusParams.Namespace),
consensusParams.Metrics,
)
// Allows messages to be routed to the new chain
m.chainRouter.AddChain(handler)
@ -515,7 +521,13 @@ func (m *manager) createSnowmanChain(
// Asynchronously passes messages from the network to the consensus engine
handler := &router.Handler{}
handler.Initialize(&engine, msgChan, defaultChannelSize)
handler.Initialize(
&engine,
msgChan,
defaultChannelSize,
fmt.Sprintf("%s_handler", consensusParams.Namespace),
consensusParams.Metrics,
)
// Allow incoming messages to be routed to the new chain
m.chainRouter.AddChain(handler)

View File

@ -62,6 +62,9 @@ func (b *UniqueBag) Difference(diff *UniqueBag) {
// GetSet ...
func (b *UniqueBag) GetSet(id ID) BitSet { return (*b)[*id.ID] }
// RemoveSet ...
func (b *UniqueBag) RemoveSet(id ID) { delete(*b, id.Key()) }
// List ...
func (b *UniqueBag) List() []ID {
idList := []ID(nil)

View File

@ -41,7 +41,7 @@ func main() {
defer Config.DB.Close()
if Config.StakingIP.IsZero() {
log.Warn("NAT traversal has failed. If this node becomes a staker, it may lose its reward due to being unreachable.")
log.Warn("NAT traversal has failed. It will be able to connect to less nodes.")
}
// Track if sybil control is enforced
@ -62,7 +62,7 @@ func main() {
// Track if assertions should be executed
if Config.LoggingConfig.Assertions {
log.Warn("assertions are enabled. This may slow down execution")
log.Debug("assertions are enabled. This may slow down execution")
}
mapper := nat.NewDefaultMapper(log, Config.Nat, nat.TCP, "gecko")
@ -83,5 +83,5 @@ func main() {
log.Debug("dispatching node handlers")
err = node.Dispatch()
log.Debug("dispatch returned with: %s", err)
log.Debug("node dispatching returned with %s", err)
}

View File

@ -77,6 +77,10 @@ type Vertex interface {
// Returns the vertices this vertex depends on
Parents() []Vertex
// Returns the height of this vertex. A vertex's height is defined by one
// greater than the maximum height of the parents.
Height() uint64
// Returns a series of state transitions to be performed on acceptance
Txs() []snowstorm.Tx

View File

@ -37,14 +37,14 @@ func (m *metrics) Initialize(log logging.Logger, namespace string, registerer pr
Namespace: namespace,
Name: "vtx_accepted",
Help: "Latency of accepting from the time the vertex was issued in milliseconds",
Buckets: timer.Buckets,
Buckets: timer.MillisecondsBuckets,
})
m.latRejected = prometheus.NewHistogram(
prometheus.HistogramOpts{
Namespace: namespace,
Name: "vtx_rejected",
Help: "Latency of rejecting from the time the vertex was issued in milliseconds",
Buckets: timer.Buckets,
Buckets: timer.MillisecondsBuckets,
})
if err := registerer.Register(m.numProcessing); err != nil {

View File

@ -16,7 +16,7 @@ type Vtx struct {
id ids.ID
txs []snowstorm.Tx
height int
height uint64
status choices.Status
bytes []byte
@ -25,6 +25,7 @@ type Vtx struct {
func (v *Vtx) ID() ids.ID { return v.id }
func (v *Vtx) ParentIDs() []ids.ID { return nil }
func (v *Vtx) Parents() []Vertex { return v.dependencies }
func (v *Vtx) Height() uint64 { return v.height }
func (v *Vtx) Txs() []snowstorm.Tx { return v.txs }
func (v *Vtx) Status() choices.Status { return v.status }
func (v *Vtx) Live() {}

View File

@ -37,14 +37,14 @@ func (m *metrics) Initialize(log logging.Logger, namespace string, registerer pr
Namespace: namespace,
Name: "accepted",
Help: "Latency of accepting from the time the block was issued in milliseconds",
Buckets: timer.Buckets,
Buckets: timer.MillisecondsBuckets,
})
m.latRejected = prometheus.NewHistogram(
prometheus.HistogramOpts{
Namespace: namespace,
Name: "rejected",
Help: "Latency of rejecting from the time the block was issued in milliseconds",
Buckets: timer.Buckets,
Buckets: timer.MillisecondsBuckets,
})
if err := registerer.Register(m.numProcessing); err != nil {

View File

@ -37,14 +37,14 @@ func (m *metrics) Initialize(log logging.Logger, namespace string, registerer pr
Namespace: namespace,
Name: "tx_accepted",
Help: "Latency of accepting from the time the transaction was issued in milliseconds",
Buckets: timer.Buckets,
Buckets: timer.MillisecondsBuckets,
})
m.latRejected = prometheus.NewHistogram(
prometheus.HistogramOpts{
Namespace: namespace,
Name: "tx_rejected",
Help: "Latency of rejecting from the time the transaction was issued in milliseconds",
Buckets: timer.Buckets,
Buckets: timer.MillisecondsBuckets,
})
if err := registerer.Register(m.numProcessing); err != nil {

View File

@ -236,6 +236,11 @@ func (b *bootstrapper) GetAncestorsFailed(vdr ids.ShortID, requestID uint32) err
// ForceAccepted ...
func (b *bootstrapper) ForceAccepted(acceptedContainerIDs ids.Set) error {
if err := b.VM.Bootstrapping(); err != nil {
return fmt.Errorf("failed to notify VM that bootstrapping has started: %w",
err)
}
for _, vtxID := range acceptedContainerIDs.List() {
if vtx, err := b.State.GetVertex(vtxID); err == nil {
if err := b.process(vtx); err != nil {
@ -267,6 +272,11 @@ func (b *bootstrapper) finish() error {
return err
}
if err := b.VM.Bootstrapped(); err != nil {
return fmt.Errorf("failed to notify VM that bootstrapping has finished: %w",
err)
}
// Start consensus
if err := b.onFinished(); err != nil {
return err

View File

@ -58,7 +58,13 @@ func newConfig(t *testing.T) (BootstrapConfig, ids.ShortID, *common.SenderTest,
peerID := peer.ID()
peers.Add(peer)
handler.Initialize(engine, make(chan common.Message), 1)
handler.Initialize(
engine,
make(chan common.Message),
1,
"",
prometheus.NewRegistry(),
)
timeouts.Initialize(0)
router.Initialize(ctx.Log, timeouts, time.Hour, time.Second)
@ -83,7 +89,7 @@ func newConfig(t *testing.T) (BootstrapConfig, ids.ShortID, *common.SenderTest,
// Three vertices in the accepted frontier. None have parents. No need to fetch anything
func TestBootstrapperSingleFrontier(t *testing.T) {
config, _, _, state, _ := newConfig(t)
config, _, _, state, vm := newConfig(t)
vtxID0 := ids.Empty.Prefix(0)
vtxID1 := ids.Empty.Prefix(1)
@ -148,6 +154,9 @@ func TestBootstrapperSingleFrontier(t *testing.T) {
return nil, errParsedUnknownVertex
}
vm.CantBootstrapping = false
vm.CantBootstrapped = false
bs.ForceAccepted(acceptedIDs)
if !*finished {
@ -170,7 +179,7 @@ func TestBootstrapperSingleFrontier(t *testing.T) {
// Requests again and gets an unexpected vertex.
// Requests again and gets the expected vertex.
func TestBootstrapperByzantineResponses(t *testing.T) {
config, peerID, sender, state, _ := newConfig(t)
config, peerID, sender, state, vm := newConfig(t)
vtxID0 := ids.Empty.Prefix(0)
vtxID1 := ids.Empty.Prefix(1)
@ -251,6 +260,7 @@ func TestBootstrapperByzantineResponses(t *testing.T) {
t.Fatal(errParsedUnknownVertex)
return nil, errParsedUnknownVertex
}
vm.CantBootstrapping = false
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request vtx0
t.Fatal(err)
@ -298,6 +308,9 @@ func TestBootstrapperByzantineResponses(t *testing.T) {
panic(errUnknownVertex)
}
}
vm.CantBootstrapped = false
if err := bs.MultiPut(peerID, *requestID, [][]byte{vtxBytes0}); err != nil { // send expected vertex
t.Fatal(err)
}
@ -422,6 +435,8 @@ func TestBootstrapperTxDependencies(t *testing.T) {
*reqIDPtr = reqID
}
vm.CantBootstrapping = false
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request vtx0
t.Fatal(err)
}
@ -437,6 +452,9 @@ func TestBootstrapperTxDependencies(t *testing.T) {
t.Fatal(errParsedUnknownVertex)
return nil, errParsedUnknownVertex
}
vm.CantBootstrapped = false
if err := bs.MultiPut(peerID, *reqIDPtr, [][]byte{vtxBytes0}); err != nil {
t.Fatal(err)
}
@ -459,9 +477,9 @@ func TestBootstrapperTxDependencies(t *testing.T) {
}
}
// Unfilfilled tx dependency
// Unfulfilled tx dependency
func TestBootstrapperMissingTxDependency(t *testing.T) {
config, peerID, sender, state, _ := newConfig(t)
config, peerID, sender, state, vm := newConfig(t)
utxos := []ids.ID{GenerateID(), GenerateID()}
@ -554,10 +572,14 @@ func TestBootstrapperMissingTxDependency(t *testing.T) {
*reqIDPtr = reqID
}
vm.CantBootstrapping = false
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request vtx1
t.Fatal(err)
}
vm.CantBootstrapped = false
if err := bs.MultiPut(peerID, *reqIDPtr, [][]byte{vtxBytes0}); err != nil {
t.Fatal(err)
}
@ -670,7 +692,7 @@ func TestBootstrapperFilterAccepted(t *testing.T) {
// MultiPut only contains 1 of the two needed vertices; have to issue another GetAncestors
func TestBootstrapperIncompleteMultiPut(t *testing.T) {
config, peerID, sender, state, _ := newConfig(t)
config, peerID, sender, state, vm := newConfig(t)
vtxID0 := ids.Empty.Prefix(0)
vtxID1 := ids.Empty.Prefix(1)
@ -753,6 +775,8 @@ func TestBootstrapperIncompleteMultiPut(t *testing.T) {
requested = vtxID
}
vm.CantBootstrapping = false
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request vtx1
t.Fatal(err)
} else if !requested.Equals(vtxID1) {
@ -767,6 +791,8 @@ func TestBootstrapperIncompleteMultiPut(t *testing.T) {
t.Fatal("should hae requested vtx0")
}
vm.CantBootstrapped = false
if err := bs.MultiPut(peerID, *reqIDPtr, [][]byte{vtxBytes0}); err != nil { // Provide vtx0; can finish now
t.Fatal(err)
} else if !bs.finished {
@ -778,5 +804,4 @@ func TestBootstrapperIncompleteMultiPut(t *testing.T) {
} else if vtx2.Status() != choices.Accepted {
t.Fatal("should be accepted")
}
}

View File

@ -27,7 +27,7 @@ type Vtx struct {
id ids.ID
txs []snowstorm.Tx
height int
height uint64
status choices.Status
bytes []byte
@ -36,6 +36,7 @@ type Vtx struct {
func (v *Vtx) ID() ids.ID { return v.id }
func (v *Vtx) DependencyIDs() []ids.ID { return nil }
func (v *Vtx) Parents() []avalanche.Vertex { return v.parents }
func (v *Vtx) Height() uint64 { return v.height }
func (v *Vtx) Txs() []snowstorm.Tx { return v.txs }
func (v *Vtx) Status() choices.Status { return v.status }
func (v *Vtx) Accept() error { v.status = choices.Accepted; return nil }

View File

@ -121,6 +121,12 @@ func (vtx *uniqueVertex) Parents() []avalanche.Vertex {
return vtx.v.parents
}
func (vtx *uniqueVertex) Height() uint64 {
vtx.refresh()
return vtx.v.vtx.height
}
func (vtx *uniqueVertex) Txs() []snowstorm.Tx {
vtx.refresh()

View File

@ -2167,6 +2167,9 @@ func TestEngineBootstrappingIntoConsensus(t *testing.T) {
vm.Default(true)
vm.CantBootstrapping = false
vm.CantBootstrapped = false
utxos := []ids.ID{GenerateID(), GenerateID()}
txID0 := GenerateID()

View File

@ -0,0 +1,117 @@
package avalanche
import (
"container/heap"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow/consensus/avalanche"
)
// A vertexItem is a Vertex managed by the priority queue.
type vertexItem struct {
vertex avalanche.Vertex
index int // The index of the item in the heap.
}
// A priorityQueue implements heap.Interface and holds vertexItems.
type priorityQueue []*vertexItem
func (pq priorityQueue) Len() int { return len(pq) }
// Returns true if the vertex at index i has greater height than the vertex at
// index j.
func (pq priorityQueue) Less(i, j int) bool {
statusI := pq[i].vertex.Status()
statusJ := pq[j].vertex.Status()
// Put unknown vertices at the front of the heap to ensure once we have made
// it below a certain height in DAG traversal we do not need to reset
if !statusI.Fetched() {
return true
}
if !statusJ.Fetched() {
return false
}
return pq[i].vertex.Height() > pq[j].vertex.Height()
}
func (pq priorityQueue) Swap(i, j int) {
pq[i], pq[j] = pq[j], pq[i]
pq[i].index = i
pq[j].index = j
}
// Push adds an item to this priority queue. x must have type *vertexItem
func (pq *priorityQueue) Push(x interface{}) {
n := len(*pq)
item := x.(*vertexItem)
item.index = n
*pq = append(*pq, item)
}
// Pop returns the last item in this priorityQueue
func (pq *priorityQueue) Pop() interface{} {
old := *pq
n := len(old)
item := old[n-1]
old[n-1] = nil
item.index = -1
*pq = old[0 : n-1]
return item
}
// vertexHeap defines the functionality of a heap of vertices
// with unique VertexIDs ordered by height
type vertexHeap interface {
Clear()
Push(avalanche.Vertex)
Pop() avalanche.Vertex // Requires that there be at least one element
Contains(avalanche.Vertex) bool
Len() int
}
type maxHeightVertexHeap struct {
heap *priorityQueue
elementIDs ids.Set
}
func newMaxVertexHeap() *maxHeightVertexHeap {
return &maxHeightVertexHeap{
heap: &priorityQueue{},
elementIDs: ids.Set{},
}
}
func (vh *maxHeightVertexHeap) Clear() {
vh.heap = &priorityQueue{}
vh.elementIDs.Clear()
}
// Push adds an element to this heap. Returns true if the element was added.
// Returns false if it was already in the heap.
func (vh *maxHeightVertexHeap) Push(vtx avalanche.Vertex) bool {
vtxID := vtx.ID()
if vh.elementIDs.Contains(vtxID) {
return false
}
vh.elementIDs.Add(vtxID)
item := &vertexItem{
vertex: vtx,
}
heap.Push(vh.heap, item)
return true
}
// If there are any vertices in this heap with status Unknown, removes one such
// vertex and returns it. Otherwise, removes and returns the vertex in this heap
// with the greatest height.
func (vh *maxHeightVertexHeap) Pop() avalanche.Vertex {
vtx := heap.Pop(vh.heap).(*vertexItem).vertex
vh.elementIDs.Remove(vtx.ID())
return vtx
}
func (vh *maxHeightVertexHeap) Len() int { return vh.heap.Len() }
func (vh *maxHeightVertexHeap) Contains(vtxID ids.ID) bool { return vh.elementIDs.Contains(vtxID) }

View File

@ -0,0 +1,130 @@
package avalanche
import (
"testing"
"github.com/ava-labs/gecko/snow/choices"
"github.com/ava-labs/gecko/snow/consensus/avalanche"
)
// This example inserts several ints into an IntHeap, checks the minimum,
// and removes them in order of priority.
func TestUniqueVertexHeapReturnsOrdered(t *testing.T) {
h := newMaxVertexHeap()
vtx0 := &Vtx{
id: GenerateID(),
height: 0,
status: choices.Processing,
}
vtx1 := &Vtx{
id: GenerateID(),
height: 1,
status: choices.Processing,
}
vtx2 := &Vtx{
id: GenerateID(),
height: 1,
status: choices.Processing,
}
vtx3 := &Vtx{
id: GenerateID(),
height: 3,
status: choices.Processing,
}
vtx4 := &Vtx{
id: GenerateID(),
status: choices.Unknown,
}
vts := []avalanche.Vertex{vtx0, vtx1, vtx2, vtx3, vtx4}
for _, vtx := range vts {
h.Push(vtx)
}
vtxZ := h.Pop()
if !vtxZ.ID().Equals(vtx4.ID()) {
t.Fatalf("Heap did not pop unknown element first")
}
vtxA := h.Pop()
if vtxA.Height() != 3 {
t.Fatalf("First height from heap was incorrect")
} else if !vtxA.ID().Equals(vtx3.ID()) {
t.Fatalf("Incorrect ID on vertex popped from heap")
}
vtxB := h.Pop()
if vtxB.Height() != 1 {
t.Fatalf("First height from heap was incorrect")
} else if !vtxB.ID().Equals(vtx1.ID()) && !vtxB.ID().Equals(vtx2.ID()) {
t.Fatalf("Incorrect ID on vertex popped from heap")
}
vtxC := h.Pop()
if vtxC.Height() != 1 {
t.Fatalf("First height from heap was incorrect")
} else if !vtxC.ID().Equals(vtx1.ID()) && !vtxC.ID().Equals(vtx2.ID()) {
t.Fatalf("Incorrect ID on vertex popped from heap")
}
if vtxB.ID().Equals(vtxC.ID()) {
t.Fatalf("Heap returned same element more than once")
}
vtxD := h.Pop()
if vtxD.Height() != 0 {
t.Fatalf("Last height returned was incorrect")
} else if !vtxD.ID().Equals(vtx0.ID()) {
t.Fatalf("Last item from heap had incorrect ID")
}
if h.Len() != 0 {
t.Fatalf("Heap was not empty after popping all of its elements")
}
}
func TestUniqueVertexHeapRemainsUnique(t *testing.T) {
h := newMaxVertexHeap()
vtx0 := &Vtx{
height: 0,
id: GenerateID(),
status: choices.Processing,
}
vtx1 := &Vtx{
height: 1,
id: GenerateID(),
status: choices.Processing,
}
sharedID := GenerateID()
vtx2 := &Vtx{
height: 1,
id: sharedID,
status: choices.Processing,
}
vtx3 := &Vtx{
height: 2,
id: sharedID,
status: choices.Processing,
}
pushed1 := h.Push(vtx0)
pushed2 := h.Push(vtx1)
pushed3 := h.Push(vtx2)
pushed4 := h.Push(vtx3)
if h.Len() != 3 {
t.Fatalf("Unique Vertex Heap has incorrect length: %d", h.Len())
} else if !(pushed1 && pushed2 && pushed3) {
t.Fatalf("Failed to push a new unique element")
} else if pushed4 {
t.Fatalf("Pushed non-unique element to the unique vertex heap")
}
}

View File

@ -5,7 +5,6 @@ package avalanche
import (
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow/consensus/avalanche"
"github.com/ava-labs/gecko/snow/consensus/snowstorm"
)
@ -60,47 +59,56 @@ func (v *voter) Update() {
}
if v.t.Consensus.Quiesce() {
v.t.Config.Context.Log.Verbo("Avalanche engine can quiesce")
v.t.Config.Context.Log.Debug("Avalanche engine can quiesce")
return
}
v.t.Config.Context.Log.Verbo("Avalanche engine can't quiesce")
v.t.Config.Context.Log.Debug("Avalanche engine can't quiesce")
v.t.errs.Add(v.t.repoll())
}
func (v *voter) bubbleVotes(votes ids.UniqueBag) ids.UniqueBag {
bubbledVotes := ids.UniqueBag{}
vertexHeap := newMaxVertexHeap()
for _, vote := range votes.List() {
set := votes.GetSet(vote)
vtx, err := v.t.Config.State.GetVertex(vote)
if err != nil {
continue
}
vts := []avalanche.Vertex{vtx}
for len(vts) > 0 {
vtx := vts[0]
vts = vts[1:]
vertexHeap.Push(vtx)
}
status := vtx.Status()
if !status.Fetched() {
v.t.Config.Context.Log.Verbo("Dropping %d vote(s) for %s because the vertex is unknown", set.Len(), vtx.ID())
continue
}
for vertexHeap.Len() > 0 {
vtx := vertexHeap.Pop()
vtxID := vtx.ID()
set := votes.GetSet(vtxID)
status := vtx.Status()
if status.Decided() {
v.t.Config.Context.Log.Verbo("Dropping %d vote(s) for %s because the vertex is decided", set.Len(), vtx.ID())
continue
}
if !status.Fetched() {
v.t.Config.Context.Log.Verbo("Dropping %d vote(s) for %s because the vertex is unknown", set.Len(), vtxID)
bubbledVotes.RemoveSet(vtx.ID())
continue
}
if v.t.Consensus.VertexIssued(vtx) {
v.t.Config.Context.Log.Verbo("Applying %d vote(s) for %s", set.Len(), vtx.ID())
bubbledVotes.UnionSet(vtx.ID(), set)
} else {
v.t.Config.Context.Log.Verbo("Bubbling %d vote(s) for %s because the vertex isn't issued", set.Len(), vtx.ID())
vts = append(vts, vtx.Parents()...)
if status.Decided() {
v.t.Config.Context.Log.Verbo("Dropping %d vote(s) for %s because the vertex is decided", set.Len(), vtxID)
bubbledVotes.RemoveSet(vtx.ID())
continue
}
if v.t.Consensus.VertexIssued(vtx) {
v.t.Config.Context.Log.Verbo("Applying %d vote(s) for %s", set.Len(), vtx.ID())
bubbledVotes.UnionSet(vtx.ID(), set)
} else {
v.t.Config.Context.Log.Verbo("Bubbling %d vote(s) for %s because the vertex isn't issued", set.Len(), vtx.ID())
bubbledVotes.RemoveSet(vtx.ID()) // Remove votes for this vertex because it hasn't been issued
for _, parentVtx := range vtx.Parents() {
bubbledVotes.UnionSet(parentVtx.ID(), set)
vertexHeap.Push(parentVtx)
}
}
}
return bubbledVotes
}

View File

@ -19,19 +19,22 @@ var (
type VMTest struct {
T *testing.T
CantInitialize, CantShutdown, CantCreateHandlers, CantCreateStaticHandlers bool
CantInitialize, CantBootstrapping, CantBootstrapped, CantShutdown, CantCreateHandlers, CantCreateStaticHandlers bool
InitializeF func(*snow.Context, database.Database, []byte, chan<- Message, []*Fx) error
ShutdownF func() error
CreateHandlersF func() map[string]*HTTPHandler
CreateStaticHandlersF func() map[string]*HTTPHandler
InitializeF func(*snow.Context, database.Database, []byte, chan<- Message, []*Fx) error
BootstrappingF, BootstrappedF, ShutdownF func() error
CreateHandlersF func() map[string]*HTTPHandler
CreateStaticHandlersF func() map[string]*HTTPHandler
}
// Default ...
func (vm *VMTest) Default(cant bool) {
vm.CantInitialize = cant
vm.CantBootstrapping = cant
vm.CantBootstrapped = cant
vm.CantShutdown = cant
vm.CantCreateHandlers = cant
vm.CantCreateStaticHandlers = cant
}
// Initialize ...
@ -45,6 +48,32 @@ func (vm *VMTest) Initialize(ctx *snow.Context, db database.Database, initState
return errInitialize
}
// Bootstrapping ...
func (vm *VMTest) Bootstrapping() error {
if vm.BootstrappingF != nil {
return vm.BootstrappingF()
} else if vm.CantBootstrapping {
if vm.T != nil {
vm.T.Fatalf("Unexpectedly called Bootstrapping")
}
return errors.New("Unexpectedly called Bootstrapping")
}
return nil
}
// Bootstrapped ...
func (vm *VMTest) Bootstrapped() error {
if vm.BootstrappedF != nil {
return vm.BootstrappedF()
} else if vm.CantBootstrapped {
if vm.T != nil {
vm.T.Fatalf("Unexpectedly called Bootstrapped")
}
return errors.New("Unexpectedly called Bootstrapped")
}
return nil
}
// Shutdown ...
func (vm *VMTest) Shutdown() error {
if vm.ShutdownF != nil {

View File

@ -12,8 +12,7 @@ import (
type VM interface {
// Initialize this VM.
// [ctx]: Metadata about this VM.
// [ctx.networkID]: The ID of the network this VM's chain is running
// on.
// [ctx.networkID]: The ID of the network this VM's chain is running on.
// [ctx.chainID]: The unique ID of the chain this VM is running on.
// [ctx.Log]: Used to log messages
// [ctx.NodeID]: The unique staker ID of this node.
@ -37,6 +36,12 @@ type VM interface {
fxs []*Fx,
) error
// Bootstrapping is called when the node is starting to bootstrap this chain.
Bootstrapping() error
// Bootstrapped is called when the node is done bootstrapping this chain.
Bootstrapped() error
// Shutdown is called when the node is shutting down.
Shutdown() error

View File

@ -84,6 +84,11 @@ func (b *bootstrapper) FilterAccepted(containerIDs ids.Set) ids.Set {
// ForceAccepted ...
func (b *bootstrapper) ForceAccepted(acceptedContainerIDs ids.Set) error {
if err := b.VM.Bootstrapping(); err != nil {
return fmt.Errorf("failed to notify VM that bootstrapping has started: %w",
err)
}
for _, blkID := range acceptedContainerIDs.List() {
if blk, err := b.VM.GetBlock(blkID); err == nil {
if err := b.process(blk); err != nil {
@ -219,11 +224,17 @@ func (b *bootstrapper) finish() error {
if b.finished {
return nil
}
b.BootstrapConfig.Context.Log.Info("bootstrapping finished fetching blocks. executing state transitions...")
if err := b.executeAll(b.Blocked, b.numBlocked); err != nil {
return err
}
if err := b.VM.Bootstrapped(); err != nil {
return fmt.Errorf("failed to notify VM that bootstrapping has finished: %w",
err)
}
// Start consensus
if err := b.onFinished(); err != nil {
return err

View File

@ -52,7 +52,13 @@ func newConfig(t *testing.T) (BootstrapConfig, ids.ShortID, *common.SenderTest,
peerID := peer.ID()
peers.Add(peer)
handler.Initialize(engine, make(chan common.Message), 1)
handler.Initialize(
engine,
make(chan common.Message),
1,
"",
prometheus.NewRegistry(),
)
timeouts.Initialize(0)
router.Initialize(ctx.Log, timeouts, time.Hour, time.Second)
@ -127,6 +133,9 @@ func TestBootstrapperSingleFrontier(t *testing.T) {
return nil, errUnknownBlock
}
vm.CantBootstrapping = false
vm.CantBootstrapped = false
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should finish
t.Fatal(err)
} else if !*finished {
@ -225,6 +234,7 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) {
}
*requestID = reqID
}
vm.CantBootstrapping = false
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request blk1
t.Fatal(err)
@ -249,6 +259,8 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) {
t.Fatal("should have sent new request")
}
vm.CantBootstrapped = false
if err := bs.MultiPut(peerID, *requestID, [][]byte{blkBytes1}); err != nil { // respond with right block
t.Fatal(err)
} else if !*finished {
@ -370,6 +382,8 @@ func TestBootstrapperPartialFetch(t *testing.T) {
requested = vtxID
}
vm.CantBootstrapping = false
if err := bs.ForceAccepted(acceptedIDs); err != nil { // should request blk2
t.Fatal(err)
}
@ -380,6 +394,8 @@ func TestBootstrapperPartialFetch(t *testing.T) {
t.Fatal("should have requested blk1")
}
vm.CantBootstrapped = false
if err := bs.MultiPut(peerID, *requestID, [][]byte{blkBytes1}); err != nil { // respond with blk1
t.Fatal(err)
} else if !requested.Equals(blkID1) {
@ -438,6 +454,7 @@ func TestBootstrapperMultiPut(t *testing.T) {
status: choices.Processing,
bytes: blkBytes3,
}
vm.CantBootstrapping = false
bs := bootstrapper{}
bs.metrics.Initialize(config.Context.Log, fmt.Sprintf("gecko_%s", config.Context.ChainID), prometheus.NewRegistry())
@ -509,6 +526,8 @@ func TestBootstrapperMultiPut(t *testing.T) {
t.Fatal(err)
}
vm.CantBootstrapped = false
if err := bs.MultiPut(peerID, *requestID, [][]byte{blkBytes2, blkBytes1}); err != nil { // respond with blk2 and blk1
t.Fatal(err)
} else if !requested.Equals(blkID2) {
@ -586,6 +605,7 @@ func TestBootstrapperFilterAccepted(t *testing.T) {
t.Fatal(errUnknownBlock)
return nil, errUnknownBlock
}
vm.CantBootstrapping = false
accepted := bs.FilterAccepted(blkIDs)

View File

@ -45,7 +45,7 @@ func (v *voter) Update() {
// must be bubbled to the nearest valid block
results = v.bubbleVotes(results)
v.t.Config.Context.Log.Verbo("Finishing poll [%d] with:\n%s", v.requestID, &results)
v.t.Config.Context.Log.Debug("Finishing poll [%d] with:\n%s", v.requestID, &results)
if err := v.t.Consensus.RecordPoll(results); err != nil {
v.t.errs.Add(err)
return
@ -54,11 +54,11 @@ func (v *voter) Update() {
v.t.Config.VM.SetPreference(v.t.Consensus.Preference())
if v.t.Consensus.Finalized() {
v.t.Config.Context.Log.Verbo("Snowman engine can quiesce")
v.t.Config.Context.Log.Debug("Snowman engine can quiesce")
return
}
v.t.Config.Context.Log.Verbo("Snowman engine can't quiesce")
v.t.Config.Context.Log.Debug("Snowman engine can't quiesce")
v.t.repoll()
}

View File

@ -4,14 +4,19 @@
package router
import (
"time"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow"
"github.com/ava-labs/gecko/snow/engine/common"
"github.com/prometheus/client_golang/prometheus"
)
// Handler passes incoming messages from the network to the consensus engine
// (Actually, it receives the incoming messages from a ChainRouter, but same difference)
type Handler struct {
metrics
msgs chan message
closed chan struct{}
engine common.Engine
@ -21,7 +26,14 @@ type Handler struct {
}
// Initialize this consensus handler
func (h *Handler) Initialize(engine common.Engine, msgChan <-chan common.Message, bufferSize int) {
func (h *Handler) Initialize(
engine common.Engine,
msgChan <-chan common.Message,
bufferSize int,
namespace string,
metrics prometheus.Registerer,
) {
h.metrics.Initialize(namespace, metrics)
h.msgs = make(chan message, bufferSize)
h.closed = make(chan struct{})
h.engine = engine
@ -47,6 +59,7 @@ func (h *Handler) Dispatch() {
if !ok {
return
}
h.metrics.pending.Dec()
if closing {
log.Debug("dropping message due to closing:\n%s", msg)
continue
@ -73,6 +86,7 @@ func (h *Handler) Dispatch() {
// Returns true iff this consensus handler (and its associated engine) should shutdown
// (due to receipt of a shutdown message)
func (h *Handler) dispatchMsg(msg message) bool {
startTime := time.Now()
ctx := h.engine.Context()
ctx.Lock.Lock()
@ -86,42 +100,61 @@ func (h *Handler) dispatchMsg(msg message) bool {
switch msg.messageType {
case getAcceptedFrontierMsg:
err = h.engine.GetAcceptedFrontier(msg.validatorID, msg.requestID)
h.getAcceptedFrontier.Observe(float64(time.Now().Sub(startTime)))
case acceptedFrontierMsg:
err = h.engine.AcceptedFrontier(msg.validatorID, msg.requestID, msg.containerIDs)
h.acceptedFrontier.Observe(float64(time.Now().Sub(startTime)))
case getAcceptedFrontierFailedMsg:
err = h.engine.GetAcceptedFrontierFailed(msg.validatorID, msg.requestID)
h.getAcceptedFrontierFailed.Observe(float64(time.Now().Sub(startTime)))
case getAcceptedMsg:
err = h.engine.GetAccepted(msg.validatorID, msg.requestID, msg.containerIDs)
h.getAccepted.Observe(float64(time.Now().Sub(startTime)))
case acceptedMsg:
err = h.engine.Accepted(msg.validatorID, msg.requestID, msg.containerIDs)
h.accepted.Observe(float64(time.Now().Sub(startTime)))
case getAcceptedFailedMsg:
err = h.engine.GetAcceptedFailed(msg.validatorID, msg.requestID)
case getMsg:
err = h.engine.Get(msg.validatorID, msg.requestID, msg.containerID)
h.getAcceptedFailed.Observe(float64(time.Now().Sub(startTime)))
case getAncestorsMsg:
err = h.engine.GetAncestors(msg.validatorID, msg.requestID, msg.containerID)
case getFailedMsg:
err = h.engine.GetFailed(msg.validatorID, msg.requestID)
h.getAncestors.Observe(float64(time.Now().Sub(startTime)))
case getAncestorsFailedMsg:
err = h.engine.GetAncestorsFailed(msg.validatorID, msg.requestID)
case putMsg:
err = h.engine.Put(msg.validatorID, msg.requestID, msg.containerID, msg.container)
h.getAncestorsFailed.Observe(float64(time.Now().Sub(startTime)))
case multiPutMsg:
err = h.engine.MultiPut(msg.validatorID, msg.requestID, msg.containers)
h.multiPut.Observe(float64(time.Now().Sub(startTime)))
case getMsg:
err = h.engine.Get(msg.validatorID, msg.requestID, msg.containerID)
h.get.Observe(float64(time.Now().Sub(startTime)))
case getFailedMsg:
err = h.engine.GetFailed(msg.validatorID, msg.requestID)
h.getFailed.Observe(float64(time.Now().Sub(startTime)))
case putMsg:
err = h.engine.Put(msg.validatorID, msg.requestID, msg.containerID, msg.container)
h.put.Observe(float64(time.Now().Sub(startTime)))
case pushQueryMsg:
err = h.engine.PushQuery(msg.validatorID, msg.requestID, msg.containerID, msg.container)
h.pushQuery.Observe(float64(time.Now().Sub(startTime)))
case pullQueryMsg:
err = h.engine.PullQuery(msg.validatorID, msg.requestID, msg.containerID)
h.pullQuery.Observe(float64(time.Now().Sub(startTime)))
case queryFailedMsg:
err = h.engine.QueryFailed(msg.validatorID, msg.requestID)
h.queryFailed.Observe(float64(time.Now().Sub(startTime)))
case chitsMsg:
err = h.engine.Chits(msg.validatorID, msg.requestID, msg.containerIDs)
h.chits.Observe(float64(time.Now().Sub(startTime)))
case notifyMsg:
err = h.engine.Notify(msg.notification)
h.notify.Observe(float64(time.Now().Sub(startTime)))
case gossipMsg:
err = h.engine.Gossip()
h.gossip.Observe(float64(time.Now().Sub(startTime)))
case shutdownMsg:
err = h.engine.Shutdown()
h.shutdown.Observe(float64(time.Now().Sub(startTime)))
done = true
}
@ -134,6 +167,7 @@ func (h *Handler) dispatchMsg(msg message) bool {
// GetAcceptedFrontier passes a GetAcceptedFrontier message received from the
// network to the consensus engine.
func (h *Handler) GetAcceptedFrontier(validatorID ids.ShortID, requestID uint32) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: getAcceptedFrontierMsg,
validatorID: validatorID,
@ -144,6 +178,7 @@ func (h *Handler) GetAcceptedFrontier(validatorID ids.ShortID, requestID uint32)
// AcceptedFrontier passes a AcceptedFrontier message received from the network
// to the consensus engine.
func (h *Handler) AcceptedFrontier(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: acceptedFrontierMsg,
validatorID: validatorID,
@ -155,6 +190,7 @@ func (h *Handler) AcceptedFrontier(validatorID ids.ShortID, requestID uint32, co
// GetAcceptedFrontierFailed passes a GetAcceptedFrontierFailed message received
// from the network to the consensus engine.
func (h *Handler) GetAcceptedFrontierFailed(validatorID ids.ShortID, requestID uint32) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: getAcceptedFrontierFailedMsg,
validatorID: validatorID,
@ -165,6 +201,7 @@ func (h *Handler) GetAcceptedFrontierFailed(validatorID ids.ShortID, requestID u
// GetAccepted passes a GetAccepted message received from the
// network to the consensus engine.
func (h *Handler) GetAccepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: getAcceptedMsg,
validatorID: validatorID,
@ -176,6 +213,7 @@ func (h *Handler) GetAccepted(validatorID ids.ShortID, requestID uint32, contain
// Accepted passes a Accepted message received from the network to the consensus
// engine.
func (h *Handler) Accepted(validatorID ids.ShortID, requestID uint32, containerIDs ids.Set) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: acceptedMsg,
validatorID: validatorID,
@ -187,6 +225,7 @@ func (h *Handler) Accepted(validatorID ids.ShortID, requestID uint32, containerI
// GetAcceptedFailed passes a GetAcceptedFailed message received from the
// network to the consensus engine.
func (h *Handler) GetAcceptedFailed(validatorID ids.ShortID, requestID uint32) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: getAcceptedFailedMsg,
validatorID: validatorID,
@ -196,6 +235,7 @@ func (h *Handler) GetAcceptedFailed(validatorID ids.ShortID, requestID uint32) {
// Get passes a Get message received from the network to the consensus engine.
func (h *Handler) Get(validatorID ids.ShortID, requestID uint32, containerID ids.ID) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: getMsg,
validatorID: validatorID,
@ -216,6 +256,7 @@ func (h *Handler) GetAncestors(validatorID ids.ShortID, requestID uint32, contai
// Put passes a Put message received from the network to the consensus engine.
func (h *Handler) Put(validatorID ids.ShortID, requestID uint32, containerID ids.ID, container []byte) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: putMsg,
validatorID: validatorID,
@ -237,6 +278,7 @@ func (h *Handler) MultiPut(validatorID ids.ShortID, requestID uint32, containers
// GetFailed passes a GetFailed message to the consensus engine.
func (h *Handler) GetFailed(validatorID ids.ShortID, requestID uint32) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: getFailedMsg,
validatorID: validatorID,
@ -255,6 +297,7 @@ func (h *Handler) GetAncestorsFailed(validatorID ids.ShortID, requestID uint32)
// PushQuery passes a PushQuery message received from the network to the consensus engine.
func (h *Handler) PushQuery(validatorID ids.ShortID, requestID uint32, blockID ids.ID, block []byte) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: pushQueryMsg,
validatorID: validatorID,
@ -266,6 +309,7 @@ func (h *Handler) PushQuery(validatorID ids.ShortID, requestID uint32, blockID i
// PullQuery passes a PullQuery message received from the network to the consensus engine.
func (h *Handler) PullQuery(validatorID ids.ShortID, requestID uint32, blockID ids.ID) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: pullQueryMsg,
validatorID: validatorID,
@ -276,6 +320,7 @@ func (h *Handler) PullQuery(validatorID ids.ShortID, requestID uint32, blockID i
// Chits passes a Chits message received from the network to the consensus engine.
func (h *Handler) Chits(validatorID ids.ShortID, requestID uint32, votes ids.Set) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: chitsMsg,
validatorID: validatorID,
@ -286,6 +331,7 @@ func (h *Handler) Chits(validatorID ids.ShortID, requestID uint32, votes ids.Set
// QueryFailed passes a QueryFailed message received from the network to the consensus engine.
func (h *Handler) QueryFailed(validatorID ids.ShortID, requestID uint32) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: queryFailedMsg,
validatorID: validatorID,
@ -294,13 +340,20 @@ func (h *Handler) QueryFailed(validatorID ids.ShortID, requestID uint32) {
}
// Gossip passes a gossip request to the consensus engine
func (h *Handler) Gossip() { h.msgs <- message{messageType: gossipMsg} }
func (h *Handler) Gossip() {
h.metrics.pending.Inc()
h.msgs <- message{messageType: gossipMsg}
}
// Shutdown shuts down the dispatcher
func (h *Handler) Shutdown() { h.msgs <- message{messageType: shutdownMsg} }
func (h *Handler) Shutdown() {
h.metrics.pending.Inc()
h.msgs <- message{messageType: shutdownMsg}
}
// Notify ...
func (h *Handler) Notify(msg common.Message) {
h.metrics.pending.Inc()
h.msgs <- message{
messageType: notifyMsg,
notification: msg,

View File

@ -0,0 +1,79 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package router
import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/ava-labs/gecko/utils/timer"
"github.com/ava-labs/gecko/utils/wrappers"
)
func initHistogram(namespace, name string, registerer prometheus.Registerer, errs *wrappers.Errs) prometheus.Histogram {
histogram := prometheus.NewHistogram(
prometheus.HistogramOpts{
Namespace: namespace,
Name: name,
Help: "Time spent processing this request in nanoseconds",
Buckets: timer.NanosecondsBuckets,
})
if err := registerer.Register(histogram); err != nil {
errs.Add(fmt.Errorf("failed to register %s statistics due to %s", name, err))
}
return histogram
}
type metrics struct {
pending prometheus.Gauge
getAcceptedFrontier, acceptedFrontier, getAcceptedFrontierFailed,
getAccepted, accepted, getAcceptedFailed,
getAncestors, multiPut, getAncestorsFailed,
get, put, getFailed,
pushQuery, pullQuery, chits, queryFailed,
notify,
gossip,
shutdown prometheus.Histogram
}
// Initialize implements the Engine interface
func (m *metrics) Initialize(namespace string, registerer prometheus.Registerer) error {
errs := wrappers.Errs{}
m.pending = prometheus.NewGauge(
prometheus.GaugeOpts{
Namespace: namespace,
Name: "pending",
Help: "Number of pending events",
})
if err := registerer.Register(m.pending); err != nil {
errs.Add(fmt.Errorf("failed to register pending statistics due to %s", err))
}
m.getAcceptedFrontier = initHistogram(namespace, "get_accepted_frontier", registerer, &errs)
m.acceptedFrontier = initHistogram(namespace, "accepted_frontier", registerer, &errs)
m.getAcceptedFrontierFailed = initHistogram(namespace, "get_accepted_frontier_failed", registerer, &errs)
m.getAccepted = initHistogram(namespace, "get_accepted", registerer, &errs)
m.accepted = initHistogram(namespace, "accepted", registerer, &errs)
m.getAcceptedFailed = initHistogram(namespace, "get_accepted_failed", registerer, &errs)
m.getAncestors = initHistogram(namespace, "get_ancestors", registerer, &errs)
m.multiPut = initHistogram(namespace, "multi_put", registerer, &errs)
m.getAncestorsFailed = initHistogram(namespace, "get_ancestors_failed", registerer, &errs)
m.get = initHistogram(namespace, "get", registerer, &errs)
m.put = initHistogram(namespace, "put", registerer, &errs)
m.getFailed = initHistogram(namespace, "get_failed", registerer, &errs)
m.pushQuery = initHistogram(namespace, "push_query", registerer, &errs)
m.pullQuery = initHistogram(namespace, "pull_query", registerer, &errs)
m.chits = initHistogram(namespace, "chits", registerer, &errs)
m.queryFailed = initHistogram(namespace, "query_failed", registerer, &errs)
m.notify = initHistogram(namespace, "notify", registerer, &errs)
m.gossip = initHistogram(namespace, "gossip", registerer, &errs)
m.shutdown = initHistogram(namespace, "shutdown", registerer, &errs)
return errs.Err
}

View File

@ -15,6 +15,7 @@ import (
"github.com/ava-labs/gecko/snow/networking/router"
"github.com/ava-labs/gecko/snow/networking/timeout"
"github.com/ava-labs/gecko/utils/logging"
"github.com/prometheus/client_golang/prometheus"
)
func TestSenderContext(t *testing.T) {
@ -58,7 +59,13 @@ func TestTimeout(t *testing.T) {
}
handler := router.Handler{}
handler.Initialize(&engine, nil, 1)
handler.Initialize(
&engine,
nil,
1,
"",
prometheus.NewRegistry(),
)
go handler.Dispatch()
chainRouter.AddChain(&handler)

View File

@ -3,9 +3,13 @@
package timer
import (
"time"
)
// Useful latency buckets
var (
Buckets = []float64{
MillisecondsBuckets = []float64{
10, // 10 ms is ~ instant
100, // 100 ms
250, // 250 ms
@ -18,4 +22,15 @@ var (
10000, // 10 seconds
// anything larger than 10 seconds will be bucketed together
}
NanosecondsBuckets = []float64{
float64(100 * time.Nanosecond),
float64(time.Microsecond),
float64(10 * time.Microsecond),
float64(100 * time.Microsecond),
float64(time.Millisecond),
float64(10 * time.Millisecond),
float64(100 * time.Millisecond),
float64(time.Second),
// anything larger than a second will be bucketed together
}
)

View File

@ -840,6 +840,16 @@ func TestBaseTxSemanticVerifyUnauthorizedFx(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
cr := codecRegistry{
index: 1,
typeToFxIndex: vm.typeToFxIndex,
@ -1386,6 +1396,16 @@ func TestBaseTxSemanticVerifyPendingUnauthorizedFx(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
cr := codecRegistry{
index: 1,
typeToFxIndex: vm.typeToFxIndex,
@ -1538,6 +1558,16 @@ func TestBaseTxSemanticVerifyPendingInvalidSignature(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
cr := codecRegistry{
index: 1,
typeToFxIndex: vm.typeToFxIndex,

View File

@ -151,6 +151,16 @@ func TestIssueExportTx(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
key := keys[0]
tx := &Tx{UnsignedTx: &ExportTx{
@ -297,6 +307,16 @@ func TestClearForceAcceptedExportTx(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
key := keys[0]
tx := &Tx{UnsignedTx: &ExportTx{

View File

@ -19,6 +19,12 @@ type Fx interface {
// return an error if the VM is incompatible.
Initialize(vm interface{}) error
// Notify this Fx that the VM is in bootstrapping
Bootstrapping() error
// Notify this Fx that the VM is bootstrapped
Bootstrapped() error
// VerifyTransfer verifies that the specified transaction can spend the
// provided utxo with no restrictions on the destination. If the transaction
// can't spend the output based on the input and credential, a non-nil error

View File

@ -4,10 +4,12 @@
package avm
type testFx struct {
initialize, verifyTransfer, verifyOperation error
initialize, bootstrapping, bootstrapped, verifyTransfer, verifyOperation error
}
func (fx *testFx) Initialize(_ interface{}) error { return fx.initialize }
func (fx *testFx) Bootstrapping() error { return fx.bootstrapping }
func (fx *testFx) Bootstrapped() error { return fx.bootstrapped }
func (fx *testFx) VerifyTransfer(_, _, _, _ interface{}) error { return fx.verifyTransfer }
func (fx *testFx) VerifyOperation(_, _, _ interface{}, _ []interface{}) error {
return fx.verifyOperation

View File

@ -140,6 +140,16 @@ func TestIssueImportTx(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
key := keys[0]
utxoID := ava.UTXOID{
@ -288,6 +298,16 @@ func TestForceAcceptImportTx(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
key := keys[0]
genesisTx := GetFirstTxFromGenesisTest(genesisBytes, t)

View File

@ -45,6 +45,7 @@ var (
errGenesisAssetMustHaveState = errors.New("genesis asset must have non-empty state")
errInvalidAddress = errors.New("invalid address")
errWrongBlockchainID = errors.New("wrong blockchain ID")
errBootstrapping = errors.New("chain is currently bootstrapping")
)
// VM implements the avalanche.DAGVM interface
@ -67,6 +68,9 @@ type VM struct {
// State management
state *prefixedState
// Set to true once this VM is marked as `Bootstrapped` by the engine
bootstrapped bool
// Transaction issuing
timer *timer.Timer
batchTimeout time.Duration
@ -197,6 +201,29 @@ func (vm *VM) Initialize(
return vm.db.Commit()
}
// Bootstrapping is called by the consensus engine when it starts bootstrapping
// this chain
func (vm *VM) Bootstrapping() error {
for _, fx := range vm.fxs {
if err := fx.Fx.Bootstrapping(); err != nil {
return err
}
}
return nil
}
// Bootstrapped is called by the consensus engine when it is done bootstrapping
// this chain
func (vm *VM) Bootstrapped() error {
for _, fx := range vm.fxs {
if err := fx.Fx.Bootstrapped(); err != nil {
return err
}
}
vm.bootstrapped = true
return nil
}
// Shutdown implements the avalanche.DAGVM interface
func (vm *VM) Shutdown() error {
if vm.timer == nil {
@ -272,6 +299,9 @@ func (vm *VM) GetTx(txID ids.ID) (snowstorm.Tx, error) {
// either accepted or rejected with the appropriate status. This function will
// go out of scope when the transaction is removed from memory.
func (vm *VM) IssueTx(b []byte, onDecide func(choices.Status)) (ids.ID, error) {
if !vm.bootstrapped {
return ids.ID{}, errBootstrapping
}
tx, err := vm.parseTx(b)
if err != nil {
return ids.ID{}, err

View File

@ -178,6 +178,14 @@ func GenesisVM(t *testing.T) ([]byte, chan common.Message, *VM) {
}
vm.batchTimeout = 0
if err := vm.Bootstrapping(); err != nil {
t.Fatal(err)
}
if err := vm.Bootstrapped(); err != nil {
t.Fatal(err)
}
return genesisBytes, issuer, vm
}
@ -678,6 +686,16 @@ func TestIssueNFT(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
createAssetTx := &Tx{UnsignedTx: &CreateAssetTx{
BaseTx: BaseTx{
NetID: networkID,
@ -841,6 +859,16 @@ func TestIssueProperty(t *testing.T) {
}
vm.batchTimeout = 0
err = vm.Bootstrapping()
if err != nil {
t.Fatal(err)
}
err = vm.Bootstrapped()
if err != nil {
t.Fatal(err)
}
createAssetTx := &Tx{UnsignedTx: &CreateAssetTx{
BaseTx: BaseTx{
NetID: networkID,

View File

@ -81,6 +81,12 @@ func (svm *SnowmanVM) GetBlock(ID ids.ID) (snowman.Block, error) {
return nil, errBadData // Should never happen
}
// Bootstrapping marks this VM as bootstrapping
func (svm *SnowmanVM) Bootstrapping() error { return nil }
// Bootstrapped marks this VM as bootstrapped
func (svm *SnowmanVM) Bootstrapped() error { return nil }
// Shutdown this vm
func (svm *SnowmanVM) Shutdown() error {
if svm.DB == nil {

View File

@ -399,6 +399,12 @@ func (vm *VM) createChain(tx *CreateChainTx) {
vm.chainManager.CreateChain(chainParams)
}
// Bootstrapping marks this VM as bootstrapping
func (vm *VM) Bootstrapping() error { return nil }
// Bootstrapped marks this VM as bootstrapped
func (vm *VM) Bootstrapped() error { return nil }
// Shutdown this blockchain
func (vm *VM) Shutdown() error {
if vm.timer == nil {

View File

@ -1598,7 +1598,13 @@ func TestBootstrapPartiallyAccepted(t *testing.T) {
// Asynchronously passes messages from the network to the consensus engine
handler := &router.Handler{}
handler.Initialize(&engine, msgChan, 1000)
handler.Initialize(
&engine,
msgChan,
1000,
"",
prometheus.NewRegistry(),
)
// Allow incoming messages to be routed to the new chain
chainRouter.AddChain(handler)

View File

@ -129,6 +129,18 @@ func (vm *VMClient) startMessengerServer(opts []grpc.ServerOption) *grpc.Server
return server
}
// Bootstrapping ...
func (vm *VMClient) Bootstrapping() error {
_, err := vm.client.Bootstrapping(context.Background(), &vmproto.BootstrappingRequest{})
return err
}
// Bootstrapped ...
func (vm *VMClient) Bootstrapped() error {
_, err := vm.client.Bootstrapped(context.Background(), &vmproto.BootstrappedRequest{})
return err
}
// Shutdown ...
func (vm *VMClient) Shutdown() error {
vm.lock.Lock()

View File

@ -84,8 +84,18 @@ func (vm *VMServer) Initialize(_ context.Context, req *vmproto.InitializeRequest
return &vmproto.InitializeResponse{}, nil
}
// Bootstrapping ...
func (vm *VMServer) Bootstrapping(context.Context, *vmproto.BootstrappingRequest) (*vmproto.BootstrappingResponse, error) {
return &vmproto.BootstrappingResponse{}, vm.vm.Bootstrapping()
}
// Bootstrapped ...
func (vm *VMServer) Bootstrapped(context.Context, *vmproto.BootstrappedRequest) (*vmproto.BootstrappedResponse, error) {
return &vmproto.BootstrappedResponse{}, vm.vm.Bootstrapped()
}
// Shutdown ...
func (vm *VMServer) Shutdown(_ context.Context, _ *vmproto.ShutdownRequest) (*vmproto.ShutdownResponse, error) {
func (vm *VMServer) Shutdown(context.Context, *vmproto.ShutdownRequest) (*vmproto.ShutdownResponse, error) {
vm.lock.Lock()
defer vm.lock.Unlock()

View File

@ -110,6 +110,130 @@ func (m *InitializeResponse) XXX_DiscardUnknown() {
var xxx_messageInfo_InitializeResponse proto.InternalMessageInfo
type BootstrappingRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BootstrappingRequest) Reset() { *m = BootstrappingRequest{} }
func (m *BootstrappingRequest) String() string { return proto.CompactTextString(m) }
func (*BootstrappingRequest) ProtoMessage() {}
func (*BootstrappingRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{2}
}
func (m *BootstrappingRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BootstrappingRequest.Unmarshal(m, b)
}
func (m *BootstrappingRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BootstrappingRequest.Marshal(b, m, deterministic)
}
func (m *BootstrappingRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_BootstrappingRequest.Merge(m, src)
}
func (m *BootstrappingRequest) XXX_Size() int {
return xxx_messageInfo_BootstrappingRequest.Size(m)
}
func (m *BootstrappingRequest) XXX_DiscardUnknown() {
xxx_messageInfo_BootstrappingRequest.DiscardUnknown(m)
}
var xxx_messageInfo_BootstrappingRequest proto.InternalMessageInfo
type BootstrappingResponse struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BootstrappingResponse) Reset() { *m = BootstrappingResponse{} }
func (m *BootstrappingResponse) String() string { return proto.CompactTextString(m) }
func (*BootstrappingResponse) ProtoMessage() {}
func (*BootstrappingResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{3}
}
func (m *BootstrappingResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BootstrappingResponse.Unmarshal(m, b)
}
func (m *BootstrappingResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BootstrappingResponse.Marshal(b, m, deterministic)
}
func (m *BootstrappingResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_BootstrappingResponse.Merge(m, src)
}
func (m *BootstrappingResponse) XXX_Size() int {
return xxx_messageInfo_BootstrappingResponse.Size(m)
}
func (m *BootstrappingResponse) XXX_DiscardUnknown() {
xxx_messageInfo_BootstrappingResponse.DiscardUnknown(m)
}
var xxx_messageInfo_BootstrappingResponse proto.InternalMessageInfo
type BootstrappedRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BootstrappedRequest) Reset() { *m = BootstrappedRequest{} }
func (m *BootstrappedRequest) String() string { return proto.CompactTextString(m) }
func (*BootstrappedRequest) ProtoMessage() {}
func (*BootstrappedRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{4}
}
func (m *BootstrappedRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BootstrappedRequest.Unmarshal(m, b)
}
func (m *BootstrappedRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BootstrappedRequest.Marshal(b, m, deterministic)
}
func (m *BootstrappedRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_BootstrappedRequest.Merge(m, src)
}
func (m *BootstrappedRequest) XXX_Size() int {
return xxx_messageInfo_BootstrappedRequest.Size(m)
}
func (m *BootstrappedRequest) XXX_DiscardUnknown() {
xxx_messageInfo_BootstrappedRequest.DiscardUnknown(m)
}
var xxx_messageInfo_BootstrappedRequest proto.InternalMessageInfo
type BootstrappedResponse struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *BootstrappedResponse) Reset() { *m = BootstrappedResponse{} }
func (m *BootstrappedResponse) String() string { return proto.CompactTextString(m) }
func (*BootstrappedResponse) ProtoMessage() {}
func (*BootstrappedResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{5}
}
func (m *BootstrappedResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_BootstrappedResponse.Unmarshal(m, b)
}
func (m *BootstrappedResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_BootstrappedResponse.Marshal(b, m, deterministic)
}
func (m *BootstrappedResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_BootstrappedResponse.Merge(m, src)
}
func (m *BootstrappedResponse) XXX_Size() int {
return xxx_messageInfo_BootstrappedResponse.Size(m)
}
func (m *BootstrappedResponse) XXX_DiscardUnknown() {
xxx_messageInfo_BootstrappedResponse.DiscardUnknown(m)
}
var xxx_messageInfo_BootstrappedResponse proto.InternalMessageInfo
type ShutdownRequest struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
@ -120,7 +244,7 @@ func (m *ShutdownRequest) Reset() { *m = ShutdownRequest{} }
func (m *ShutdownRequest) String() string { return proto.CompactTextString(m) }
func (*ShutdownRequest) ProtoMessage() {}
func (*ShutdownRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{2}
return fileDescriptor_cab246c8c7c5372d, []int{6}
}
func (m *ShutdownRequest) XXX_Unmarshal(b []byte) error {
@ -151,7 +275,7 @@ func (m *ShutdownResponse) Reset() { *m = ShutdownResponse{} }
func (m *ShutdownResponse) String() string { return proto.CompactTextString(m) }
func (*ShutdownResponse) ProtoMessage() {}
func (*ShutdownResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{3}
return fileDescriptor_cab246c8c7c5372d, []int{7}
}
func (m *ShutdownResponse) XXX_Unmarshal(b []byte) error {
@ -182,7 +306,7 @@ func (m *CreateHandlersRequest) Reset() { *m = CreateHandlersRequest{} }
func (m *CreateHandlersRequest) String() string { return proto.CompactTextString(m) }
func (*CreateHandlersRequest) ProtoMessage() {}
func (*CreateHandlersRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{4}
return fileDescriptor_cab246c8c7c5372d, []int{8}
}
func (m *CreateHandlersRequest) XXX_Unmarshal(b []byte) error {
@ -214,7 +338,7 @@ func (m *CreateHandlersResponse) Reset() { *m = CreateHandlersResponse{}
func (m *CreateHandlersResponse) String() string { return proto.CompactTextString(m) }
func (*CreateHandlersResponse) ProtoMessage() {}
func (*CreateHandlersResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{5}
return fileDescriptor_cab246c8c7c5372d, []int{9}
}
func (m *CreateHandlersResponse) XXX_Unmarshal(b []byte) error {
@ -255,7 +379,7 @@ func (m *Handler) Reset() { *m = Handler{} }
func (m *Handler) String() string { return proto.CompactTextString(m) }
func (*Handler) ProtoMessage() {}
func (*Handler) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{6}
return fileDescriptor_cab246c8c7c5372d, []int{10}
}
func (m *Handler) XXX_Unmarshal(b []byte) error {
@ -307,7 +431,7 @@ func (m *BuildBlockRequest) Reset() { *m = BuildBlockRequest{} }
func (m *BuildBlockRequest) String() string { return proto.CompactTextString(m) }
func (*BuildBlockRequest) ProtoMessage() {}
func (*BuildBlockRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{7}
return fileDescriptor_cab246c8c7c5372d, []int{11}
}
func (m *BuildBlockRequest) XXX_Unmarshal(b []byte) error {
@ -341,7 +465,7 @@ func (m *BuildBlockResponse) Reset() { *m = BuildBlockResponse{} }
func (m *BuildBlockResponse) String() string { return proto.CompactTextString(m) }
func (*BuildBlockResponse) ProtoMessage() {}
func (*BuildBlockResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{8}
return fileDescriptor_cab246c8c7c5372d, []int{12}
}
func (m *BuildBlockResponse) XXX_Unmarshal(b []byte) error {
@ -394,7 +518,7 @@ func (m *ParseBlockRequest) Reset() { *m = ParseBlockRequest{} }
func (m *ParseBlockRequest) String() string { return proto.CompactTextString(m) }
func (*ParseBlockRequest) ProtoMessage() {}
func (*ParseBlockRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{9}
return fileDescriptor_cab246c8c7c5372d, []int{13}
}
func (m *ParseBlockRequest) XXX_Unmarshal(b []byte) error {
@ -435,7 +559,7 @@ func (m *ParseBlockResponse) Reset() { *m = ParseBlockResponse{} }
func (m *ParseBlockResponse) String() string { return proto.CompactTextString(m) }
func (*ParseBlockResponse) ProtoMessage() {}
func (*ParseBlockResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{10}
return fileDescriptor_cab246c8c7c5372d, []int{14}
}
func (m *ParseBlockResponse) XXX_Unmarshal(b []byte) error {
@ -488,7 +612,7 @@ func (m *GetBlockRequest) Reset() { *m = GetBlockRequest{} }
func (m *GetBlockRequest) String() string { return proto.CompactTextString(m) }
func (*GetBlockRequest) ProtoMessage() {}
func (*GetBlockRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{11}
return fileDescriptor_cab246c8c7c5372d, []int{15}
}
func (m *GetBlockRequest) XXX_Unmarshal(b []byte) error {
@ -529,7 +653,7 @@ func (m *GetBlockResponse) Reset() { *m = GetBlockResponse{} }
func (m *GetBlockResponse) String() string { return proto.CompactTextString(m) }
func (*GetBlockResponse) ProtoMessage() {}
func (*GetBlockResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{12}
return fileDescriptor_cab246c8c7c5372d, []int{16}
}
func (m *GetBlockResponse) XXX_Unmarshal(b []byte) error {
@ -582,7 +706,7 @@ func (m *SetPreferenceRequest) Reset() { *m = SetPreferenceRequest{} }
func (m *SetPreferenceRequest) String() string { return proto.CompactTextString(m) }
func (*SetPreferenceRequest) ProtoMessage() {}
func (*SetPreferenceRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{13}
return fileDescriptor_cab246c8c7c5372d, []int{17}
}
func (m *SetPreferenceRequest) XXX_Unmarshal(b []byte) error {
@ -620,7 +744,7 @@ func (m *SetPreferenceResponse) Reset() { *m = SetPreferenceResponse{} }
func (m *SetPreferenceResponse) String() string { return proto.CompactTextString(m) }
func (*SetPreferenceResponse) ProtoMessage() {}
func (*SetPreferenceResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{14}
return fileDescriptor_cab246c8c7c5372d, []int{18}
}
func (m *SetPreferenceResponse) XXX_Unmarshal(b []byte) error {
@ -651,7 +775,7 @@ func (m *LastAcceptedRequest) Reset() { *m = LastAcceptedRequest{} }
func (m *LastAcceptedRequest) String() string { return proto.CompactTextString(m) }
func (*LastAcceptedRequest) ProtoMessage() {}
func (*LastAcceptedRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{15}
return fileDescriptor_cab246c8c7c5372d, []int{19}
}
func (m *LastAcceptedRequest) XXX_Unmarshal(b []byte) error {
@ -683,7 +807,7 @@ func (m *LastAcceptedResponse) Reset() { *m = LastAcceptedResponse{} }
func (m *LastAcceptedResponse) String() string { return proto.CompactTextString(m) }
func (*LastAcceptedResponse) ProtoMessage() {}
func (*LastAcceptedResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{16}
return fileDescriptor_cab246c8c7c5372d, []int{20}
}
func (m *LastAcceptedResponse) XXX_Unmarshal(b []byte) error {
@ -722,7 +846,7 @@ func (m *BlockVerifyRequest) Reset() { *m = BlockVerifyRequest{} }
func (m *BlockVerifyRequest) String() string { return proto.CompactTextString(m) }
func (*BlockVerifyRequest) ProtoMessage() {}
func (*BlockVerifyRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{17}
return fileDescriptor_cab246c8c7c5372d, []int{21}
}
func (m *BlockVerifyRequest) XXX_Unmarshal(b []byte) error {
@ -760,7 +884,7 @@ func (m *BlockVerifyResponse) Reset() { *m = BlockVerifyResponse{} }
func (m *BlockVerifyResponse) String() string { return proto.CompactTextString(m) }
func (*BlockVerifyResponse) ProtoMessage() {}
func (*BlockVerifyResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{18}
return fileDescriptor_cab246c8c7c5372d, []int{22}
}
func (m *BlockVerifyResponse) XXX_Unmarshal(b []byte) error {
@ -792,7 +916,7 @@ func (m *BlockAcceptRequest) Reset() { *m = BlockAcceptRequest{} }
func (m *BlockAcceptRequest) String() string { return proto.CompactTextString(m) }
func (*BlockAcceptRequest) ProtoMessage() {}
func (*BlockAcceptRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{19}
return fileDescriptor_cab246c8c7c5372d, []int{23}
}
func (m *BlockAcceptRequest) XXX_Unmarshal(b []byte) error {
@ -830,7 +954,7 @@ func (m *BlockAcceptResponse) Reset() { *m = BlockAcceptResponse{} }
func (m *BlockAcceptResponse) String() string { return proto.CompactTextString(m) }
func (*BlockAcceptResponse) ProtoMessage() {}
func (*BlockAcceptResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{20}
return fileDescriptor_cab246c8c7c5372d, []int{24}
}
func (m *BlockAcceptResponse) XXX_Unmarshal(b []byte) error {
@ -862,7 +986,7 @@ func (m *BlockRejectRequest) Reset() { *m = BlockRejectRequest{} }
func (m *BlockRejectRequest) String() string { return proto.CompactTextString(m) }
func (*BlockRejectRequest) ProtoMessage() {}
func (*BlockRejectRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{21}
return fileDescriptor_cab246c8c7c5372d, []int{25}
}
func (m *BlockRejectRequest) XXX_Unmarshal(b []byte) error {
@ -900,7 +1024,7 @@ func (m *BlockRejectResponse) Reset() { *m = BlockRejectResponse{} }
func (m *BlockRejectResponse) String() string { return proto.CompactTextString(m) }
func (*BlockRejectResponse) ProtoMessage() {}
func (*BlockRejectResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cab246c8c7c5372d, []int{22}
return fileDescriptor_cab246c8c7c5372d, []int{26}
}
func (m *BlockRejectResponse) XXX_Unmarshal(b []byte) error {
@ -924,6 +1048,10 @@ var xxx_messageInfo_BlockRejectResponse proto.InternalMessageInfo
func init() {
proto.RegisterType((*InitializeRequest)(nil), "vmproto.InitializeRequest")
proto.RegisterType((*InitializeResponse)(nil), "vmproto.InitializeResponse")
proto.RegisterType((*BootstrappingRequest)(nil), "vmproto.BootstrappingRequest")
proto.RegisterType((*BootstrappingResponse)(nil), "vmproto.BootstrappingResponse")
proto.RegisterType((*BootstrappedRequest)(nil), "vmproto.BootstrappedRequest")
proto.RegisterType((*BootstrappedResponse)(nil), "vmproto.BootstrappedResponse")
proto.RegisterType((*ShutdownRequest)(nil), "vmproto.ShutdownRequest")
proto.RegisterType((*ShutdownResponse)(nil), "vmproto.ShutdownResponse")
proto.RegisterType((*CreateHandlersRequest)(nil), "vmproto.CreateHandlersRequest")
@ -950,46 +1078,49 @@ func init() {
func init() { proto.RegisterFile("vm.proto", fileDescriptor_cab246c8c7c5372d) }
var fileDescriptor_cab246c8c7c5372d = []byte{
// 617 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x6d, 0x6f, 0xd2, 0x50,
0x14, 0x4e, 0x21, 0x32, 0x3c, 0xc0, 0x06, 0x17, 0xd8, 0xb0, 0x6e, 0x13, 0x1b, 0xb3, 0x60, 0x62,
0xf8, 0x30, 0x7f, 0xc0, 0x22, 0x8a, 0x6e, 0xf1, 0x6d, 0x96, 0x84, 0x98, 0xe8, 0x97, 0x42, 0x0f,
0x5b, 0x95, 0xb5, 0xf5, 0xde, 0x0b, 0x73, 0xfe, 0x23, 0xff, 0xa5, 0xa1, 0xbd, 0x6d, 0xef, 0xbd,
0xb4, 0x59, 0xe2, 0xb7, 0x9e, 0x73, 0x9e, 0xf3, 0x9c, 0x97, 0x7b, 0x9e, 0x42, 0x75, 0x7d, 0x33,
0x0c, 0x69, 0xc0, 0x03, 0xb2, 0xb3, 0xbe, 0x89, 0x3e, 0xac, 0x5b, 0x68, 0x5d, 0xf8, 0x1e, 0xf7,
0x9c, 0xa5, 0xf7, 0x07, 0x6d, 0xfc, 0xb5, 0x42, 0xc6, 0x89, 0x09, 0x55, 0x77, 0x36, 0x41, 0xba,
0x46, 0xda, 0x33, 0xfa, 0xc6, 0xa0, 0x61, 0xa7, 0x36, 0xb1, 0xa0, 0x7e, 0x85, 0x3e, 0x32, 0x8f,
0x8d, 0xee, 0x38, 0xb2, 0x5e, 0xa9, 0x6f, 0x0c, 0xea, 0xb6, 0xe2, 0xdb, 0x60, 0xd0, 0xbf, 0xf2,
0x7c, 0x14, 0x1c, 0xe5, 0x88, 0x43, 0xf1, 0x59, 0x1d, 0x20, 0x72, 0x61, 0x16, 0x06, 0x3e, 0x43,
0xab, 0x05, 0x7b, 0x93, 0xeb, 0x15, 0x77, 0x83, 0x5b, 0x5f, 0x34, 0x63, 0x11, 0x68, 0x66, 0x2e,
0x01, 0x3b, 0x80, 0xee, 0x6b, 0x8a, 0x0e, 0xc7, 0x73, 0xc7, 0x77, 0x97, 0x48, 0x59, 0x02, 0x7e,
0x0b, 0xfb, 0x7a, 0x20, 0x4e, 0x21, 0x2f, 0xa0, 0x7a, 0x2d, 0x7c, 0x3d, 0xa3, 0x5f, 0x1e, 0xd4,
0x4e, 0x9b, 0x43, 0xb1, 0x84, 0xa1, 0x00, 0xdb, 0x29, 0xc2, 0xfa, 0x06, 0x3b, 0xc2, 0x49, 0xf6,
0xa1, 0x12, 0x52, 0x5c, 0x78, 0xbf, 0xa3, 0x55, 0x3c, 0xb4, 0x85, 0x45, 0xfa, 0x50, 0x5b, 0x06,
0xf3, 0x9f, 0x9f, 0x43, 0xee, 0x05, 0x7e, 0xbc, 0x87, 0x86, 0x2d, 0xbb, 0x36, 0x99, 0x4c, 0x5e,
0x80, 0xb0, 0xac, 0x36, 0xb4, 0x46, 0x2b, 0x6f, 0xe9, 0x8e, 0x36, 0xe0, 0xa4, 0xf3, 0x29, 0x10,
0xd9, 0x29, 0xba, 0xde, 0x85, 0x92, 0xe7, 0x46, 0x85, 0xeb, 0x76, 0xc9, 0x73, 0x37, 0x2f, 0x13,
0x3a, 0x14, 0x7d, 0x7e, 0xf1, 0x46, 0x6c, 0x3e, 0xb5, 0x49, 0x07, 0x1e, 0xcc, 0xa2, 0x27, 0x29,
0x47, 0x81, 0xd8, 0xb0, 0x9e, 0x43, 0xeb, 0xd2, 0xa1, 0x0c, 0xe5, 0x62, 0x19, 0xd4, 0x90, 0xa1,
0x5f, 0x81, 0xc8, 0xd0, 0xff, 0x68, 0x61, 0x33, 0x31, 0x77, 0xf8, 0x8a, 0xa5, 0x13, 0x47, 0x96,
0xf5, 0x14, 0xf6, 0xde, 0x21, 0x57, 0x5a, 0xd0, 0x68, 0xad, 0xef, 0xd0, 0xcc, 0x20, 0xa2, 0xb4,
0x5c, 0xca, 0x28, 0x9a, 0xb6, 0x24, 0x8d, 0x50, 0xd8, 0xc0, 0x09, 0x74, 0x26, 0xc8, 0x2f, 0x29,
0x2e, 0x90, 0xa2, 0x3f, 0xc7, 0xa2, 0x2e, 0x0e, 0xa0, 0xab, 0xe1, 0xc4, 0xc5, 0x75, 0xa1, 0xfd,
0xc1, 0x61, 0xfc, 0xd5, 0x7c, 0x8e, 0x21, 0x47, 0x37, 0x79, 0xb5, 0x13, 0xe8, 0xa8, 0xee, 0xfc,
0xa5, 0x59, 0xcf, 0x80, 0x44, 0xa3, 0x4d, 0x91, 0x7a, 0x8b, 0xbb, 0xa2, 0xea, 0x5d, 0x68, 0x2b,
0x28, 0x51, 0x3b, 0x49, 0x8e, 0xab, 0xdc, 0x97, 0x9c, 0xa0, 0xb4, 0x64, 0x1b, 0x7f, 0xe0, 0xfc,
0xde, 0xe4, 0x04, 0x15, 0x27, 0x9f, 0xfe, 0xad, 0x40, 0x69, 0xfa, 0x91, 0x8c, 0x01, 0x32, 0xad,
0x12, 0x33, 0xd5, 0xcd, 0xd6, 0x9f, 0xc3, 0x7c, 0x9c, 0x1b, 0x13, 0x4b, 0x39, 0x83, 0x6a, 0xa2,
0x64, 0xd2, 0x4b, 0x81, 0x9a, 0xde, 0xcd, 0x47, 0x39, 0x11, 0x41, 0xf0, 0x05, 0x76, 0x55, 0x75,
0x93, 0xe3, 0x14, 0x9c, 0xfb, 0x3f, 0x30, 0x9f, 0x14, 0xc6, 0x05, 0xe5, 0x18, 0x20, 0x93, 0x9d,
0x34, 0xda, 0x96, 0x40, 0xa5, 0xd1, 0x72, 0x74, 0x3a, 0x06, 0xc8, 0xa4, 0x23, 0xd1, 0x6c, 0x49,
0x4f, 0xa2, 0xc9, 0xd1, 0xda, 0x19, 0x54, 0x13, 0x11, 0x48, 0x1b, 0xd2, 0xa4, 0x23, 0x6d, 0x68,
0x4b, 0x31, 0x9f, 0xa0, 0xa1, 0xdc, 0x2f, 0x39, 0xca, 0xb6, 0x99, 0x73, 0xff, 0xe6, 0x71, 0x51,
0x58, 0xf0, 0xbd, 0x87, 0xba, 0x7c, 0xdf, 0xe4, 0x30, 0xc5, 0xe7, 0xa8, 0xc1, 0x3c, 0x2a, 0x88,
0x0a, 0xb2, 0x73, 0xa8, 0x49, 0xe7, 0x4d, 0xa4, 0x85, 0x6e, 0x49, 0xc3, 0x3c, 0xcc, 0x0f, 0x6a,
0x4c, 0x71, 0x09, 0x9d, 0x49, 0xd1, 0x89, 0xce, 0xa4, 0xca, 0x23, 0x65, 0x8a, 0x0f, 0x5f, 0x67,
0x52, 0x44, 0xa3, 0x33, 0xa9, 0x5a, 0x99, 0x55, 0xa2, 0xd0, 0xcb, 0x7f, 0x01, 0x00, 0x00, 0xff,
0xff, 0xbb, 0xac, 0x5b, 0xc8, 0x65, 0x07, 0x00, 0x00,
// 672 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x54, 0x61, 0x4f, 0x13, 0x41,
0x10, 0x4d, 0x4b, 0x84, 0x3a, 0xb4, 0x40, 0x97, 0x16, 0xea, 0x09, 0x5a, 0x2f, 0x86, 0x60, 0x62,
0xf8, 0x80, 0x3f, 0x80, 0x58, 0x45, 0x21, 0x2a, 0xe2, 0x91, 0x10, 0x13, 0xfd, 0x72, 0xf4, 0x06,
0x38, 0x2d, 0x77, 0xe7, 0xee, 0xb6, 0x88, 0x3f, 0xd0, 0xdf, 0x65, 0xee, 0x6e, 0xef, 0x6e, 0x76,
0xbb, 0x17, 0x12, 0xbf, 0x75, 0x67, 0xde, 0xbc, 0x99, 0x9b, 0xe9, 0x7b, 0xd0, 0x9a, 0xdd, 0xec,
0x25, 0x3c, 0x96, 0x31, 0x5b, 0x9a, 0xdd, 0x64, 0x3f, 0xdc, 0x5b, 0xe8, 0x1e, 0x47, 0xa1, 0x0c,
0xfd, 0x49, 0xf8, 0x07, 0x3d, 0xfc, 0x35, 0x45, 0x21, 0x99, 0x03, 0xad, 0xe0, 0xe2, 0x0c, 0xf9,
0x0c, 0xf9, 0xa0, 0x31, 0x6c, 0xec, 0x76, 0xbc, 0xf2, 0xcd, 0x5c, 0x68, 0x5f, 0x61, 0x84, 0x22,
0x14, 0xa3, 0x3b, 0x89, 0x62, 0xd0, 0x1c, 0x36, 0x76, 0xdb, 0x9e, 0x16, 0x4b, 0x31, 0x18, 0x5d,
0x85, 0x11, 0x2a, 0x8e, 0x85, 0x8c, 0x43, 0x8b, 0xb9, 0x3d, 0x60, 0xb4, 0xb1, 0x48, 0xe2, 0x48,
0xa0, 0xbb, 0x01, 0xbd, 0x51, 0x1c, 0x4b, 0x21, 0xb9, 0x9f, 0x24, 0x61, 0x74, 0xa5, 0x26, 0x72,
0x37, 0xa1, 0x6f, 0xc4, 0x55, 0x41, 0x1f, 0xd6, 0xab, 0x04, 0x06, 0x05, 0x5e, 0xe3, 0x49, 0xc3,
0x0a, 0xde, 0x85, 0xd5, 0xb3, 0xeb, 0xa9, 0x0c, 0xe2, 0xdb, 0xa8, 0x80, 0x32, 0x58, 0xab, 0x42,
0x0a, 0xb6, 0x09, 0xfd, 0x37, 0x1c, 0x7d, 0x89, 0x47, 0x7e, 0x14, 0x4c, 0x90, 0x8b, 0x02, 0xfc,
0x0e, 0x36, 0xcc, 0x44, 0x5e, 0xc2, 0x5e, 0x42, 0xeb, 0x5a, 0xc5, 0x06, 0x8d, 0xe1, 0xc2, 0xee,
0xf2, 0xfe, 0xda, 0x9e, 0x5a, 0xf2, 0x9e, 0x02, 0x7b, 0x25, 0xc2, 0xfd, 0x06, 0x4b, 0x2a, 0xc8,
0x36, 0x60, 0x31, 0xe1, 0x78, 0x19, 0xfe, 0xce, 0x56, 0xfd, 0xd0, 0x53, 0x2f, 0x36, 0x84, 0xe5,
0x49, 0x3c, 0xfe, 0xf9, 0x39, 0x91, 0x61, 0x1c, 0xe5, 0x7b, 0xee, 0x78, 0x34, 0x94, 0x56, 0x0a,
0xba, 0x60, 0xf5, 0x72, 0xd7, 0xa1, 0x3b, 0x9a, 0x86, 0x93, 0x60, 0x94, 0x82, 0x8b, 0xc9, 0xcf,
0x81, 0xd1, 0xa0, 0x9a, 0x7a, 0x05, 0x9a, 0x61, 0x90, 0x35, 0x6e, 0x7b, 0xcd, 0x30, 0x48, 0x2f,
0x9f, 0xf8, 0x1c, 0x23, 0x79, 0xfc, 0x56, 0x5d, 0xb6, 0x7c, 0xb3, 0x1e, 0x3c, 0xb8, 0xc8, 0x4e,
0xbe, 0x90, 0x25, 0xf2, 0x87, 0xfb, 0x02, 0xba, 0xa7, 0x3e, 0x17, 0x48, 0x9b, 0x55, 0xd0, 0x06,
0x85, 0x7e, 0x05, 0x46, 0xa1, 0xff, 0x31, 0x42, 0xfa, 0xc5, 0xd2, 0x97, 0x53, 0x51, 0x7e, 0x71,
0xf6, 0x72, 0x9f, 0xc1, 0xea, 0x7b, 0x94, 0xda, 0x08, 0x06, 0xad, 0xfb, 0x1d, 0xd6, 0x2a, 0x88,
0x6a, 0x4d, 0x5b, 0x35, 0xea, 0xbe, 0xb6, 0x49, 0x3e, 0xa1, 0x76, 0x80, 0x1d, 0xe8, 0x9d, 0xa1,
0x3c, 0xe5, 0x78, 0x89, 0x1c, 0xa3, 0x31, 0xd6, 0x4d, 0xb1, 0x09, 0x7d, 0x03, 0x57, 0xfd, 0x8f,
0x3f, 0xfa, 0x42, 0xbe, 0x1e, 0x8f, 0x31, 0x91, 0xd5, 0xff, 0x78, 0x07, 0x7a, 0x7a, 0xd8, 0xbe,
0x34, 0xf7, 0x39, 0xb0, 0xec, 0xd3, 0xce, 0x91, 0x87, 0x97, 0x77, 0x75, 0xdd, 0x53, 0xb1, 0x50,
0x94, 0xea, 0x5d, 0x14, 0xe7, 0x5d, 0xee, 0x2b, 0x2e, 0x50, 0x46, 0xb1, 0x87, 0x3f, 0x70, 0x7c,
0x6f, 0x71, 0x81, 0xca, 0x8b, 0xf7, 0xff, 0x2e, 0x41, 0xf3, 0xfc, 0x13, 0x3b, 0x04, 0xa8, 0xbc,
0x80, 0x39, 0xa5, 0x6e, 0xe6, 0x9c, 0xc9, 0x79, 0x6c, 0xcd, 0xa9, 0xa5, 0x9c, 0x40, 0x47, 0x33,
0x09, 0xb6, 0x5d, 0xa2, 0x6d, 0xa6, 0xe2, 0x3c, 0xa9, 0x4b, 0x2b, 0xbe, 0x0f, 0xd0, 0xa6, 0x26,
0xc2, 0xb6, 0x2c, 0xf8, 0xf2, 0x54, 0xce, 0x76, 0x4d, 0x56, 0x91, 0x1d, 0x40, 0xab, 0xb0, 0x19,
0x36, 0x28, 0xa1, 0x86, 0x19, 0x39, 0x8f, 0x2c, 0x19, 0x45, 0xf0, 0x05, 0x56, 0x74, 0xeb, 0x61,
0xd5, 0xfc, 0x56, 0xb3, 0x72, 0x9e, 0xd6, 0xe6, 0x15, 0xe5, 0x21, 0x40, 0xe5, 0x09, 0x64, 0xef,
0x73, 0xee, 0x41, 0xf6, 0x6e, 0x31, 0x91, 0x43, 0x80, 0x4a, 0xd7, 0x84, 0x66, 0xce, 0x17, 0x08,
0x8d, 0xc5, 0x08, 0x0e, 0xa0, 0x55, 0x28, 0x94, 0x6c, 0xc8, 0xd0, 0x35, 0xd9, 0xd0, 0x9c, 0x9c,
0x4f, 0xa0, 0xa3, 0x89, 0x8b, 0xdc, 0xdf, 0x26, 0x4e, 0x72, 0x7f, 0xab, 0x26, 0xd3, 0xfb, 0x53,
0xf1, 0x91, 0xfb, 0x5b, 0xa4, 0x4a, 0xee, 0x6f, 0x55, 0xec, 0x11, 0x2c, 0x13, 0xed, 0x31, 0xb2,
0xd0, 0x39, 0xdd, 0x3a, 0x5b, 0xf6, 0xa4, 0xc1, 0x94, 0xb7, 0x30, 0x99, 0x34, 0x11, 0x9b, 0x4c,
0xba, 0x76, 0x4b, 0xa6, 0x5c, 0x95, 0x26, 0x93, 0xa6, 0x68, 0x93, 0x49, 0x17, 0xf2, 0xc5, 0x62,
0x96, 0x7a, 0xf5, 0x2f, 0x00, 0x00, 0xff, 0xff, 0x92, 0xa7, 0x99, 0xc8, 0x62, 0x08, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -1005,6 +1136,8 @@ const _ = grpc.SupportPackageIsVersion6
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type VMClient interface {
Initialize(ctx context.Context, in *InitializeRequest, opts ...grpc.CallOption) (*InitializeResponse, error)
Bootstrapping(ctx context.Context, in *BootstrappingRequest, opts ...grpc.CallOption) (*BootstrappingResponse, error)
Bootstrapped(ctx context.Context, in *BootstrappedRequest, opts ...grpc.CallOption) (*BootstrappedResponse, error)
Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error)
CreateHandlers(ctx context.Context, in *CreateHandlersRequest, opts ...grpc.CallOption) (*CreateHandlersResponse, error)
BuildBlock(ctx context.Context, in *BuildBlockRequest, opts ...grpc.CallOption) (*BuildBlockResponse, error)
@ -1034,6 +1167,24 @@ func (c *vMClient) Initialize(ctx context.Context, in *InitializeRequest, opts .
return out, nil
}
func (c *vMClient) Bootstrapping(ctx context.Context, in *BootstrappingRequest, opts ...grpc.CallOption) (*BootstrappingResponse, error) {
out := new(BootstrappingResponse)
err := c.cc.Invoke(ctx, "/vmproto.VM/Bootstrapping", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *vMClient) Bootstrapped(ctx context.Context, in *BootstrappedRequest, opts ...grpc.CallOption) (*BootstrappedResponse, error) {
out := new(BootstrappedResponse)
err := c.cc.Invoke(ctx, "/vmproto.VM/Bootstrapped", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *vMClient) Shutdown(ctx context.Context, in *ShutdownRequest, opts ...grpc.CallOption) (*ShutdownResponse, error) {
out := new(ShutdownResponse)
err := c.cc.Invoke(ctx, "/vmproto.VM/Shutdown", in, out, opts...)
@ -1127,6 +1278,8 @@ func (c *vMClient) BlockReject(ctx context.Context, in *BlockRejectRequest, opts
// VMServer is the server API for VM service.
type VMServer interface {
Initialize(context.Context, *InitializeRequest) (*InitializeResponse, error)
Bootstrapping(context.Context, *BootstrappingRequest) (*BootstrappingResponse, error)
Bootstrapped(context.Context, *BootstrappedRequest) (*BootstrappedResponse, error)
Shutdown(context.Context, *ShutdownRequest) (*ShutdownResponse, error)
CreateHandlers(context.Context, *CreateHandlersRequest) (*CreateHandlersResponse, error)
BuildBlock(context.Context, *BuildBlockRequest) (*BuildBlockResponse, error)
@ -1146,6 +1299,12 @@ type UnimplementedVMServer struct {
func (*UnimplementedVMServer) Initialize(ctx context.Context, req *InitializeRequest) (*InitializeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Initialize not implemented")
}
func (*UnimplementedVMServer) Bootstrapping(ctx context.Context, req *BootstrappingRequest) (*BootstrappingResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Bootstrapping not implemented")
}
func (*UnimplementedVMServer) Bootstrapped(ctx context.Context, req *BootstrappedRequest) (*BootstrappedResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Bootstrapped not implemented")
}
func (*UnimplementedVMServer) Shutdown(ctx context.Context, req *ShutdownRequest) (*ShutdownResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Shutdown not implemented")
}
@ -1199,6 +1358,42 @@ func _VM_Initialize_Handler(srv interface{}, ctx context.Context, dec func(inter
return interceptor(ctx, in, info, handler)
}
func _VM_Bootstrapping_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BootstrappingRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(VMServer).Bootstrapping(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/vmproto.VM/Bootstrapping",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(VMServer).Bootstrapping(ctx, req.(*BootstrappingRequest))
}
return interceptor(ctx, in, info, handler)
}
func _VM_Bootstrapped_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(BootstrappedRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(VMServer).Bootstrapped(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/vmproto.VM/Bootstrapped",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(VMServer).Bootstrapped(ctx, req.(*BootstrappedRequest))
}
return interceptor(ctx, in, info, handler)
}
func _VM_Shutdown_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ShutdownRequest)
if err := dec(in); err != nil {
@ -1387,6 +1582,14 @@ var _VM_serviceDesc = grpc.ServiceDesc{
MethodName: "Initialize",
Handler: _VM_Initialize_Handler,
},
{
MethodName: "Bootstrapping",
Handler: _VM_Bootstrapping_Handler,
},
{
MethodName: "Bootstrapped",
Handler: _VM_Bootstrapped_Handler,
},
{
MethodName: "Shutdown",
Handler: _VM_Shutdown_Handler,

View File

@ -9,6 +9,14 @@ message InitializeRequest {
message InitializeResponse {}
message BootstrappingRequest {}
message BootstrappingResponse {}
message BootstrappedRequest {}
message BootstrappedResponse {}
message ShutdownRequest {}
message ShutdownResponse {}
@ -86,6 +94,8 @@ message BlockRejectResponse {}
service VM {
rpc Initialize(InitializeRequest) returns (InitializeResponse);
rpc Bootstrapping(BootstrappingRequest) returns (BootstrappingResponse);
rpc Bootstrapped(BootstrappedRequest) returns (BootstrappedResponse);
rpc Shutdown(ShutdownRequest) returns (ShutdownResponse);
rpc CreateHandlers(CreateHandlersRequest) returns (CreateHandlersResponse);
rpc BuildBlock(BuildBlockRequest) returns (BuildBlockResponse);
@ -97,4 +107,4 @@ service VM {
rpc BlockVerify(BlockVerifyRequest) returns (BlockVerifyResponse);
rpc BlockAccept(BlockAcceptRequest) returns (BlockAcceptResponse);
rpc BlockReject(BlockRejectRequest) returns (BlockRejectResponse);
}
}

View File

@ -34,8 +34,9 @@ var (
// Fx describes the secp256k1 feature extension
type Fx struct {
VM VM
SECPFactory crypto.FactorySECP256K1R
VM VM
SECPFactory crypto.FactorySECP256K1R
bootstrapped bool
}
// Initialize ...
@ -69,6 +70,12 @@ func (fx *Fx) InitializeVM(vmIntf interface{}) error {
return nil
}
// Bootstrapping ...
func (fx *Fx) Bootstrapping() error { return nil }
// Bootstrapped ...
func (fx *Fx) Bootstrapped() error { fx.bootstrapped = true; return nil }
// VerifyOperation ...
func (fx *Fx) VerifyOperation(txIntf, opIntf, credIntf interface{}, utxosIntf []interface{}) error {
tx, ok := txIntf.(Tx)
@ -156,6 +163,11 @@ func (fx *Fx) VerifyCredentials(tx Tx, in *Input, cred *Credential, out *OutputO
return errInputCredentialSignersMismatch
}
// disable signature verification during bootstrapping
if !fx.bootstrapped {
return nil
}
txBytes := tx.UnsignedBytes()
txHash := hashing.ComputeHash256(txBytes)

View File

@ -76,6 +76,12 @@ func TestFxVerifyTransfer(t *testing.T) {
if err := fx.Initialize(&vm); err != nil {
t.Fatal(err)
}
if err := fx.Bootstrapping(); err != nil {
t.Fatal(err)
}
if err := fx.Bootstrapped(); err != nil {
t.Fatal(err)
}
tx := &testTx{
bytes: txBytes,
}
@ -470,6 +476,9 @@ func TestFxVerifyTransferInvalidSignature(t *testing.T) {
if err := fx.Initialize(&vm); err != nil {
t.Fatal(err)
}
if err := fx.Bootstrapping(); err != nil {
t.Fatal(err)
}
tx := &testTx{
bytes: txBytes,
}
@ -495,6 +504,14 @@ func TestFxVerifyTransferInvalidSignature(t *testing.T) {
},
}
if err := fx.VerifyTransfer(tx, in, cred, out); err != nil {
t.Fatal(err)
}
if err := fx.Bootstrapped(); err != nil {
t.Fatal(err)
}
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to an invalid signature")
}
@ -508,6 +525,9 @@ func TestFxVerifyTransferWrongSigner(t *testing.T) {
if err := fx.Initialize(&vm); err != nil {
t.Fatal(err)
}
if err := fx.Bootstrapping(); err != nil {
t.Fatal(err)
}
tx := &testTx{
bytes: txBytes,
}
@ -533,6 +553,14 @@ func TestFxVerifyTransferWrongSigner(t *testing.T) {
},
}
if err := fx.VerifyTransfer(tx, in, cred, out); err != nil {
t.Fatal(err)
}
if err := fx.Bootstrapped(); err != nil {
t.Fatal(err)
}
if err := fx.VerifyTransfer(tx, in, cred, out); err == nil {
t.Fatalf("Should have errored due to a wrong signer")
}

View File

@ -105,7 +105,13 @@ func ConsensusLeader(numBlocks, numTxsPerBlock int, b *testing.B) {
// Asynchronously passes messages from the network to the consensus engine
handler := &router.Handler{}
handler.Initialize(&engine, msgChan, 1000)
handler.Initialize(
&engine,
msgChan,
1000,
"",
prometheus.NewRegistry(),
)
// Allow incoming messages to be routed to the new chain
chainRouter.AddChain(handler)
@ -238,7 +244,13 @@ func ConsensusFollower(numBlocks, numTxsPerBlock int, b *testing.B) {
// Asynchronously passes messages from the network to the consensus engine
handler := &router.Handler{}
handler.Initialize(&engine, msgChan, 1000)
handler.Initialize(
&engine,
msgChan,
1000,
"",
prometheus.NewRegistry(),
)
// Allow incoming messages to be routed to the new chain
chainRouter.AddChain(handler)

View File

@ -116,6 +116,12 @@ func (vm *VM) Initialize(
return nil
}
// Bootstrapping marks this VM as bootstrapping
func (vm *VM) Bootstrapping() error { return nil }
// Bootstrapped marks this VM as bootstrapped
func (vm *VM) Bootstrapped() error { return nil }
// Shutdown implements the snowman.ChainVM interface
func (vm *VM) Shutdown() error {
if vm.timer == nil {

View File

@ -128,6 +128,12 @@ func (vm *VM) Initialize(
return vm.db.Commit()
}
// Bootstrapping marks this VM as bootstrapping
func (vm *VM) Bootstrapping() error { return nil }
// Bootstrapped marks this VM as bootstrapped
func (vm *VM) Bootstrapped() error { return nil }
// Shutdown implements the avalanche.DAGVM interface
func (vm *VM) Shutdown() error {
if vm.timer == nil {