diff --git a/README.md b/README.md index 0eb539f9f0d5..7842615f35be 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ The minimum recommended hardware specification for nodes connected to Mainnet is - CPU: Equivalent of 8 AWS vCPU - RAM: 16 GiB - Storage: 1 TiB + - Nodes running for very long periods of time or nodes with custom configurations may observe higher storage requirements. - OS: Ubuntu 20.04/22.04 or macOS >= 12 - Network: Reliable IPv4 or IPv6 network connection, with an open public port. diff --git a/chains/manager.go b/chains/manager.go index 70c2bc1de514..55119b223244 100644 --- a/chains/manager.go +++ b/chains/manager.go @@ -883,21 +883,17 @@ func (m *manager) createAvalancheChain( // create bootstrap gear bootstrapCfg := smbootstrap.Config{ - Config: common.Config{ - Ctx: ctx, - Beacons: vdrs, - SampleK: sampleK, - Alpha: bootstrapWeight/2 + 1, // must be > 50% - StartupTracker: startupTracker, - Sender: snowmanMessageSender, - BootstrapTracker: sb, - Timer: h, - AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, - SharedCfg: &common.SharedConfig{}, - }, - AllGetsServer: snowGetHandler, - Blocked: blockBlocker, - VM: vmWrappingProposerVM, + AllGetsServer: snowGetHandler, + Ctx: ctx, + Beacons: vdrs, + SampleK: sampleK, + StartupTracker: startupTracker, + Sender: snowmanMessageSender, + BootstrapTracker: sb, + Timer: h, + AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, + Blocked: blockBlocker, + VM: vmWrappingProposerVM, } var snowmanBootstrapper common.BootstrapableEngine snowmanBootstrapper, err = smbootstrap.New( @@ -1234,24 +1230,19 @@ func (m *manager) createSnowmanChain( } // create bootstrap gear - alpha := bootstrapWeight/2 + 1 // must be > 50% bootstrapCfg := smbootstrap.Config{ - Config: common.Config{ - Ctx: ctx, - Beacons: beacons, - SampleK: sampleK, - StartupTracker: startupTracker, - Alpha: alpha, - Sender: messageSender, - BootstrapTracker: sb, - Timer: h, - AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, - SharedCfg: &common.SharedConfig{}, - }, - AllGetsServer: snowGetHandler, - Blocked: blocked, - VM: vm, - Bootstrapped: bootstrapFunc, + AllGetsServer: snowGetHandler, + Ctx: ctx, + Beacons: beacons, + SampleK: sampleK, + StartupTracker: startupTracker, + Sender: messageSender, + BootstrapTracker: sb, + Timer: h, + AncestorsMaxContainersReceived: m.BootstrapAncestorsMaxContainersReceived, + Blocked: blocked, + VM: vm, + Bootstrapped: bootstrapFunc, } var bootstrapper common.BootstrapableEngine bootstrapper, err = smbootstrap.New( @@ -1274,7 +1265,7 @@ func (m *manager) createSnowmanChain( messageSender, beacons, sampleK, - alpha, + bootstrapWeight/2+1, // must be > 50% m.StateSyncBeacons, vm, ) diff --git a/codec/hierarchycodec/codec.go b/codec/hierarchycodec/codec.go index d1d03d879275..1b82380bc576 100644 --- a/codec/hierarchycodec/codec.go +++ b/codec/hierarchycodec/codec.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/codec/reflectcodec" + "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/wrappers" ) @@ -42,20 +43,18 @@ type typeID struct { type hierarchyCodec struct { codec.Codec - lock sync.RWMutex - currentGroupID uint16 - nextTypeID uint16 - typeIDToType map[typeID]reflect.Type - typeToTypeID map[reflect.Type]typeID + lock sync.RWMutex + currentGroupID uint16 + nextTypeID uint16 + registeredTypes *bimap.BiMap[typeID, reflect.Type] } // New returns a new, concurrency-safe codec func New(tagNames []string, maxSliceLen uint32) Codec { hCodec := &hierarchyCodec{ - currentGroupID: 0, - nextTypeID: 0, - typeIDToType: map[typeID]reflect.Type{}, - typeToTypeID: map[reflect.Type]typeID{}, + currentGroupID: 0, + nextTypeID: 0, + registeredTypes: bimap.New[typeID, reflect.Type](), } hCodec.Codec = reflectcodec.New(hCodec, tagNames, maxSliceLen) return hCodec @@ -88,7 +87,7 @@ func (c *hierarchyCodec) RegisterType(val interface{}) error { defer c.lock.Unlock() valType := reflect.TypeOf(val) - if _, exists := c.typeToTypeID[valType]; exists { + if c.registeredTypes.HasValue(valType) { return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType) } @@ -98,8 +97,7 @@ func (c *hierarchyCodec) RegisterType(val interface{}) error { } c.nextTypeID++ - c.typeIDToType[valTypeID] = valType - c.typeToTypeID[valType] = valTypeID + c.registeredTypes.Put(valTypeID, valType) return nil } @@ -112,7 +110,7 @@ func (c *hierarchyCodec) PackPrefix(p *wrappers.Packer, valueType reflect.Type) c.lock.RLock() defer c.lock.RUnlock() - typeID, ok := c.typeToTypeID[valueType] // Get the type ID of the value being marshaled + typeID, ok := c.registeredTypes.GetKey(valueType) // Get the type ID of the value being marshaled if !ok { return fmt.Errorf("can't marshal unregistered type %q", valueType) } @@ -136,7 +134,7 @@ func (c *hierarchyCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type typeID: typeIDShort, } // Get a type that implements the interface - implementingType, ok := c.typeIDToType[t] + implementingType, ok := c.registeredTypes.GetValue(t) if !ok { return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: unknown type ID %+v", t) } diff --git a/codec/linearcodec/codec.go b/codec/linearcodec/codec.go index 677c331b0366..07097aee79eb 100644 --- a/codec/linearcodec/codec.go +++ b/codec/linearcodec/codec.go @@ -10,6 +10,7 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/codec/reflectcodec" + "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/wrappers" ) @@ -36,19 +37,17 @@ type Codec interface { type linearCodec struct { codec.Codec - lock sync.RWMutex - nextTypeID uint32 - typeIDToType map[uint32]reflect.Type - typeToTypeID map[reflect.Type]uint32 + lock sync.RWMutex + nextTypeID uint32 + registeredTypes *bimap.BiMap[uint32, reflect.Type] } // New returns a new, concurrency-safe codec; it allow to specify // both tagNames and maxSlicelenght func New(tagNames []string, maxSliceLen uint32) Codec { hCodec := &linearCodec{ - nextTypeID: 0, - typeIDToType: map[uint32]reflect.Type{}, - typeToTypeID: map[reflect.Type]uint32{}, + nextTypeID: 0, + registeredTypes: bimap.New[uint32, reflect.Type](), } hCodec.Codec = reflectcodec.New(hCodec, tagNames, maxSliceLen) return hCodec @@ -78,12 +77,11 @@ func (c *linearCodec) RegisterType(val interface{}) error { defer c.lock.Unlock() valType := reflect.TypeOf(val) - if _, exists := c.typeToTypeID[valType]; exists { + if c.registeredTypes.HasValue(valType) { return fmt.Errorf("%w: %v", codec.ErrDuplicateType, valType) } - c.typeIDToType[c.nextTypeID] = valType - c.typeToTypeID[valType] = c.nextTypeID + c.registeredTypes.Put(c.nextTypeID, valType) c.nextTypeID++ return nil } @@ -97,7 +95,7 @@ func (c *linearCodec) PackPrefix(p *wrappers.Packer, valueType reflect.Type) err c.lock.RLock() defer c.lock.RUnlock() - typeID, ok := c.typeToTypeID[valueType] // Get the type ID of the value being marshaled + typeID, ok := c.registeredTypes.GetKey(valueType) // Get the type ID of the value being marshaled if !ok { return fmt.Errorf("can't marshal unregistered type %q", valueType) } @@ -114,7 +112,7 @@ func (c *linearCodec) UnpackPrefix(p *wrappers.Packer, valueType reflect.Type) ( return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: %w", p.Err) } // Get a type that implements the interface - implementingType, ok := c.typeIDToType[typeID] + implementingType, ok := c.registeredTypes.GetValue(typeID) if !ok { return reflect.Value{}, fmt.Errorf("couldn't unmarshal interface: unknown type ID %d", typeID) } diff --git a/genesis/config.go b/genesis/config.go index 2a7063f87940..a951e9e078fc 100644 --- a/genesis/config.go +++ b/genesis/config.go @@ -17,6 +17,7 @@ import ( "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/formatting/address" "github.com/ava-labs/avalanchego/utils/math" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" ) var ( @@ -58,9 +59,10 @@ func (a Allocation) Less(other Allocation) bool { } type Staker struct { - NodeID ids.NodeID `json:"nodeID"` - RewardAddress ids.ShortID `json:"rewardAddress"` - DelegationFee uint32 `json:"delegationFee"` + NodeID ids.NodeID `json:"nodeID"` + RewardAddress ids.ShortID `json:"rewardAddress"` + DelegationFee uint32 `json:"delegationFee"` + Signer *signer.ProofOfPossession `json:"signer,omitempty"` } func (s Staker) Unparse(networkID uint32) (UnparsedStaker, error) { @@ -73,6 +75,7 @@ func (s Staker) Unparse(networkID uint32) (UnparsedStaker, error) { NodeID: s.NodeID, RewardAddress: avaxAddr, DelegationFee: s.DelegationFee, + Signer: s.Signer, }, err } diff --git a/genesis/genesis.go b/genesis/genesis.go index e59b8c6fbbbc..533795b56973 100644 --- a/genesis/genesis.go +++ b/genesis/genesis.go @@ -430,6 +430,7 @@ func FromConfig(config *Config) ([]byte, ids.ID, error) { }, Staked: utxos, ExactDelegationFee: &delegationFee, + Signer: staker.Signer, }, ) } diff --git a/genesis/unparsed_config.go b/genesis/unparsed_config.go index 9831d835add9..647443bae482 100644 --- a/genesis/unparsed_config.go +++ b/genesis/unparsed_config.go @@ -9,6 +9,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/formatting/address" + "github.com/ava-labs/avalanchego/vms/platformvm/signer" ) var errInvalidETHAddress = errors.New("invalid eth address") @@ -54,15 +55,17 @@ func (ua UnparsedAllocation) Parse() (Allocation, error) { } type UnparsedStaker struct { - NodeID ids.NodeID `json:"nodeID"` - RewardAddress string `json:"rewardAddress"` - DelegationFee uint32 `json:"delegationFee"` + NodeID ids.NodeID `json:"nodeID"` + RewardAddress string `json:"rewardAddress"` + DelegationFee uint32 `json:"delegationFee"` + Signer *signer.ProofOfPossession `json:"signer,omitempty"` } func (us UnparsedStaker) Parse() (Staker, error) { s := Staker{ NodeID: us.NodeID, DelegationFee: us.DelegationFee, + Signer: us.Signer, } _, _, avaxAddrBytes, err := address.Parse(us.RewardAddress) diff --git a/x/sync/peer_tracker.go b/network/p2p/peer_tracker.go similarity index 94% rename from x/sync/peer_tracker.go rename to network/p2p/peer_tracker.go index a1f8a66ae711..338d890bed22 100644 --- a/x/sync/peer_tracker.go +++ b/network/p2p/peer_tracker.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package sync +package p2p import ( "math" @@ -45,7 +45,7 @@ type peerInfo struct { // Tracks the bandwidth of responses coming from peers, // preferring to contact peers with known good bandwidth, connecting // to new peers with an exponentially decaying probability. -type peerTracker struct { +type PeerTracker struct { // Lock to protect concurrent access to the peer tracker lock sync.Mutex // All peers we are connected to @@ -64,12 +64,12 @@ type peerTracker struct { averageBandwidthMetric prometheus.Gauge } -func newPeerTracker( +func NewPeerTracker( log logging.Logger, metricsNamespace string, registerer prometheus.Registerer, -) (*peerTracker, error) { - t := &peerTracker{ +) (*PeerTracker, error) { + t := &PeerTracker{ peers: make(map[ids.NodeID]*peerInfo), trackedPeers: make(set.Set[ids.NodeID]), responsivePeers: make(set.Set[ids.NodeID]), @@ -112,7 +112,7 @@ func newPeerTracker( // Returns true if we're not connected to enough peers. // Otherwise returns true probabilistically based on the number of tracked peers. // Assumes p.lock is held. -func (p *peerTracker) shouldTrackNewPeer() bool { +func (p *PeerTracker) shouldTrackNewPeer() bool { numResponsivePeers := p.responsivePeers.Len() if numResponsivePeers < desiredMinResponsivePeers { return true @@ -137,11 +137,12 @@ func (p *peerTracker) shouldTrackNewPeer() bool { return rand.Float64() < newPeerProbability // #nosec G404 } +// TODO get rid of minVersion // Returns a peer that we're connected to. // If we should track more peers, returns a random peer with version >= [minVersion], if any exist. // Otherwise, with probability [randomPeerProbability] returns a random peer from [p.responsivePeers]. // With probability [1-randomPeerProbability] returns the peer in [p.bandwidthHeap] with the highest bandwidth. -func (p *peerTracker) GetAnyPeer(minVersion *version.Application) (ids.NodeID, bool) { +func (p *PeerTracker) GetAnyPeer(minVersion *version.Application) (ids.NodeID, bool) { p.lock.Lock() defer p.lock.Unlock() @@ -187,7 +188,7 @@ func (p *peerTracker) GetAnyPeer(minVersion *version.Application) (ids.NodeID, b } // Record that we sent a request to [nodeID]. -func (p *peerTracker) TrackPeer(nodeID ids.NodeID) { +func (p *PeerTracker) TrackPeer(nodeID ids.NodeID) { p.lock.Lock() defer p.lock.Unlock() @@ -197,7 +198,7 @@ func (p *peerTracker) TrackPeer(nodeID ids.NodeID) { // Record that we observed that [nodeID]'s bandwidth is [bandwidth]. // Adds the peer's bandwidth averager to the bandwidth heap. -func (p *peerTracker) TrackBandwidth(nodeID ids.NodeID, bandwidth float64) { +func (p *PeerTracker) TrackBandwidth(nodeID ids.NodeID, bandwidth float64) { p.lock.Lock() defer p.lock.Unlock() @@ -229,7 +230,7 @@ func (p *peerTracker) TrackBandwidth(nodeID ids.NodeID, bandwidth float64) { } // Connected should be called when [nodeID] connects to this node -func (p *peerTracker) Connected(nodeID ids.NodeID, nodeVersion *version.Application) { +func (p *PeerTracker) Connected(nodeID ids.NodeID, nodeVersion *version.Application) { p.lock.Lock() defer p.lock.Unlock() @@ -264,7 +265,7 @@ func (p *peerTracker) Connected(nodeID ids.NodeID, nodeVersion *version.Applicat } // Disconnected should be called when [nodeID] disconnects from this node -func (p *peerTracker) Disconnected(nodeID ids.NodeID) { +func (p *PeerTracker) Disconnected(nodeID ids.NodeID) { p.lock.Lock() defer p.lock.Unlock() @@ -277,7 +278,7 @@ func (p *peerTracker) Disconnected(nodeID ids.NodeID) { } // Returns the number of peers the node is connected to. -func (p *peerTracker) Size() int { +func (p *PeerTracker) Size() int { p.lock.Lock() defer p.lock.Unlock() diff --git a/network/p2p/peer_tracker_test.go b/network/p2p/peer_tracker_test.go new file mode 100644 index 000000000000..d7c38b828e9d --- /dev/null +++ b/network/p2p/peer_tracker_test.go @@ -0,0 +1,99 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package p2p + +import ( + "testing" + + "github.com/prometheus/client_golang/prometheus" + + "github.com/stretchr/testify/require" + + "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/utils/logging" + "github.com/ava-labs/avalanchego/version" +) + +func TestPeerTracker(t *testing.T) { + require := require.New(t) + p, err := NewPeerTracker(logging.NoLog{}, "", prometheus.NewRegistry()) + require.NoError(err) + + // Connect some peers + numExtraPeers := 10 + numPeers := desiredMinResponsivePeers + numExtraPeers + peerIDs := make([]ids.NodeID, numPeers) + peerVersion := &version.Application{ + Major: 1, + Minor: 2, + Patch: 3, + } + + for i := range peerIDs { + peerIDs[i] = ids.GenerateTestNodeID() + p.Connected(peerIDs[i], peerVersion) + } + + responsivePeers := make(map[ids.NodeID]bool) + + // Expect requests to go to new peers until we have desiredMinResponsivePeers responsive peers. + for i := 0; i < desiredMinResponsivePeers+numExtraPeers/2; i++ { + peer, ok := p.GetAnyPeer(nil) + require.True(ok) + require.NotNil(peer) + + _, exists := responsivePeers[peer] + require.Falsef(exists, "expected connecting to a new peer, but got the same peer twice: peer %s iteration %d", peer, i) + responsivePeers[peer] = true + + p.TrackPeer(peer) // mark the peer as having a message sent to it + } + + // Mark some peers as responsive and others as not responsive + i := 0 + for peer := range responsivePeers { + if i < desiredMinResponsivePeers { + p.TrackBandwidth(peer, 10) + } else { + responsivePeers[peer] = false // remember which peers were not responsive + p.TrackBandwidth(peer, 0) + } + i++ + } + + // Expect requests to go to responsive or new peers, so long as they are available + numRequests := 50 + for i := 0; i < numRequests; i++ { + peer, ok := p.GetAnyPeer(nil) + require.True(ok) + require.NotNil(peer) + + responsive, ok := responsivePeers[peer] + if ok { + require.Truef(responsive, "expected connecting to a responsive peer, but got a peer that was not responsive: peer %s iteration %d", peer, i) + p.TrackBandwidth(peer, 10) + } else { + responsivePeers[peer] = false // remember that we connected to this peer + p.TrackPeer(peer) // mark the peer as having a message sent to it + p.TrackBandwidth(peer, 0) // mark the peer as non-responsive + } + } + + // Disconnect from peers that were previously responsive and ones we didn't connect to yet. + for _, peer := range peerIDs { + responsive, ok := responsivePeers[peer] + if ok && responsive || !ok { + p.Disconnected(peer) + } + } + + // Requests should fall back on non-responsive peers when no other choice is left + peer, ok := p.GetAnyPeer(nil) + require.True(ok) + require.NotNil(peer) + + responsive, ok := responsivePeers[peer] + require.True(ok) + require.Falsef(responsive, "expected connecting to a non-responsive peer, but got a peer that was responsive: peer %s", peer) +} diff --git a/scripts/mocks.mockgen.txt b/scripts/mocks.mockgen.txt index 4b7afa01849f..76add90f3f7f 100644 --- a/scripts/mocks.mockgen.txt +++ b/scripts/mocks.mockgen.txt @@ -27,17 +27,14 @@ github.com/ava-labs/avalanchego/utils/logging=Logger=utils/logging/mock_logger.g github.com/ava-labs/avalanchego/utils/resource=User=utils/resource/mock_user.go github.com/ava-labs/avalanchego/vms/avm/block=Block=vms/avm/block/mock_block.go github.com/ava-labs/avalanchego/vms/avm/metrics=Metrics=vms/avm/metrics/mock_metrics.go -github.com/ava-labs/avalanchego/vms/avm/states=Chain,State,Diff=vms/avm/states/mock_states.go +github.com/ava-labs/avalanchego/vms/avm/state=Chain,State,Diff=vms/avm/state/mock_state.go github.com/ava-labs/avalanchego/vms/avm/txs/mempool=Mempool=vms/avm/txs/mempool/mock_mempool.go github.com/ava-labs/avalanchego/vms/components/avax=TransferableIn=vms/components/avax/mock_transferable_in.go github.com/ava-labs/avalanchego/vms/components/verify=Verifiable=vms/components/verify/mock_verifiable.go github.com/ava-labs/avalanchego/vms/platformvm/block/executor=Manager=vms/platformvm/block/executor/mock_manager.go github.com/ava-labs/avalanchego/vms/platformvm/block=Block=vms/platformvm/block/mock_block.go -github.com/ava-labs/avalanchego/vms/platformvm/state=Chain=vms/platformvm/state/mock_chain.go -github.com/ava-labs/avalanchego/vms/platformvm/state=Diff=vms/platformvm/state/mock_diff.go +github.com/ava-labs/avalanchego/vms/platformvm/state=Chain,Diff,State,Versions=vms/platformvm/state/mock_state.go github.com/ava-labs/avalanchego/vms/platformvm/state=StakerIterator=vms/platformvm/state/mock_staker_iterator.go -github.com/ava-labs/avalanchego/vms/platformvm/state=State=vms/platformvm/state/mock_state.go -github.com/ava-labs/avalanchego/vms/platformvm/state=Versions=vms/platformvm/state/mock_versions.go github.com/ava-labs/avalanchego/vms/platformvm/txs/builder=Builder=vms/platformvm/txs/builder/mock_builder.go github.com/ava-labs/avalanchego/vms/platformvm/txs/mempool=Mempool=vms/platformvm/txs/mempool/mock_mempool.go github.com/ava-labs/avalanchego/vms/platformvm/utxo=Verifier=vms/platformvm/utxo/mock_verifier.go diff --git a/snow/consensus/snowman/metrics.go b/snow/consensus/snowman/metrics.go index 9dfac39880ab..6e5159d6c1a5 100644 --- a/snow/consensus/snowman/metrics.go +++ b/snow/consensus/snowman/metrics.go @@ -41,21 +41,22 @@ type metrics struct { // numProcessing keeps track of the number of processing blocks numProcessing prometheus.Gauge + blockSizeAcceptedSum prometheus.Gauge // pollsAccepted tracks the number of polls that a block was in processing // for before being accepted pollsAccepted metric.Averager // latAccepted tracks the number of nanoseconds that a block was processing // before being accepted latAccepted metric.Averager - blockSizeAcceptedSum prometheus.Gauge + buildLatencyAccepted prometheus.Gauge + blockSizeRejectedSum prometheus.Gauge // pollsRejected tracks the number of polls that a block was in processing // for before being rejected pollsRejected metric.Averager // latRejected tracks the number of nanoseconds that a block was processing // before being rejected - latRejected metric.Averager - blockSizeRejectedSum prometheus.Gauge + latRejected metric.Averager // numFailedPolls keeps track of the number of polls that failed numFailedPolls prometheus.Counter @@ -101,6 +102,11 @@ func newMetrics( Help: "number of currently processing blocks", }), + blockSizeAcceptedSum: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: namespace, + Name: "blks_accepted_container_size_sum", + Help: "cumulative size of all accepted blocks", + }), pollsAccepted: metric.NewAveragerWithErrs( namespace, "blks_polls_accepted", @@ -121,12 +127,17 @@ func newMetrics( reg, &errs, ), - blockSizeAcceptedSum: prometheus.NewGauge(prometheus.GaugeOpts{ + buildLatencyAccepted: prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, - Name: "blks_accepted_container_size_sum", - Help: "cumulative size of all accepted blocks", + Name: "blks_build_accept_latency", + Help: "time (in ns) from the timestamp of a block to the time it was accepted", }), + blockSizeRejectedSum: prometheus.NewGauge(prometheus.GaugeOpts{ + Namespace: namespace, + Name: "blks_rejected_container_size_sum", + Help: "cumulative size of all rejected blocks", + }), pollsRejected: metric.NewAveragerWithErrs( namespace, "blks_polls_rejected", @@ -147,11 +158,6 @@ func newMetrics( reg, &errs, ), - blockSizeRejectedSum: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: namespace, - Name: "blks_rejected_container_size_sum", - Help: "cumulative size of all rejected blocks", - }), numSuccessfulPolls: prometheus.NewCounter(prometheus.CounterOpts{ Namespace: namespace, @@ -176,6 +182,7 @@ func newMetrics( reg.Register(m.lastAcceptedTimestamp), reg.Register(m.numProcessing), reg.Register(m.blockSizeAcceptedSum), + reg.Register(m.buildLatencyAccepted), reg.Register(m.blockSizeRejectedSum), reg.Register(m.numSuccessfulPolls), reg.Register(m.numFailedPolls), @@ -216,12 +223,16 @@ func (m *metrics) Accepted( m.processingBlocks.Delete(blkID) m.numProcessing.Dec() + m.blockSizeAcceptedSum.Add(float64(blockSize)) + m.pollsAccepted.Observe(float64(pollNumber - start.pollNumber)) - duration := time.Since(start.time) - m.latAccepted.Observe(float64(duration)) + now := time.Now() + processingDuration := now.Sub(start.time) + m.latAccepted.Observe(float64(processingDuration)) - m.blockSizeAcceptedSum.Add(float64(blockSize)) + builtDuration := now.Sub(timestamp) + m.buildLatencyAccepted.Add(float64(builtDuration)) } func (m *metrics) Rejected(blkID ids.ID, pollNumber uint64, blockSize int) { @@ -236,12 +247,12 @@ func (m *metrics) Rejected(blkID ids.ID, pollNumber uint64, blockSize int) { m.processingBlocks.Delete(blkID) m.numProcessing.Dec() + m.blockSizeRejectedSum.Add(float64(blockSize)) + m.pollsRejected.Observe(float64(pollNumber - start.pollNumber)) duration := time.Since(start.time) m.latRejected.Observe(float64(duration)) - - m.blockSizeRejectedSum.Add(float64(blockSize)) } func (m *metrics) MeasureAndGetOldestDuration() time.Duration { diff --git a/snow/consensus/snowman/topological.go b/snow/consensus/snowman/topological.go index bc68762c894e..f3fc838a8f8b 100644 --- a/snow/consensus/snowman/topological.go +++ b/snow/consensus/snowman/topological.go @@ -622,9 +622,11 @@ func (ts *Topological) acceptPreferredChild(ctx context.Context, n *snowmanBlock } height := child.Height() + timestamp := child.Timestamp() ts.ctx.Log.Trace("accepting block", zap.Stringer("blkID", pref), zap.Uint64("height", height), + zap.Time("timestamp", timestamp), ) if err := child.Accept(ctx); err != nil { return err @@ -641,7 +643,7 @@ func (ts *Topological) acceptPreferredChild(ctx context.Context, n *snowmanBlock ts.metrics.Accepted( pref, height, - child.Timestamp(), + timestamp, ts.pollNumber, len(bytes), ) diff --git a/snow/engine/avalanche/bootstrap/bootstrapper.go b/snow/engine/avalanche/bootstrap/bootstrapper.go index c6ef6513b668..967d65711abc 100644 --- a/snow/engine/avalanche/bootstrap/bootstrapper.go +++ b/snow/engine/avalanche/bootstrap/bootstrapper.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/avalanche" "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/heap" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" @@ -30,6 +31,10 @@ const ( stripeWidth = 5 cacheSize = 100000 + // statusUpdateFrequency is how many containers should be processed between + // logs + statusUpdateFrequency = 5000 + // maxOutstandingGetAncestorsRequests is the maximum number of GetAncestors // sent but not yet responded to/failed maxOutstandingGetAncestorsRequests = 10 @@ -53,10 +58,10 @@ func New( ChitsHandler: common.NewNoOpChitsHandler(config.Ctx.Log), AppHandler: config.VM, + outstandingRequests: bimap.New[common.Request, ids.ID](), + processedCache: &cache.LRU[ids.ID, struct{}]{Size: cacheSize}, - Fetcher: common.Fetcher{ - OnFinished: onFinished, - }, + onFinished: onFinished, } return b, b.metrics.Initialize("bs", config.Ctx.AvalancheRegisterer) } @@ -77,9 +82,11 @@ type bootstrapper struct { common.ChitsHandler common.AppHandler - common.Fetcher metrics + // tracks which validators were asked for which containers in which requests + outstandingRequests *bimap.BiMap[common.Request, ids.ID] + // IDs of vertices that we will send a GetAncestors request for once we are // not at the max number of outstanding requests needToFetch set.Set[ids.ID] @@ -89,6 +96,9 @@ type bootstrapper struct { // Tracks the last requestID that was used in a request requestID uint32 + + // Called when bootstrapping is done on a specific chain + onFinished func(ctx context.Context, lastReqID uint32) error } func (b *bootstrapper) Context() *snow.ConsensusContext { @@ -133,7 +143,10 @@ func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request vtxs = vtxs[:b.Config.AncestorsMaxContainersReceived] } - requestedVtxID, requested := b.OutstandingRequests.Remove(nodeID, requestID) + requestedVtxID, requested := b.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) vtx, err := b.Manager.ParseVtx(ctx, vtxs[0]) // first vertex should be the one we requested in GetAncestors request if err != nil { if !requested { @@ -173,7 +186,7 @@ func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request ) return b.fetch(ctx, requestedVtxID) } - if !requested && !b.OutstandingRequests.Contains(vtxID) && !b.needToFetch.Contains(vtxID) { + if !requested && !b.outstandingRequests.HasValue(vtxID) && !b.needToFetch.Contains(vtxID) { b.Ctx.Log.Debug("received un-needed vertex", zap.Stringer("nodeID", nodeID), zap.Uint32("requestID", requestID), @@ -240,7 +253,10 @@ func (b *bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, request } func (b *bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - vtxID, ok := b.OutstandingRequests.Remove(nodeID, requestID) + vtxID, ok := b.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) if !ok { b.Ctx.Log.Debug("skipping GetAncestorsFailed call", zap.String("reason", "no matching outstanding request"), @@ -333,7 +349,7 @@ func (b *bootstrapper) Start(ctx context.Context, startReqID uint32) error { return fmt.Errorf("failed to get linearization status: %w", err) } if linearized { - return b.ForceAccepted(ctx, nil) + return b.startSyncing(ctx, nil) } // If a stop vertex is well known, accept that. @@ -342,7 +358,7 @@ func (b *bootstrapper) Start(ctx context.Context, startReqID uint32) error { zap.Stringer("vtxID", b.Config.StopVertexID), ) - return b.ForceAccepted(ctx, []ids.ID{b.Config.StopVertexID}) + return b.startSyncing(ctx, []ids.ID{b.Config.StopVertexID}) } // If a stop vertex isn't well known, treat the current state as the final @@ -364,7 +380,7 @@ func (b *bootstrapper) Start(ctx context.Context, startReqID uint32) error { zap.Stringer("vtxID", stopVertexID), ) - return b.ForceAccepted(ctx, nil) + return b.startSyncing(ctx, nil) } func (b *bootstrapper) HealthCheck(ctx context.Context) (interface{}, error) { @@ -379,21 +395,17 @@ func (b *bootstrapper) HealthCheck(ctx context.Context) (interface{}, error) { return intf, vmErr } -func (b *bootstrapper) GetVM() common.VM { - return b.VM -} - // Add the vertices in [vtxIDs] to the set of vertices that we need to fetch, // and then fetch vertices (and their ancestors) until either there are no more // to fetch or we are at the maximum number of outstanding requests. func (b *bootstrapper) fetch(ctx context.Context, vtxIDs ...ids.ID) error { b.needToFetch.Add(vtxIDs...) - for b.needToFetch.Len() > 0 && b.OutstandingRequests.Len() < maxOutstandingGetAncestorsRequests { + for b.needToFetch.Len() > 0 && b.outstandingRequests.Len() < maxOutstandingGetAncestorsRequests { vtxID := b.needToFetch.CappedList(1)[0] b.needToFetch.Remove(vtxID) // Make sure we haven't already requested this vertex - if b.OutstandingRequests.Contains(vtxID) { + if b.outstandingRequests.HasValue(vtxID) { continue } @@ -409,7 +421,13 @@ func (b *bootstrapper) fetch(ctx context.Context, vtxIDs ...ids.ID) error { validatorID := validatorIDs[0] b.requestID++ - b.OutstandingRequests.Add(validatorID, b.requestID, vtxID) + b.outstandingRequests.Put( + common.Request{ + NodeID: validatorID, + RequestID: b.requestID, + }, + vtxID, + ) b.Config.Sender.SendGetAncestors(ctx, validatorID, b.requestID, vtxID) // request vertex and ancestors } return b.checkFinish(ctx) @@ -494,7 +512,7 @@ func (b *bootstrapper) process(ctx context.Context, vtxs ...avalanche.Vertex) er b.numFetchedVts.Inc() verticesFetchedSoFar := b.VtxBlocked.Jobs.PendingJobs() - if verticesFetchedSoFar%common.StatusUpdateFrequency == 0 { // Periodically print progress + if verticesFetchedSoFar%statusUpdateFrequency == 0 { // Periodically print progress b.Ctx.Log.Info("fetched vertices", zap.Uint64("numVerticesFetched", verticesFetchedSoFar), ) @@ -540,8 +558,8 @@ func (b *bootstrapper) process(ctx context.Context, vtxs ...avalanche.Vertex) er return b.fetch(ctx) } -// ForceAccepted starts bootstrapping. Process the vertices in [accepterContainerIDs]. -func (b *bootstrapper) ForceAccepted(ctx context.Context, acceptedContainerIDs []ids.ID) error { +// startSyncing starts bootstrapping. Process the vertices in [accepterContainerIDs]. +func (b *bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs []ids.ID) error { pendingContainerIDs := b.VtxBlocked.MissingIDs() // Append the list of accepted container IDs to pendingContainerIDs to ensure // we iterate over every container that must be traversed. @@ -606,7 +624,7 @@ func (b *bootstrapper) checkFinish(ctx context.Context) error { } b.processedCache.Flush() - return b.OnFinished(ctx, b.requestID) + return b.onFinished(ctx, b.requestID) } // A vertex is less than another vertex if it is unknown. Ties are broken by diff --git a/snow/engine/avalanche/engine.go b/snow/engine/avalanche/engine.go index 9b828ac05946..375666c99598 100644 --- a/snow/engine/avalanche/engine.go +++ b/snow/engine/avalanche/engine.go @@ -66,10 +66,6 @@ func (e *engine) Context() *snow.ConsensusContext { return e.ctx } -func (e *engine) GetVM() common.VM { - return e.vm -} - func (*engine) HealthCheck(context.Context) (interface{}, error) { return nil, nil } diff --git a/snow/engine/common/bootstrapable.go b/snow/engine/common/bootstrapable.go index a4abcc59a880..256acb6d468e 100644 --- a/snow/engine/common/bootstrapable.go +++ b/snow/engine/common/bootstrapable.go @@ -3,22 +3,10 @@ package common -import ( - "context" - - "github.com/ava-labs/avalanchego/ids" -) +import "context" type BootstrapableEngine interface { - Bootstrapable Engine -} - -// Bootstrapable defines the functionality required to support bootstrapping -type Bootstrapable interface { - // Force the provided containers to be accepted. Only returns fatal errors - // if they occur. - ForceAccepted(ctx context.Context, acceptedContainerIDs []ids.ID) error // Clear removes all containers to be processed upon bootstrapping Clear(ctx context.Context) error diff --git a/snow/engine/common/bootstrapper.go b/snow/engine/common/bootstrapper.go deleted file mode 100644 index d4c8f041a8d2..000000000000 --- a/snow/engine/common/bootstrapper.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package common - -import ( - "context" - - "go.uber.org/zap" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/utils/set" - - smbootstrapper "github.com/ava-labs/avalanchego/snow/consensus/snowman/bootstrapper" -) - -const ( - // StatusUpdateFrequency is how many containers should be processed between - // logs - StatusUpdateFrequency = 5000 - - // MaxOutstandingBroadcastRequests is the maximum number of requests to have - // outstanding when broadcasting. - MaxOutstandingBroadcastRequests = 50 -) - -var _ Bootstrapper = (*bootstrapper)(nil) - -type Bootstrapper interface { - AcceptedFrontierHandler - AcceptedHandler - Haltable - Startup(context.Context) error - Restart(ctx context.Context) error -} - -// It collects mechanisms common to both snowman and avalanche bootstrappers -type bootstrapper struct { - Config - Halter - - minority smbootstrapper.Poll - majority smbootstrapper.Poll -} - -func NewCommonBootstrapper(config Config) Bootstrapper { - return &bootstrapper{ - Config: config, - minority: smbootstrapper.Noop, - majority: smbootstrapper.Noop, - } -} - -func (b *bootstrapper) AcceptedFrontier(ctx context.Context, nodeID ids.NodeID, requestID uint32, containerID ids.ID) error { - if requestID != b.Config.SharedCfg.RequestID { - b.Ctx.Log.Debug("received out-of-sync AcceptedFrontier message", - zap.Stringer("nodeID", nodeID), - zap.Uint32("expectedRequestID", b.Config.SharedCfg.RequestID), - zap.Uint32("requestID", requestID), - ) - return nil - } - - if err := b.minority.RecordOpinion(ctx, nodeID, set.Of(containerID)); err != nil { - return err - } - return b.sendMessagesOrFinish(ctx) -} - -func (b *bootstrapper) GetAcceptedFrontierFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - if requestID != b.Config.SharedCfg.RequestID { - b.Ctx.Log.Debug("received out-of-sync GetAcceptedFrontierFailed message", - zap.Stringer("nodeID", nodeID), - zap.Uint32("expectedRequestID", b.Config.SharedCfg.RequestID), - zap.Uint32("requestID", requestID), - ) - return nil - } - - if err := b.minority.RecordOpinion(ctx, nodeID, nil); err != nil { - return err - } - return b.sendMessagesOrFinish(ctx) -} - -func (b *bootstrapper) Accepted(ctx context.Context, nodeID ids.NodeID, requestID uint32, containerIDs set.Set[ids.ID]) error { - if requestID != b.Config.SharedCfg.RequestID { - b.Ctx.Log.Debug("received out-of-sync Accepted message", - zap.Stringer("nodeID", nodeID), - zap.Uint32("expectedRequestID", b.Config.SharedCfg.RequestID), - zap.Uint32("requestID", requestID), - ) - return nil - } - - if err := b.majority.RecordOpinion(ctx, nodeID, containerIDs); err != nil { - return err - } - return b.sendMessagesOrFinish(ctx) -} - -func (b *bootstrapper) GetAcceptedFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - if requestID != b.Config.SharedCfg.RequestID { - b.Ctx.Log.Debug("received out-of-sync GetAcceptedFailed message", - zap.Stringer("nodeID", nodeID), - zap.Uint32("expectedRequestID", b.Config.SharedCfg.RequestID), - zap.Uint32("requestID", requestID), - ) - return nil - } - - if err := b.majority.RecordOpinion(ctx, nodeID, nil); err != nil { - return err - } - return b.sendMessagesOrFinish(ctx) -} - -func (b *bootstrapper) Startup(ctx context.Context) error { - currentBeacons := b.Beacons.GetMap(b.Ctx.SubnetID) - nodeWeights := make(map[ids.NodeID]uint64, len(currentBeacons)) - for nodeID, beacon := range currentBeacons { - nodeWeights[nodeID] = beacon.Weight - } - - frontierNodes, err := smbootstrapper.Sample(nodeWeights, b.SampleK) - if err != nil { - return err - } - - b.Ctx.Log.Debug("sampled nodes to seed bootstrapping frontier", - zap.Reflect("sampledNodes", frontierNodes), - zap.Int("numNodes", len(nodeWeights)), - ) - - b.minority = smbootstrapper.NewMinority( - b.Ctx.Log, - frontierNodes, - MaxOutstandingBroadcastRequests, - ) - b.majority = smbootstrapper.NewMajority( - b.Ctx.Log, - nodeWeights, - MaxOutstandingBroadcastRequests, - ) - - if accepted, finalized := b.majority.Result(ctx); finalized { - b.Ctx.Log.Info("bootstrapping skipped", - zap.String("reason", "no provided bootstraps"), - ) - return b.Bootstrapable.ForceAccepted(ctx, accepted) - } - - b.Config.SharedCfg.RequestID++ - return b.sendMessagesOrFinish(ctx) -} - -func (b *bootstrapper) Restart(ctx context.Context) error { - b.Ctx.Log.Debug("Checking for new frontiers") - b.Config.SharedCfg.Restarted = true - return b.Startup(ctx) -} - -func (b *bootstrapper) sendMessagesOrFinish(ctx context.Context) error { - if peers := b.minority.GetPeers(ctx); peers.Len() > 0 { - b.Sender.SendGetAcceptedFrontier(ctx, peers, b.Config.SharedCfg.RequestID) - return nil - } - - potentialAccepted, finalized := b.minority.Result(ctx) - if !finalized { - // We haven't finalized the accepted frontier, so we should wait for the - // outstanding requests. - return nil - } - - if peers := b.majority.GetPeers(ctx); peers.Len() > 0 { - b.Sender.SendGetAccepted(ctx, peers, b.Config.SharedCfg.RequestID, potentialAccepted) - return nil - } - - accepted, finalized := b.majority.Result(ctx) - if !finalized { - // We haven't finalized the accepted set, so we should wait for the - // outstanding requests. - return nil - } - - numAccepted := len(accepted) - if numAccepted == 0 { - b.Ctx.Log.Debug("restarting bootstrap", - zap.String("reason", "no blocks accepted"), - zap.Int("numBeacons", b.Beacons.Count(b.Ctx.SubnetID)), - ) - return b.Startup(ctx) - } - - if !b.Config.SharedCfg.Restarted { - b.Ctx.Log.Info("bootstrapping started syncing", - zap.Int("numAccepted", numAccepted), - ) - } else { - b.Ctx.Log.Debug("bootstrapping started syncing", - zap.Int("numAccepted", numAccepted), - ) - } - - return b.Bootstrapable.ForceAccepted(ctx, accepted) -} diff --git a/snow/engine/common/config.go b/snow/engine/common/config.go deleted file mode 100644 index 5ac9052f0593..000000000000 --- a/snow/engine/common/config.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package common - -import ( - "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/snow/engine/common/tracker" - "github.com/ava-labs/avalanchego/snow/validators" -) - -// Config wraps the common configurations that are needed by a Snow consensus -// engine -type Config struct { - Ctx *snow.ConsensusContext - Beacons validators.Manager - - SampleK int - Alpha uint64 - StartupTracker tracker.Startup - Sender Sender - Bootstrapable Bootstrapable - BootstrapTracker BootstrapTracker - Timer Timer - - // This node will only consider the first [AncestorsMaxContainersReceived] - // containers in an ancestors message it receives. - AncestorsMaxContainersReceived int - - SharedCfg *SharedConfig -} - -// Shared among common.bootstrapper and snowman/avalanche bootstrapper -type SharedConfig struct { - // Tracks the last requestID that was used in a request - RequestID uint32 - - // True if RestartBootstrap has been called at least once - Restarted bool -} diff --git a/snow/engine/common/engine.go b/snow/engine/common/engine.go index d92911ff1f7f..e50d94327a30 100644 --- a/snow/engine/common/engine.go +++ b/snow/engine/common/engine.go @@ -32,9 +32,6 @@ type Engine interface { // Returns nil if the engine is healthy. // Periodically called and reported through the health API health.Checker - - // GetVM returns this engine's VM - GetVM() VM } type Handler interface { diff --git a/snow/engine/common/fetcher.go b/snow/engine/common/fetcher.go deleted file mode 100644 index 9e90da3d325b..000000000000 --- a/snow/engine/common/fetcher.go +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package common - -import "context" - -type Fetcher struct { - // tracks which validators were asked for which containers in which requests - OutstandingRequests Requests - - // Called when bootstrapping is done on a specific chain - OnFinished func(ctx context.Context, lastReqID uint32) error -} diff --git a/snow/engine/common/request.go b/snow/engine/common/request.go new file mode 100644 index 000000000000..d677a485c8f4 --- /dev/null +++ b/snow/engine/common/request.go @@ -0,0 +1,11 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package common + +import "github.com/ava-labs/avalanchego/ids" + +type Request struct { + NodeID ids.NodeID + RequestID uint32 +} diff --git a/snow/engine/common/requests.go b/snow/engine/common/requests.go deleted file mode 100644 index ce66585e590d..000000000000 --- a/snow/engine/common/requests.go +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package common - -import ( - "fmt" - "strings" - - "github.com/ava-labs/avalanchego/ids" -) - -const ( - minRequestsSize = 32 -) - -type req struct { - vdr ids.NodeID - id uint32 -} - -// Requests tracks pending container messages from a peer. -type Requests struct { - reqsToID map[ids.NodeID]map[uint32]ids.ID - idToReq map[ids.ID]req -} - -// Add a request. Assumes that requestIDs are unique. Assumes that containerIDs -// are only in one request at a time. -func (r *Requests) Add(vdr ids.NodeID, requestID uint32, containerID ids.ID) { - if r.reqsToID == nil { - r.reqsToID = make(map[ids.NodeID]map[uint32]ids.ID, minRequestsSize) - } - vdrReqs, ok := r.reqsToID[vdr] - if !ok { - vdrReqs = make(map[uint32]ids.ID) - r.reqsToID[vdr] = vdrReqs - } - vdrReqs[requestID] = containerID - - if r.idToReq == nil { - r.idToReq = make(map[ids.ID]req, minRequestsSize) - } - r.idToReq[containerID] = req{ - vdr: vdr, - id: requestID, - } -} - -// Get the containerID the request is expecting and if the request exists. -func (r *Requests) Get(vdr ids.NodeID, requestID uint32) (ids.ID, bool) { - containerID, ok := r.reqsToID[vdr][requestID] - return containerID, ok -} - -// Remove attempts to abandon a requestID sent to a validator. If the request is -// currently outstanding, the requested ID will be returned along with true. If -// the request isn't currently outstanding, false will be returned. -func (r *Requests) Remove(vdr ids.NodeID, requestID uint32) (ids.ID, bool) { - vdrReqs := r.reqsToID[vdr] - containerID, ok := vdrReqs[requestID] - if !ok { - return ids.ID{}, false - } - - if len(vdrReqs) == 1 { - delete(r.reqsToID, vdr) - } else { - delete(vdrReqs, requestID) - } - - delete(r.idToReq, containerID) - return containerID, true -} - -// RemoveAny outstanding requests for the container ID. True is returned if the -// container ID had an outstanding request. -func (r *Requests) RemoveAny(containerID ids.ID) bool { - req, ok := r.idToReq[containerID] - if !ok { - return false - } - - r.Remove(req.vdr, req.id) - return true -} - -// Len returns the total number of outstanding requests. -func (r *Requests) Len() int { - return len(r.idToReq) -} - -// Contains returns true if there is an outstanding request for the container -// ID. -func (r *Requests) Contains(containerID ids.ID) bool { - _, ok := r.idToReq[containerID] - return ok -} - -func (r Requests) String() string { - sb := strings.Builder{} - sb.WriteString(fmt.Sprintf("Requests: (Num Validators = %d)", len(r.reqsToID))) - for vdr, reqs := range r.reqsToID { - sb.WriteString(fmt.Sprintf("\n VDR[%s]: (Outstanding Requests %d)", vdr, len(reqs))) - for reqID, containerID := range reqs { - sb.WriteString(fmt.Sprintf("\n Request[%d]: %s", reqID, containerID)) - } - } - return sb.String() -} diff --git a/snow/engine/common/requests_test.go b/snow/engine/common/requests_test.go deleted file mode 100644 index 73a98e4ccb94..000000000000 --- a/snow/engine/common/requests_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package common - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/avalanchego/ids" -) - -func TestRequests(t *testing.T) { - require := require.New(t) - - req := Requests{} - - require.Empty(req) - - _, removed := req.Remove(ids.EmptyNodeID, 0) - require.False(removed) - - require.False(req.RemoveAny(ids.Empty)) - require.False(req.Contains(ids.Empty)) - - req.Add(ids.EmptyNodeID, 0, ids.Empty) - require.Equal(1, req.Len()) - - _, removed = req.Remove(ids.EmptyNodeID, 1) - require.False(removed) - - _, removed = req.Remove(ids.BuildTestNodeID([]byte{0x01}), 0) - require.False(removed) - - require.True(req.Contains(ids.Empty)) - require.Equal(1, req.Len()) - - req.Add(ids.EmptyNodeID, 10, ids.Empty.Prefix(0)) - require.Equal(2, req.Len()) - - _, removed = req.Remove(ids.EmptyNodeID, 1) - require.False(removed) - - _, removed = req.Remove(ids.BuildTestNodeID([]byte{0x01}), 0) - require.False(removed) - - require.True(req.Contains(ids.Empty)) - require.Equal(2, req.Len()) - - removedID, removed := req.Remove(ids.EmptyNodeID, 0) - require.True(removed) - require.Equal(ids.Empty, removedID) - - removedID, removed = req.Remove(ids.EmptyNodeID, 10) - require.True(removed) - require.Equal(ids.Empty.Prefix(0), removedID) - - require.Zero(req.Len()) - - req.Add(ids.EmptyNodeID, 0, ids.Empty) - require.Equal(1, req.Len()) - - require.True(req.RemoveAny(ids.Empty)) - require.Zero(req.Len()) - - require.False(req.RemoveAny(ids.Empty)) - require.Zero(req.Len()) -} diff --git a/snow/engine/common/test_bootstrapable.go b/snow/engine/common/test_bootstrapable.go deleted file mode 100644 index 625070616377..000000000000 --- a/snow/engine/common/test_bootstrapable.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package common - -import ( - "context" - "errors" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/ava-labs/avalanchego/ids" -) - -var ( - _ Bootstrapable = (*BootstrapableTest)(nil) - - errForceAccepted = errors.New("unexpectedly called ForceAccepted") - errClear = errors.New("unexpectedly called Clear") -) - -// BootstrapableTest is a test engine that supports bootstrapping -type BootstrapableTest struct { - T *testing.T - - CantForceAccepted, CantClear bool - - ClearF func(ctx context.Context) error - ForceAcceptedF func(ctx context.Context, acceptedContainerIDs []ids.ID) error -} - -// Default sets the default on call handling -func (b *BootstrapableTest) Default(cant bool) { - b.CantForceAccepted = cant -} - -func (b *BootstrapableTest) Clear(ctx context.Context) error { - if b.ClearF != nil { - return b.ClearF(ctx) - } - if b.CantClear && b.T != nil { - require.FailNow(b.T, errClear.Error()) - } - return errClear -} - -func (b *BootstrapableTest) ForceAccepted(ctx context.Context, containerIDs []ids.ID) error { - if b.ForceAcceptedF != nil { - return b.ForceAcceptedF(ctx, containerIDs) - } - if b.CantForceAccepted && b.T != nil { - require.FailNow(b.T, errForceAccepted.Error()) - } - return errForceAccepted -} diff --git a/snow/engine/common/test_bootstrapper.go b/snow/engine/common/test_bootstrapper.go index 1f8fd59bf3d3..6ee9e223dc18 100644 --- a/snow/engine/common/test_bootstrapper.go +++ b/snow/engine/common/test_bootstrapper.go @@ -3,18 +3,39 @@ package common +import ( + "context" + "errors" + + "github.com/stretchr/testify/require" +) + var ( - _ Engine = (*BootstrapperTest)(nil) - _ Bootstrapable = (*BootstrapperTest)(nil) + _ BootstrapableEngine = (*BootstrapperTest)(nil) + + errClear = errors.New("unexpectedly called Clear") ) -// EngineTest is a test engine type BootstrapperTest struct { - BootstrapableTest EngineTest + + CantClear bool + + ClearF func(ctx context.Context) error } func (b *BootstrapperTest) Default(cant bool) { - b.BootstrapableTest.Default(cant) b.EngineTest.Default(cant) + + b.CantClear = cant +} + +func (b *BootstrapperTest) Clear(ctx context.Context) error { + if b.ClearF != nil { + return b.ClearF(ctx) + } + if b.CantClear && b.T != nil { + require.FailNow(b.T, errClear.Error()) + } + return errClear } diff --git a/snow/engine/common/test_config.go b/snow/engine/common/test_config.go deleted file mode 100644 index c8cfa7fc76fd..000000000000 --- a/snow/engine/common/test_config.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package common - -import ( - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/snow" - "github.com/ava-labs/avalanchego/snow/engine/common/tracker" - "github.com/ava-labs/avalanchego/snow/validators" - "github.com/ava-labs/avalanchego/utils/constants" -) - -// DefaultConfigTest returns a test configuration -func DefaultConfigTest() Config { - isBootstrapped := false - bootstrapTracker := &BootstrapTrackerTest{ - IsBootstrappedF: func() bool { - return isBootstrapped - }, - BootstrappedF: func(ids.ID) { - isBootstrapped = true - }, - } - - beacons := validators.NewManager() - - connectedPeers := tracker.NewPeers() - startupTracker := tracker.NewStartup(connectedPeers, 0) - beacons.RegisterCallbackListener(constants.PrimaryNetworkID, startupTracker) - - return Config{ - Ctx: snow.DefaultConsensusContextTest(), - Beacons: beacons, - StartupTracker: startupTracker, - Sender: &SenderTest{}, - Bootstrapable: &BootstrapableTest{}, - BootstrapTracker: bootstrapTracker, - Timer: &TimerTest{}, - AncestorsMaxContainersReceived: 2000, - SharedCfg: &SharedConfig{}, - } -} diff --git a/snow/engine/common/test_engine.go b/snow/engine/common/test_engine.go index 3eb376de8e32..0081d63b5753 100644 --- a/snow/engine/common/test_engine.go +++ b/snow/engine/common/test_engine.go @@ -691,16 +691,3 @@ func (e *EngineTest) HealthCheck(ctx context.Context) (interface{}, error) { } return nil, errHealthCheck } - -func (e *EngineTest) GetVM() VM { - if e.GetVMF != nil { - return e.GetVMF() - } - if !e.CantGetVM { - return nil - } - if e.T != nil { - require.FailNow(e.T, "Unexpectedly called GetVM") - } - return nil -} diff --git a/snow/engine/common/traced_bootstrapable_engine.go b/snow/engine/common/traced_bootstrapable_engine.go index ba7a0d89228d..d387df04ac34 100644 --- a/snow/engine/common/traced_bootstrapable_engine.go +++ b/snow/engine/common/traced_bootstrapable_engine.go @@ -6,11 +6,6 @@ package common import ( "context" - "go.opentelemetry.io/otel/attribute" - - oteltrace "go.opentelemetry.io/otel/trace" - - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/trace" ) @@ -29,15 +24,6 @@ func TraceBootstrapableEngine(bootstrapableEngine BootstrapableEngine, tracer tr } } -func (e *tracedBootstrapableEngine) ForceAccepted(ctx context.Context, acceptedContainerIDs []ids.ID) error { - ctx, span := e.tracer.Start(ctx, "tracedBootstrapableEngine.ForceAccepted", oteltrace.WithAttributes( - attribute.Int("numAcceptedContainerIDs", len(acceptedContainerIDs)), - )) - defer span.End() - - return e.bootstrapableEngine.ForceAccepted(ctx, acceptedContainerIDs) -} - func (e *tracedBootstrapableEngine) Clear(ctx context.Context) error { ctx, span := e.tracer.Start(ctx, "tracedBootstrapableEngine.Clear") defer span.End() diff --git a/snow/engine/common/traced_engine.go b/snow/engine/common/traced_engine.go index 9050f29cd1e1..28be03d6df7c 100644 --- a/snow/engine/common/traced_engine.go +++ b/snow/engine/common/traced_engine.go @@ -418,7 +418,3 @@ func (e *tracedEngine) HealthCheck(ctx context.Context) (interface{}, error) { return e.engine.HealthCheck(ctx) } - -func (e *tracedEngine) GetVM() VM { - return e.engine.GetVM() -} diff --git a/snow/engine/snowman/bootstrap/block_job.go b/snow/engine/snowman/bootstrap/block_job.go index 83d86af27d1a..06ae8fbcb84f 100644 --- a/snow/engine/snowman/bootstrap/block_job.go +++ b/snow/engine/snowman/bootstrap/block_job.go @@ -98,7 +98,8 @@ func (b *blockJob) Execute(ctx context.Context) error { b.numAccepted.Inc() b.log.Trace("accepting block in bootstrapping", zap.Stringer("blkID", blkID), - zap.Uint64("blkHeight", b.blk.Height()), + zap.Uint64("height", b.blk.Height()), + zap.Time("timestamp", b.blk.Timestamp()), ) if err := b.blk.Accept(ctx); err != nil { b.log.Debug("failed to accept block during bootstrapping", diff --git a/snow/engine/snowman/bootstrap/bootstrapper.go b/snow/engine/snowman/bootstrap/bootstrapper.go index 5541a98d9e2e..0e2c7e0dab16 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper.go +++ b/snow/engine/snowman/bootstrap/bootstrapper.go @@ -18,15 +18,27 @@ import ( "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" + "github.com/ava-labs/avalanchego/snow/consensus/snowman/bootstrapper" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer" "github.com/ava-labs/avalanchego/version" ) -// Parameters for delaying bootstrapping to avoid potential CPU burns -const bootstrappingDelay = 10 * time.Second +const ( + // Delay bootstrapping to avoid potential CPU burns + bootstrappingDelay = 10 * time.Second + + // statusUpdateFrequency is how many containers should be processed between + // logs + statusUpdateFrequency = 5000 + + // maxOutstandingBroadcastRequests is the maximum number of requests to have + // outstanding when broadcasting. + maxOutstandingBroadcastRequests = 50 +) var ( _ common.BootstrapableEngine = (*Bootstrapper)(nil) @@ -52,6 +64,8 @@ var ( // called, so it must be guaranteed the VM is not used until after Start. type Bootstrapper struct { Config + common.Halter + *metrics // list of NoOpsHandler for messages dropped by bootstrapper common.StateSummaryFrontierHandler @@ -61,21 +75,26 @@ type Bootstrapper struct { common.ChitsHandler common.AppHandler - common.Bootstrapper - common.Fetcher - *metrics + requestID uint32 // Tracks the last requestID that was used in a request - started bool + started bool + restarted bool - // Greatest height of the blocks passed in ForceAccepted + minority bootstrapper.Poll + majority bootstrapper.Poll + + // Greatest height of the blocks passed in startSyncing tipHeight uint64 // Height of the last accepted block when bootstrapping starts startingHeight uint64 - // Number of blocks that were fetched on ForceAccepted + // Number of blocks that were fetched on startSyncing initiallyFetched uint64 - // Time that ForceAccepted was last called + // Time that startSyncing was last called startTime time.Time + // tracks which validators were asked for which containers in which requests + outstandingRequests *bimap.BiMap[common.Request, ids.ID] + // number of state transitions executed executedStateTransitions int @@ -95,15 +114,14 @@ type Bootstrapper struct { // bootstrappedOnce ensures that the [Bootstrapped] callback is only invoked // once, even if bootstrapping is retried. bootstrappedOnce sync.Once + + // Called when bootstrapping is done on a specific chain + onFinished func(ctx context.Context, lastReqID uint32) error } func New(config Config, onFinished func(ctx context.Context, lastReqID uint32) error) (*Bootstrapper, error) { metrics, err := newMetrics("bs", config.Ctx.Registerer) - if err != nil { - return nil, err - } - - b := &Bootstrapper{ + return &Bootstrapper{ Config: config, metrics: metrics, StateSummaryFrontierHandler: common.NewNoOpStateSummaryFrontierHandler(config.Ctx.Log), @@ -113,22 +131,30 @@ func New(config Config, onFinished func(ctx context.Context, lastReqID uint32) e ChitsHandler: common.NewNoOpChitsHandler(config.Ctx.Log), AppHandler: config.VM, - Fetcher: common.Fetcher{ - OnFinished: onFinished, - }, - executedStateTransitions: math.MaxInt32, - } + minority: bootstrapper.Noop, + majority: bootstrapper.Noop, - config.Bootstrapable = b - b.Bootstrapper = common.NewCommonBootstrapper(config.Config) + outstandingRequests: bimap.New[common.Request, ids.ID](), - return b, nil + executedStateTransitions: math.MaxInt, + onFinished: onFinished, + }, err } func (b *Bootstrapper) Context() *snow.ConsensusContext { return b.Ctx } +func (b *Bootstrapper) Clear(context.Context) error { + b.Ctx.Lock.Lock() + defer b.Ctx.Lock.Unlock() + + if err := b.Config.Blocked.Clear(); err != nil { + return err + } + return b.Config.Blocked.Commit() +} + func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { b.Ctx.Log.Info("starting bootstrapper") @@ -161,7 +187,7 @@ func (b *Bootstrapper) Start(ctx context.Context, startReqID uint32) error { return fmt.Errorf("couldn't get last accepted block: %w", err) } b.startingHeight = lastAccepted.Height() - b.Config.SharedCfg.RequestID = startReqID + b.requestID = startReqID return b.tryStartBootstrapping(ctx) } @@ -203,164 +229,176 @@ func (b *Bootstrapper) tryStartBootstrapping(ctx context.Context) error { } b.started = true - return b.Startup(ctx) + return b.startBootstrapping(ctx) } -// Ancestors handles the receipt of multiple containers. Should be received in -// response to a GetAncestors message to [nodeID] with request ID [requestID] -func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { - // Make sure this is in response to a request we made - wantedBlkID, ok := b.OutstandingRequests.Remove(nodeID, requestID) - if !ok { // this message isn't in response to a request we made - b.Ctx.Log.Debug("received unexpected Ancestors", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - ) - return nil +func (b *Bootstrapper) startBootstrapping(ctx context.Context) error { + currentBeacons := b.Beacons.GetMap(b.Ctx.SubnetID) + nodeWeights := make(map[ids.NodeID]uint64, len(currentBeacons)) + for nodeID, beacon := range currentBeacons { + nodeWeights[nodeID] = beacon.Weight } - lenBlks := len(blks) - if lenBlks == 0 { - b.Ctx.Log.Debug("received Ancestors with no block", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), + frontierNodes, err := bootstrapper.Sample(nodeWeights, b.SampleK) + if err != nil { + return err + } + + b.Ctx.Log.Debug("sampled nodes to seed bootstrapping frontier", + zap.Reflect("sampledNodes", frontierNodes), + zap.Int("numNodes", len(nodeWeights)), + ) + + b.minority = bootstrapper.NewMinority( + b.Ctx.Log, + frontierNodes, + maxOutstandingBroadcastRequests, + ) + b.majority = bootstrapper.NewMajority( + b.Ctx.Log, + nodeWeights, + maxOutstandingBroadcastRequests, + ) + + if accepted, finalized := b.majority.Result(ctx); finalized { + b.Ctx.Log.Info("bootstrapping skipped", + zap.String("reason", "no provided bootstraps"), ) + return b.startSyncing(ctx, accepted) + } - b.markUnavailable(nodeID) + b.requestID++ + return b.sendBootstrappingMessagesOrFinish(ctx) +} - // Send another request for this - return b.fetch(ctx, wantedBlkID) +func (b *Bootstrapper) sendBootstrappingMessagesOrFinish(ctx context.Context) error { + if peers := b.minority.GetPeers(ctx); peers.Len() > 0 { + b.Sender.SendGetAcceptedFrontier(ctx, peers, b.requestID) + return nil } - // This node has responded - so add it back into the set - b.fetchFrom.Add(nodeID) + potentialAccepted, finalized := b.minority.Result(ctx) + if !finalized { + // We haven't finalized the accepted frontier, so we should wait for the + // outstanding requests. + return nil + } - if lenBlks > b.Config.AncestorsMaxContainersReceived { - blks = blks[:b.Config.AncestorsMaxContainersReceived] - b.Ctx.Log.Debug("ignoring containers in Ancestors", - zap.Int("numContainers", lenBlks-b.Config.AncestorsMaxContainersReceived), - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - ) + if peers := b.majority.GetPeers(ctx); peers.Len() > 0 { + b.Sender.SendGetAccepted(ctx, peers, b.requestID, potentialAccepted) + return nil } - blocks, err := block.BatchedParseBlock(ctx, b.VM, blks) - if err != nil { // the provided blocks couldn't be parsed - b.Ctx.Log.Debug("failed to parse blocks in Ancestors", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - zap.Error(err), - ) - return b.fetch(ctx, wantedBlkID) + accepted, finalized := b.majority.Result(ctx) + if !finalized { + // We haven't finalized the accepted set, so we should wait for the + // outstanding requests. + return nil } - if len(blocks) == 0 { - b.Ctx.Log.Debug("parsing blocks returned an empty set of blocks", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), + numAccepted := len(accepted) + if numAccepted == 0 { + b.Ctx.Log.Debug("restarting bootstrap", + zap.String("reason", "no blocks accepted"), + zap.Int("numBeacons", b.Beacons.Count(b.Ctx.SubnetID)), ) - return b.fetch(ctx, wantedBlkID) + // Invariant: These functions are mutualy recursive. However, when + // [startBootstrapping] calls [sendMessagesOrFinish], it is guaranteed + // to exit when sending GetAcceptedFrontier requests. + return b.startBootstrapping(ctx) } - requestedBlock := blocks[0] - if actualID := requestedBlock.ID(); actualID != wantedBlkID { - b.Ctx.Log.Debug("first block is not the requested block", - zap.Stringer("expectedBlkID", wantedBlkID), - zap.Stringer("blkID", actualID), + if !b.restarted { + b.Ctx.Log.Info("bootstrapping started syncing", + zap.Int("numAccepted", numAccepted), + ) + } else { + b.Ctx.Log.Debug("bootstrapping started syncing", + zap.Int("numAccepted", numAccepted), ) - return b.fetch(ctx, wantedBlkID) } - blockSet := make(map[ids.ID]snowman.Block, len(blocks)) - for _, block := range blocks[1:] { - blockSet[block.ID()] = block - } - return b.process(ctx, requestedBlock, blockSet) + return b.startSyncing(ctx, accepted) } -func (b *Bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - blkID, ok := b.OutstandingRequests.Remove(nodeID, requestID) - if !ok { - b.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", +func (b *Bootstrapper) AcceptedFrontier(ctx context.Context, nodeID ids.NodeID, requestID uint32, containerID ids.ID) error { + if requestID != b.requestID { + b.Ctx.Log.Debug("received out-of-sync AcceptedFrontier message", zap.Stringer("nodeID", nodeID), + zap.Uint32("expectedRequestID", b.requestID), zap.Uint32("requestID", requestID), ) return nil } - // This node timed out their request, so we can add them back to [fetchFrom] - b.fetchFrom.Add(nodeID) - - // Send another request for this - return b.fetch(ctx, blkID) + if err := b.minority.RecordOpinion(ctx, nodeID, set.Of(containerID)); err != nil { + return err + } + return b.sendBootstrappingMessagesOrFinish(ctx) } -func (b *Bootstrapper) Timeout(ctx context.Context) error { - if !b.awaitingTimeout { - return errUnexpectedTimeout +func (b *Bootstrapper) GetAcceptedFrontierFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { + if requestID != b.requestID { + b.Ctx.Log.Debug("received out-of-sync GetAcceptedFrontierFailed message", + zap.Stringer("nodeID", nodeID), + zap.Uint32("expectedRequestID", b.requestID), + zap.Uint32("requestID", requestID), + ) + return nil } - b.awaitingTimeout = false - if !b.Config.BootstrapTracker.IsBootstrapped() { - return b.Restart(ctx) + if err := b.minority.RecordOpinion(ctx, nodeID, nil); err != nil { + return err } - b.fetchETA.Set(0) - return b.OnFinished(ctx, b.Config.SharedCfg.RequestID) -} - -func (*Bootstrapper) Gossip(context.Context) error { - return nil + return b.sendBootstrappingMessagesOrFinish(ctx) } -func (b *Bootstrapper) Shutdown(ctx context.Context) error { - b.Ctx.Log.Info("shutting down bootstrapper") - - b.Ctx.Lock.Lock() - defer b.Ctx.Lock.Unlock() +func (b *Bootstrapper) Accepted(ctx context.Context, nodeID ids.NodeID, requestID uint32, containerIDs set.Set[ids.ID]) error { + if requestID != b.requestID { + b.Ctx.Log.Debug("received out-of-sync Accepted message", + zap.Stringer("nodeID", nodeID), + zap.Uint32("expectedRequestID", b.requestID), + zap.Uint32("requestID", requestID), + ) + return nil + } - return b.VM.Shutdown(ctx) + if err := b.majority.RecordOpinion(ctx, nodeID, containerIDs); err != nil { + return err + } + return b.sendBootstrappingMessagesOrFinish(ctx) } -func (b *Bootstrapper) Notify(_ context.Context, msg common.Message) error { - if msg != common.StateSyncDone { - b.Ctx.Log.Warn("received an unexpected message from the VM", - zap.Stringer("msg", msg), +func (b *Bootstrapper) GetAcceptedFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { + if requestID != b.requestID { + b.Ctx.Log.Debug("received out-of-sync GetAcceptedFailed message", + zap.Stringer("nodeID", nodeID), + zap.Uint32("expectedRequestID", b.requestID), + zap.Uint32("requestID", requestID), ) return nil } - return nil -} - -func (b *Bootstrapper) HealthCheck(ctx context.Context) (interface{}, error) { - b.Ctx.Lock.Lock() - defer b.Ctx.Lock.Unlock() - vmIntf, vmErr := b.VM.HealthCheck(ctx) - intf := map[string]interface{}{ - "consensus": struct{}{}, - "vm": vmIntf, + if err := b.majority.RecordOpinion(ctx, nodeID, nil); err != nil { + return err } - return intf, vmErr + return b.sendBootstrappingMessagesOrFinish(ctx) } -func (b *Bootstrapper) GetVM() common.VM { - return b.VM -} - -func (b *Bootstrapper) ForceAccepted(ctx context.Context, acceptedContainerIDs []ids.ID) error { - pendingContainerIDs := b.Blocked.MissingIDs() - +func (b *Bootstrapper) startSyncing(ctx context.Context, acceptedContainerIDs []ids.ID) error { // Initialize the fetch from set to the currently preferred peers b.fetchFrom = b.StartupTracker.PreferredPeers() + pendingContainerIDs := b.Blocked.MissingIDs() // Append the list of accepted container IDs to pendingContainerIDs to ensure // we iterate over every container that must be traversed. pendingContainerIDs = append(pendingContainerIDs, acceptedContainerIDs...) - toProcess := make([]snowman.Block, 0, len(pendingContainerIDs)) b.Ctx.Log.Debug("starting bootstrapping", zap.Int("numPendingBlocks", len(pendingContainerIDs)), zap.Int("numAcceptedBlocks", len(acceptedContainerIDs)), ) + + toProcess := make([]snowman.Block, 0, len(pendingContainerIDs)) for _, blkID := range pendingContainerIDs { b.Blocked.AddMissingID(blkID) @@ -386,19 +424,19 @@ func (b *Bootstrapper) ForceAccepted(ctx context.Context, acceptedContainerIDs [ } } - return b.checkFinish(ctx) + return b.tryStartExecuting(ctx) } // Get block [blkID] and its ancestors from a validator func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { // Make sure we haven't already requested this block - if b.OutstandingRequests.Contains(blkID) { + if b.outstandingRequests.HasValue(blkID) { return nil } // Make sure we don't already have this block if _, err := b.VM.GetBlock(ctx, blkID); err == nil { - return b.checkFinish(ctx) + return b.tryStartExecuting(ctx) } validatorID, ok := b.fetchFrom.Peek() @@ -409,13 +447,114 @@ func (b *Bootstrapper) fetch(ctx context.Context, blkID ids.ID) error { // We only allow one outbound request at a time from a node b.markUnavailable(validatorID) - b.Config.SharedCfg.RequestID++ + b.requestID++ - b.OutstandingRequests.Add(validatorID, b.Config.SharedCfg.RequestID, blkID) - b.Config.Sender.SendGetAncestors(ctx, validatorID, b.Config.SharedCfg.RequestID, blkID) // request block and ancestors + b.outstandingRequests.Put( + common.Request{ + NodeID: validatorID, + RequestID: b.requestID, + }, + blkID, + ) + b.Config.Sender.SendGetAncestors(ctx, validatorID, b.requestID, blkID) // request block and ancestors return nil } +// Ancestors handles the receipt of multiple containers. Should be received in +// response to a GetAncestors message to [nodeID] with request ID [requestID] +func (b *Bootstrapper) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { + // Make sure this is in response to a request we made + wantedBlkID, ok := b.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) + if !ok { // this message isn't in response to a request we made + b.Ctx.Log.Debug("received unexpected Ancestors", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return nil + } + + lenBlks := len(blks) + if lenBlks == 0 { + b.Ctx.Log.Debug("received Ancestors with no block", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + + b.markUnavailable(nodeID) + + // Send another request for this + return b.fetch(ctx, wantedBlkID) + } + + // This node has responded - so add it back into the set + b.fetchFrom.Add(nodeID) + + if lenBlks > b.Config.AncestorsMaxContainersReceived { + blks = blks[:b.Config.AncestorsMaxContainersReceived] + b.Ctx.Log.Debug("ignoring containers in Ancestors", + zap.Int("numContainers", lenBlks-b.Config.AncestorsMaxContainersReceived), + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + } + + blocks, err := block.BatchedParseBlock(ctx, b.VM, blks) + if err != nil { // the provided blocks couldn't be parsed + b.Ctx.Log.Debug("failed to parse blocks in Ancestors", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + zap.Error(err), + ) + return b.fetch(ctx, wantedBlkID) + } + + if len(blocks) == 0 { + b.Ctx.Log.Debug("parsing blocks returned an empty set of blocks", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return b.fetch(ctx, wantedBlkID) + } + + requestedBlock := blocks[0] + if actualID := requestedBlock.ID(); actualID != wantedBlkID { + b.Ctx.Log.Debug("first block is not the requested block", + zap.Stringer("expectedBlkID", wantedBlkID), + zap.Stringer("blkID", actualID), + ) + return b.fetch(ctx, wantedBlkID) + } + + blockSet := make(map[ids.ID]snowman.Block, len(blocks)) + for _, block := range blocks[1:] { + blockSet[block.ID()] = block + } + return b.process(ctx, requestedBlock, blockSet) +} + +func (b *Bootstrapper) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { + blkID, ok := b.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) + if !ok { + b.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + ) + return nil + } + + // This node timed out their request, so we can add them back to [fetchFrom] + b.fetchFrom.Add(nodeID) + + // Send another request for this + return b.fetch(ctx, blkID) +} + // markUnavailable removes [nodeID] from the set of peers used to fetch // ancestors. If the set becomes empty, it is reset to the currently preferred // peers so bootstrapping can continue. @@ -429,16 +568,6 @@ func (b *Bootstrapper) markUnavailable(nodeID ids.NodeID) { } } -func (b *Bootstrapper) Clear(context.Context) error { - b.Ctx.Lock.Lock() - defer b.Ctx.Lock.Unlock() - - if err := b.Config.Blocked.Clear(); err != nil { - return err - } - return b.Config.Blocked.Commit() -} - // process a series of consecutive blocks starting at [blk]. // // - blk is a block that is assumed to have been marked as acceptable by the @@ -475,7 +604,7 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin if err := b.Blocked.Commit(); err != nil { return err } - return b.checkFinish(ctx) + return b.tryStartExecuting(ctx) } // If this block is going to be accepted, make sure to update the @@ -501,7 +630,7 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin if err := b.Blocked.Commit(); err != nil { return err } - return b.checkFinish(ctx) + return b.tryStartExecuting(ctx) } // We added a new block to the queue, so track that it was fetched @@ -509,7 +638,7 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin // Periodically log progress blocksFetchedSoFar := b.Blocked.Jobs.PendingJobs() - if blocksFetchedSoFar%common.StatusUpdateFrequency == 0 { + if blocksFetchedSoFar%statusUpdateFrequency == 0 { totalBlocksToFetch := b.tipHeight - b.startingHeight eta := timer.EstimateETA( b.startTime, @@ -518,7 +647,7 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin ) b.fetchETA.Set(float64(eta)) - if !b.Config.SharedCfg.Restarted { + if !b.restarted { b.Ctx.Log.Info("fetching blocks", zap.Uint64("numFetchedBlocks", blocksFetchedSoFar), zap.Uint64("numTotalBlocks", totalBlocksToFetch), @@ -562,13 +691,14 @@ func (b *Bootstrapper) process(ctx context.Context, blk snowman.Block, processin if err := b.Blocked.Commit(); err != nil { return err } - return b.checkFinish(ctx) + return b.tryStartExecuting(ctx) } } -// checkFinish repeatedly executes pending transactions and requests new frontier vertices until there aren't any new ones -// after which it finishes the bootstrap process -func (b *Bootstrapper) checkFinish(ctx context.Context) error { +// tryStartExecuting executes all pending blocks if there are no more blocks +// being fetched. After executing all pending blocks it will either restart +// bootstrapping, or transition into normal operations. +func (b *Bootstrapper) tryStartExecuting(ctx context.Context) error { if numPending := b.Blocked.NumMissingIDs(); numPending != 0 { return nil } @@ -577,7 +707,7 @@ func (b *Bootstrapper) checkFinish(ctx context.Context) error { return nil } - if !b.Config.SharedCfg.Restarted { + if !b.restarted { b.Ctx.Log.Info("executing blocks", zap.Uint64("numPendingJobs", b.Blocked.PendingJobs()), ) @@ -591,7 +721,7 @@ func (b *Bootstrapper) checkFinish(ctx context.Context) error { ctx, b.Config.Ctx, b, - b.Config.SharedCfg.Restarted, + b.restarted, b.Ctx.BlockAcceptor, ) if err != nil || b.Halted() { @@ -605,7 +735,7 @@ func (b *Bootstrapper) checkFinish(ctx context.Context) error { // so that the bootstrapping process will terminate even as new blocks are // being issued. if executedBlocks > 0 && executedBlocks < previouslyExecuted/2 { - return b.Restart(ctx) + return b.restartBootstrapping(ctx) } // If there is an additional callback, notify them that this chain has been @@ -620,7 +750,7 @@ func (b *Bootstrapper) checkFinish(ctx context.Context) error { // If the subnet hasn't finished bootstrapping, this chain should remain // syncing. if !b.Config.BootstrapTracker.IsBootstrapped() { - if !b.Config.SharedCfg.Restarted { + if !b.restarted { b.Ctx.Log.Info("waiting for the remaining chains in this subnet to finish syncing") } else { b.Ctx.Log.Debug("waiting for the remaining chains in this subnet to finish syncing") @@ -632,5 +762,61 @@ func (b *Bootstrapper) checkFinish(ctx context.Context) error { return nil } b.fetchETA.Set(0) - return b.OnFinished(ctx, b.Config.SharedCfg.RequestID) + return b.onFinished(ctx, b.requestID) +} + +func (b *Bootstrapper) Timeout(ctx context.Context) error { + if !b.awaitingTimeout { + return errUnexpectedTimeout + } + b.awaitingTimeout = false + + if !b.Config.BootstrapTracker.IsBootstrapped() { + return b.restartBootstrapping(ctx) + } + b.fetchETA.Set(0) + return b.onFinished(ctx, b.requestID) +} + +func (b *Bootstrapper) restartBootstrapping(ctx context.Context) error { + b.Ctx.Log.Debug("Checking for new frontiers") + b.restarted = true + return b.startBootstrapping(ctx) +} + +func (b *Bootstrapper) Notify(_ context.Context, msg common.Message) error { + if msg != common.StateSyncDone { + b.Ctx.Log.Warn("received an unexpected message from the VM", + zap.Stringer("msg", msg), + ) + return nil + } + + b.Ctx.StateSyncing.Set(false) + return nil +} + +func (b *Bootstrapper) HealthCheck(ctx context.Context) (interface{}, error) { + b.Ctx.Lock.Lock() + defer b.Ctx.Lock.Unlock() + + vmIntf, vmErr := b.VM.HealthCheck(ctx) + intf := map[string]interface{}{ + "consensus": struct{}{}, + "vm": vmIntf, + } + return intf, vmErr +} + +func (b *Bootstrapper) Shutdown(ctx context.Context) error { + b.Ctx.Log.Info("shutting down bootstrapper") + + b.Ctx.Lock.Lock() + defer b.Ctx.Lock.Unlock() + + return b.VM.Shutdown(ctx) +} + +func (*Bootstrapper) Gossip(context.Context) error { + return nil } diff --git a/snow/engine/snowman/bootstrap/bootstrapper_test.go b/snow/engine/snowman/bootstrap/bootstrapper_test.go index c883de181323..83cbca730ba5 100644 --- a/snow/engine/snowman/bootstrap/bootstrapper_test.go +++ b/snow/engine/snowman/bootstrap/bootstrapper_test.go @@ -75,28 +75,22 @@ func newConfig(t *testing.T) (Config, ids.NodeID, *common.SenderTest, *block.Tes require.NoError(startupTracker.Connected(context.Background(), peer, version.CurrentApp)) - commonConfig := common.Config{ + snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) + require.NoError(err) + + blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) + return Config{ + AllGetsServer: snowGetHandler, Ctx: ctx, Beacons: vdrs, SampleK: vdrs.Count(ctx.SubnetID), - Alpha: totalWeight/2 + 1, StartupTracker: startupTracker, Sender: sender, BootstrapTracker: bootstrapTracker, Timer: &common.TimerTest{}, AncestorsMaxContainersReceived: 2000, - SharedCfg: &common.SharedConfig{}, - } - - snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) - require.NoError(err) - - blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) - return Config{ - Config: commonConfig, - AllGetsServer: snowGetHandler, - Blocked: blocker, - VM: vm, + Blocked: blocker, + VM: vm, }, peer, sender, vm } @@ -121,27 +115,21 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { startupTracker := tracker.NewStartup(peerTracker, startupAlpha) peers.RegisterCallbackListener(ctx.SubnetID, startupTracker) - commonCfg := common.Config{ + blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) + snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) + require.NoError(err) + cfg := Config{ + AllGetsServer: snowGetHandler, Ctx: ctx, Beacons: peers, SampleK: sampleK, - Alpha: alpha, StartupTracker: startupTracker, Sender: sender, BootstrapTracker: &common.BootstrapTrackerTest{}, Timer: &common.TimerTest{}, AncestorsMaxContainersReceived: 2000, - SharedCfg: &common.SharedConfig{}, - } - - blocker, _ := queue.NewWithMissing(memdb.New(), "", prometheus.NewRegistry()) - snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) - require.NoError(err) - cfg := Config{ - Config: commonCfg, - AllGetsServer: snowGetHandler, - Blocked: blocker, - VM: vm, + Blocked: blocker, + VM: vm, } blkID0 := ids.Empty.Prefix(0) @@ -192,7 +180,7 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { // attempt starting bootstrapper with not enough stake connected. Bootstrapper should stall. vdr0 := ids.GenerateTestNodeID() - require.NoError(peers.AddStaker(commonCfg.Ctx.SubnetID, vdr0, nil, ids.Empty, startupAlpha/2)) + require.NoError(peers.AddStaker(ctx.SubnetID, vdr0, nil, ids.Empty, startupAlpha/2)) require.NoError(bs.Connected(context.Background(), vdr0, version.CurrentApp)) require.NoError(bs.Start(context.Background(), 0)) @@ -200,7 +188,7 @@ func TestBootstrapperStartsOnlyIfEnoughStakeIsConnected(t *testing.T) { // finally attempt starting bootstrapper with enough stake connected. Frontiers should be requested. vdr := ids.GenerateTestNodeID() - require.NoError(peers.AddStaker(commonCfg.Ctx.SubnetID, vdr, nil, ids.Empty, startupAlpha)) + require.NoError(peers.AddStaker(ctx.SubnetID, vdr, nil, ids.Empty, startupAlpha)) require.NoError(bs.Connected(context.Background(), vdr, version.CurrentApp)) require.True(frontierRequested) } @@ -283,7 +271,7 @@ func TestBootstrapperSingleFrontier(t *testing.T) { return nil, errUnknownBlock } - require.NoError(bs.ForceAccepted(context.Background(), acceptedIDs)) + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) require.Equal(choices.Accepted, blk1.Status()) } @@ -396,7 +384,7 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { } vm.CantSetState = false - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blkID2})) // should request blk1 + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID2})) // should request blk1 oldReqID := requestID require.NoError(bs.Ancestors(context.Background(), peerID, requestID, [][]byte{blkBytes0})) // respond with wrong block @@ -409,7 +397,7 @@ func TestBootstrapperUnknownByzantineResponse(t *testing.T) { require.Equal(choices.Accepted, blk1.Status()) require.Equal(choices.Accepted, blk2.Status()) - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blkID2})) + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID2})) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -542,7 +530,7 @@ func TestBootstrapperPartialFetch(t *testing.T) { requested = blkID } - require.NoError(bs.ForceAccepted(context.Background(), acceptedIDs)) // should request blk2 + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk2 require.NoError(bs.Ancestors(context.Background(), peerID, *requestID, [][]byte{blkBytes2})) // respond with blk2 require.Equal(blkID1, requested) @@ -555,7 +543,7 @@ func TestBootstrapperPartialFetch(t *testing.T) { require.Equal(choices.Accepted, blk1.Status()) require.Equal(choices.Accepted, blk2.Status()) - require.NoError(bs.ForceAccepted(context.Background(), acceptedIDs)) + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -690,7 +678,7 @@ func TestBootstrapperEmptyResponse(t *testing.T) { } // should request blk2 - require.NoError(bs.ForceAccepted(context.Background(), acceptedIDs)) + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) require.Equal(peerID, requestedVdr) require.Equal(blkID2, requestedBlock) @@ -851,7 +839,7 @@ func TestBootstrapperAncestors(t *testing.T) { requested = blkID } - require.NoError(bs.ForceAccepted(context.Background(), acceptedIDs)) // should request blk2 + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) // should request blk2 require.NoError(bs.Ancestors(context.Background(), peerID, *requestID, [][]byte{blkBytes2, blkBytes1})) // respond with blk2 and blk1 require.Equal(blkID2, requested) @@ -860,7 +848,7 @@ func TestBootstrapperAncestors(t *testing.T) { require.Equal(choices.Accepted, blk1.Status()) require.Equal(choices.Accepted, blk2.Status()) - require.NoError(bs.ForceAccepted(context.Background(), acceptedIDs)) + require.NoError(bs.startSyncing(context.Background(), acceptedIDs)) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -971,7 +959,7 @@ func TestBootstrapperFinalized(t *testing.T) { requestIDs[blkID] = reqID } - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blkID1, blkID2})) // should request blk2 and blk1 + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID1, blkID2})) // should request blk2 and blk1 reqIDBlk2, ok := requestIDs[blkID2] require.True(ok) @@ -983,7 +971,7 @@ func TestBootstrapperFinalized(t *testing.T) { require.Equal(choices.Accepted, blk1.Status()) require.Equal(choices.Accepted, blk2.Status()) - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blkID2})) + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID2})) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -1133,7 +1121,7 @@ func TestRestartBootstrapping(t *testing.T) { } // Force Accept blk3 - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blkID3})) // should request blk3 + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID3})) // should request blk3 reqID, ok := requestIDs[blkID3] require.True(ok) @@ -1142,11 +1130,12 @@ func TestRestartBootstrapping(t *testing.T) { require.Contains(requestIDs, blkID1) - // Remove request, so we can restart bootstrapping via ForceAccepted - require.True(bs.OutstandingRequests.RemoveAny(blkID1)) + // Remove request, so we can restart bootstrapping via startSyncing + _, removed := bs.outstandingRequests.DeleteValue(blkID1) + require.True(removed) requestIDs = map[ids.ID]uint32{} - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blkID4})) + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID4})) blk1RequestID, ok := requestIDs[blkID1] require.True(ok) @@ -1166,7 +1155,7 @@ func TestRestartBootstrapping(t *testing.T) { require.Equal(choices.Accepted, blk3.Status()) require.Equal(choices.Accepted, blk4.Status()) - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blkID4})) + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blkID4})) require.Equal(snow.NormalOp, config.Ctx.State.Get().State) } @@ -1240,7 +1229,7 @@ func TestBootstrapOldBlockAfterStateSync(t *testing.T) { } // Force Accept, the already transitively accepted, blk0 - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blk0.ID()})) // should request blk0 + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blk0.ID()})) // should request blk0 reqID, ok := requestIDs[blk0.ID()] require.True(ok) @@ -1317,7 +1306,7 @@ func TestBootstrapContinueAfterHalt(t *testing.T) { vm.CantSetState = false require.NoError(bs.Start(context.Background(), 0)) - require.NoError(bs.ForceAccepted(context.Background(), []ids.ID{blk2.ID()})) + require.NoError(bs.startSyncing(context.Background(), []ids.ID{blk2.ID()})) require.Equal(1, bs.Blocked.NumMissingIDs()) } @@ -1360,19 +1349,6 @@ func TestBootstrapNoParseOnNew(t *testing.T) { peers.RegisterCallbackListener(ctx.SubnetID, startupTracker) require.NoError(startupTracker.Connected(context.Background(), peer, version.CurrentApp)) - commonConfig := common.Config{ - Ctx: ctx, - Beacons: peers, - SampleK: peers.Count(ctx.SubnetID), - Alpha: totalWeight/2 + 1, - StartupTracker: startupTracker, - Sender: sender, - BootstrapTracker: bootstrapTracker, - Timer: &common.TimerTest{}, - AncestorsMaxContainersReceived: 2000, - SharedCfg: &common.SharedConfig{}, - } - snowGetHandler, err := getter.New(vm, sender, ctx.Log, time.Second, 2000, ctx.Registerer) require.NoError(err) @@ -1422,10 +1398,17 @@ func TestBootstrapNoParseOnNew(t *testing.T) { require.NoError(err) config := Config{ - Config: commonConfig, - AllGetsServer: snowGetHandler, - Blocked: blocker, - VM: vm, + AllGetsServer: snowGetHandler, + Ctx: ctx, + Beacons: peers, + SampleK: peers.Count(ctx.SubnetID), + StartupTracker: startupTracker, + Sender: sender, + BootstrapTracker: bootstrapTracker, + Timer: &common.TimerTest{}, + AncestorsMaxContainersReceived: 2000, + Blocked: blocker, + VM: vm, } _, err = New( diff --git a/snow/engine/snowman/bootstrap/config.go b/snow/engine/snowman/bootstrap/config.go index 0c05feb7dfa5..785654cb72dc 100644 --- a/snow/engine/snowman/bootstrap/config.go +++ b/snow/engine/snowman/bootstrap/config.go @@ -4,15 +4,30 @@ package bootstrap import ( + "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/snow/engine/common/queue" + "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" + "github.com/ava-labs/avalanchego/snow/validators" ) type Config struct { - common.Config common.AllGetsServer + Ctx *snow.ConsensusContext + Beacons validators.Manager + + SampleK int + StartupTracker tracker.Startup + Sender common.Sender + BootstrapTracker common.BootstrapTracker + Timer common.Timer + + // This node will only consider the first [AncestorsMaxContainersReceived] + // containers in an ancestors message it receives. + AncestorsMaxContainersReceived int + // Blocked tracks operations that are blocked on blocks // // It should be guaranteed that `MissingIDs` should contain all IDs diff --git a/snow/engine/snowman/config_test.go b/snow/engine/snowman/config_test.go index 325db778f056..1d649bed99bd 100644 --- a/snow/engine/snowman/config_test.go +++ b/snow/engine/snowman/config_test.go @@ -4,20 +4,24 @@ package snowman import ( + "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/consensus/snowball" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/snow/engine/common" + "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" ) -func DefaultConfigs() Config { - commonCfg := common.DefaultConfigTest() +func DefaultConfig() Config { + connectedPeers := tracker.NewPeers() + startupTracker := tracker.NewStartup(connectedPeers, 0) + return Config{ - Ctx: commonCfg.Ctx, - Sender: commonCfg.Sender, - Validators: validators.NewManager(), + Ctx: snow.DefaultConsensusContextTest(), VM: &block.TestVM{}, + Sender: &common.SenderTest{}, + Validators: validators.NewManager(), Params: snowball.Parameters{ K: 1, AlphaPreference: 1, @@ -31,7 +35,7 @@ func DefaultConfigs() Config { }, Consensus: &snowman.Topological{}, - Peers: commonCfg.StartupTracker, + Peers: startupTracker, AncestorsMaxContainersSent: 2000, AncestorsMaxContainersReceived: 2000, } diff --git a/snow/engine/snowman/issuer.go b/snow/engine/snowman/issuer.go index ca69064105e1..3558d47360dc 100644 --- a/snow/engine/snowman/issuer.go +++ b/snow/engine/snowman/issuer.go @@ -6,6 +6,8 @@ package snowman import ( "context" + "github.com/prometheus/client_golang/prometheus" + "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/utils/set" @@ -13,11 +15,13 @@ import ( // issuer issues [blk] into to consensus after its dependencies are met. type issuer struct { - t *Transitive - blk snowman.Block - abandoned bool - deps set.Set[ids.ID] - push bool + t *Transitive + nodeID ids.NodeID // nodeID of the peer that provided this block + blk snowman.Block + issuedMetric prometheus.Counter + abandoned bool + deps set.Set[ids.ID] + push bool } func (i *issuer) Dependencies() set.Set[ids.ID] { @@ -51,5 +55,5 @@ func (i *issuer) Update(ctx context.Context) { return } // Issue the block into consensus - i.t.errs.Add(i.t.deliver(ctx, i.blk, i.push)) + i.t.errs.Add(i.t.deliver(ctx, i.nodeID, i.blk, i.push, i.issuedMetric)) } diff --git a/snow/engine/snowman/metrics.go b/snow/engine/snowman/metrics.go index ae7cc66cfbfb..dfdc92c636db 100644 --- a/snow/engine/snowman/metrics.go +++ b/snow/engine/snowman/metrics.go @@ -10,6 +10,14 @@ import ( "github.com/ava-labs/avalanchego/utils/wrappers" ) +const ( + pullGossipSource = "pull_gossip" + pushGossipSource = "push_gossip" + putGossipSource = "put_gossip" + builtSource = "built" + unknownSource = "unknown" +) + type metrics struct { bootstrapFinished prometheus.Gauge numRequests prometheus.Gauge @@ -27,6 +35,8 @@ type metrics struct { numProcessingAncestorFetchesUnneeded prometheus.Counter getAncestorsBlks metric.Averager selectedVoteIndex metric.Averager + issuerStake metric.Averager + issued *prometheus.CounterVec } func (m *metrics) Initialize(namespace string, reg prometheus.Registerer) error { @@ -115,6 +125,25 @@ func (m *metrics) Initialize(namespace string, reg prometheus.Registerer) error reg, &errs, ) + m.issuerStake = metric.NewAveragerWithErrs( + namespace, + "issuer_stake", + "stake weight of the peer who provided a block that was issued into consensus", + reg, + &errs, + ) + m.issued = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: namespace, + Name: "blks_issued", + Help: "number of blocks that have been issued into consensus by discovery mechanism", + }, []string{"source"}) + + // Register the labels + m.issued.WithLabelValues(pullGossipSource) + m.issued.WithLabelValues(pushGossipSource) + m.issued.WithLabelValues(putGossipSource) + m.issued.WithLabelValues(builtSource) + m.issued.WithLabelValues(unknownSource) errs.Add( reg.Register(m.bootstrapFinished), @@ -131,6 +160,7 @@ func (m *metrics) Initialize(namespace string, reg prometheus.Registerer) error reg.Register(m.numProcessingAncestorFetchesDropped), reg.Register(m.numProcessingAncestorFetchesSucceeded), reg.Register(m.numProcessingAncestorFetchesUnneeded), + reg.Register(m.issued), ) return errs.Err } diff --git a/snow/engine/snowman/syncer/blocks_backfiller.go b/snow/engine/snowman/syncer/blocks_backfiller.go index 9913ae5cda4e..cfbb093a8c45 100644 --- a/snow/engine/snowman/syncer/blocks_backfiller.go +++ b/snow/engine/snowman/syncer/blocks_backfiller.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/common/tracker" "github.com/ava-labs/avalanchego/snow/engine/snowman/block" "github.com/ava-labs/avalanchego/snow/validators" + "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/set" ) @@ -43,17 +44,18 @@ type BlockBackfillerConfig struct { type BlockBackfiller struct { BlockBackfillerConfig - fetchFrom set.Set[ids.NodeID] // picked from bootstrapper - outstandingRequests common.Requests // tracks which validators were asked for which block in which requests - interrupted bool // flag to allow backfilling restart after recovering from validators disconnections + fetchFrom set.Set[ids.NodeID] // picked from bootstrapper + outstandingRequests *bimap.BiMap[common.Request, ids.ID] // tracks which validators were asked for which block in which requests + interrupted bool // flag to allow backfilling restart after recovering from validators disconnections } func NewBlockBackfiller(cfg BlockBackfillerConfig) *BlockBackfiller { return &BlockBackfiller{ BlockBackfillerConfig: cfg, - fetchFrom: set.Of[ids.NodeID](cfg.Validators.GetValidatorIDs(cfg.Ctx.SubnetID)...), - interrupted: len(cfg.Peers.PreferredPeers()) > 0, + fetchFrom: set.Of[ids.NodeID](cfg.Validators.GetValidatorIDs(cfg.Ctx.SubnetID)...), + outstandingRequests: bimap.New[common.Request, ids.ID](), + interrupted: len(cfg.Peers.PreferredPeers()) > 0, } } @@ -80,7 +82,10 @@ func (bb *BlockBackfiller) Start(ctx context.Context) error { // response to a GetAncestors message to [nodeID] with request ID [requestID] func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, requestID uint32, blks [][]byte) error { // Make sure this is in response to a request we made - wantedBlkID, ok := bb.outstandingRequests.Remove(nodeID, requestID) + wantedBlkID, ok := bb.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) if !ok { // this message isn't in response to a request we made bb.Ctx.Log.Debug("received unexpected Ancestors", zap.Stringer("nodeID", nodeID), @@ -144,7 +149,10 @@ func (bb *BlockBackfiller) Ancestors(ctx context.Context, nodeID ids.NodeID, req } func (bb *BlockBackfiller) GetAncestorsFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { - blkID, ok := bb.outstandingRequests.Remove(nodeID, requestID) + blkID, ok := bb.outstandingRequests.DeleteKey(common.Request{ + NodeID: nodeID, + RequestID: requestID, + }) if !ok { bb.Ctx.Log.Debug("unexpectedly called GetAncestorsFailed", zap.Stringer("nodeID", nodeID), @@ -170,7 +178,14 @@ func (bb *BlockBackfiller) fetch(ctx context.Context, blkID ids.ID) error { // We only allow one outbound request at a time from a node bb.markUnavailable(validatorID) *bb.SharedRequestID++ - bb.outstandingRequests.Add(validatorID, *bb.SharedRequestID, blkID) + bb.outstandingRequests.Put( + common.Request{ + NodeID: validatorID, + RequestID: *bb.SharedRequestID, + }, + blkID, + ) + bb.Sender.SendGetAncestors(ctx, validatorID, *bb.SharedRequestID, blkID) return nil } diff --git a/snow/engine/snowman/syncer/state_syncer.go b/snow/engine/snowman/syncer/state_syncer.go index 89c839a25dcd..42db0b264cd1 100644 --- a/snow/engine/snowman/syncer/state_syncer.go +++ b/snow/engine/snowman/syncer/state_syncer.go @@ -24,6 +24,10 @@ import ( safemath "github.com/ava-labs/avalanchego/utils/math" ) +// maxOutstandingBroadcastRequests is the maximum number of requests to have +// outstanding when broadcasting. +const maxOutstandingBroadcastRequests = 50 + var _ common.StateSyncer = (*stateSyncer)(nil) // summary content as received from network, along with accumulated weight. @@ -544,7 +548,7 @@ func (ss *stateSyncer) startup(ctx context.Context) error { // no more seeders to be reached in the pending set func (ss *stateSyncer) sendGetStateSummaryFrontiers(ctx context.Context) { vdrs := set.NewSet[ids.NodeID](1) - for ss.targetSeeders.Len() > 0 && ss.pendingSeeders.Len() < common.MaxOutstandingBroadcastRequests { + for ss.targetSeeders.Len() > 0 && ss.pendingSeeders.Len() < maxOutstandingBroadcastRequests { vdr, _ := ss.targetSeeders.Pop() vdrs.Add(vdr) ss.pendingSeeders.Add(vdr) @@ -560,7 +564,7 @@ func (ss *stateSyncer) sendGetStateSummaryFrontiers(ctx context.Context) { // no more voters to be reached in the pending set. func (ss *stateSyncer) sendGetAcceptedStateSummaries(ctx context.Context) { vdrs := set.NewSet[ids.NodeID](1) - for ss.targetVoters.Len() > 0 && ss.pendingVoters.Len() < common.MaxOutstandingBroadcastRequests { + for ss.targetVoters.Len() > 0 && ss.pendingVoters.Len() < maxOutstandingBroadcastRequests { vdr, _ := ss.targetVoters.Pop() vdrs.Add(vdr) ss.pendingVoters.Add(vdr) @@ -618,10 +622,6 @@ func (ss *stateSyncer) HealthCheck(ctx context.Context) (interface{}, error) { return intf, vmErr } -func (ss *stateSyncer) GetVM() common.VM { - return ss.VM -} - func (ss *stateSyncer) IsEnabled(ctx context.Context) (bool, error) { if ss.stateSyncVM == nil { // state sync is not implemented diff --git a/snow/engine/snowman/syncer/state_syncer_test.go b/snow/engine/snowman/syncer/state_syncer_test.go index 95b4d6382ec3..c3dd9b2f16a6 100644 --- a/snow/engine/snowman/syncer/state_syncer_test.go +++ b/snow/engine/snowman/syncer/state_syncer_test.go @@ -243,7 +243,7 @@ func TestBeaconsAreReachedForFrontiersUponStartup(t *testing.T) { } // check that vdrs are reached out for frontiers - require.Len(contactedFrontiersProviders, safemath.Min(beacons.Count(ctx.SubnetID), common.MaxOutstandingBroadcastRequests)) + require.Len(contactedFrontiersProviders, safemath.Min(beacons.Count(ctx.SubnetID), maxOutstandingBroadcastRequests)) for beaconID := range contactedFrontiersProviders { // check that beacon is duly marked as reached out require.Contains(syncer.pendingSeeders, beaconID) @@ -284,7 +284,7 @@ func TestUnRequestedStateSummaryFrontiersAreDropped(t *testing.T) { initiallyReachedOutBeaconsSize := len(contactedFrontiersProviders) require.Positive(initiallyReachedOutBeaconsSize) - require.LessOrEqual(initiallyReachedOutBeaconsSize, common.MaxOutstandingBroadcastRequests) + require.LessOrEqual(initiallyReachedOutBeaconsSize, maxOutstandingBroadcastRequests) // mock VM to simulate a valid summary is returned fullVM.CantParseStateSummary = true @@ -373,7 +373,7 @@ func TestMalformedStateSummaryFrontiersAreDropped(t *testing.T) { initiallyReachedOutBeaconsSize := len(contactedFrontiersProviders) require.Positive(initiallyReachedOutBeaconsSize) - require.LessOrEqual(initiallyReachedOutBeaconsSize, common.MaxOutstandingBroadcastRequests) + require.LessOrEqual(initiallyReachedOutBeaconsSize, maxOutstandingBroadcastRequests) // mock VM to simulate an invalid summary is returned summary := []byte{'s', 'u', 'm', 'm', 'a', 'r', 'y'} @@ -441,7 +441,7 @@ func TestLateResponsesFromUnresponsiveFrontiersAreNotRecorded(t *testing.T) { initiallyReachedOutBeaconsSize := len(contactedFrontiersProviders) require.Positive(initiallyReachedOutBeaconsSize) - require.LessOrEqual(initiallyReachedOutBeaconsSize, common.MaxOutstandingBroadcastRequests) + require.LessOrEqual(initiallyReachedOutBeaconsSize, maxOutstandingBroadcastRequests) // pick one of the vdrs that have been reached out unresponsiveBeaconID := pickRandomFrom(contactedFrontiersProviders) @@ -647,7 +647,7 @@ func TestVoteRequestsAreSentAsAllFrontierBeaconsResponded(t *testing.T) { // check that vote requests are issued initiallyContactedVotersSize := len(contactedVoters) require.Positive(initiallyContactedVotersSize) - require.LessOrEqual(initiallyContactedVotersSize, common.MaxOutstandingBroadcastRequests) + require.LessOrEqual(initiallyContactedVotersSize, maxOutstandingBroadcastRequests) } func TestUnRequestedVotesAreDropped(t *testing.T) { @@ -716,7 +716,7 @@ func TestUnRequestedVotesAreDropped(t *testing.T) { // check that vote requests are issued initiallyContactedVotersSize := len(contactedVoters) require.Positive(initiallyContactedVotersSize) - require.LessOrEqual(initiallyContactedVotersSize, common.MaxOutstandingBroadcastRequests) + require.LessOrEqual(initiallyContactedVotersSize, maxOutstandingBroadcastRequests) _, found := syncer.weightedSummaries[summaryID] require.True(found) @@ -832,7 +832,7 @@ func TestVotesForUnknownSummariesAreDropped(t *testing.T) { // check that vote requests are issued initiallyContactedVotersSize := len(contactedVoters) require.Positive(initiallyContactedVotersSize) - require.LessOrEqual(initiallyContactedVotersSize, common.MaxOutstandingBroadcastRequests) + require.LessOrEqual(initiallyContactedVotersSize, maxOutstandingBroadcastRequests) _, found := syncer.weightedSummaries[summaryID] require.True(found) diff --git a/snow/engine/snowman/syncer/utils_test.go b/snow/engine/snowman/syncer/utils_test.go index fee7c4f847e6..149d1fe0e681 100644 --- a/snow/engine/snowman/syncer/utils_test.go +++ b/snow/engine/snowman/syncer/utils_test.go @@ -58,10 +58,10 @@ type fullVM struct { } func buildTestPeers(t *testing.T, subnetID ids.ID) validators.Manager { - // we consider more than common.MaxOutstandingBroadcastRequests peers - // so to test the effect of cap on number of requests sent out + // We consider more than maxOutstandingBroadcastRequests peers to test + // capping the number of requests sent out. vdrs := validators.NewManager() - for idx := 0; idx < 2*common.MaxOutstandingBroadcastRequests; idx++ { + for idx := 0; idx < 2*maxOutstandingBroadcastRequests; idx++ { beaconID := ids.GenerateTestNodeID() require.NoError(t, vdrs.AddStaker(subnetID, beaconID, nil, ids.Empty, 1)) } diff --git a/snow/engine/snowman/transitive.go b/snow/engine/snowman/transitive.go index 38a80ffa914f..258cb545595e 100644 --- a/snow/engine/snowman/transitive.go +++ b/snow/engine/snowman/transitive.go @@ -7,6 +7,8 @@ import ( "context" "fmt" + "github.com/prometheus/client_golang/prometheus" + "go.uber.org/zap" "github.com/ava-labs/avalanchego/cache" @@ -23,6 +25,7 @@ import ( "github.com/ava-labs/avalanchego/snow/engine/snowman/syncer" "github.com/ava-labs/avalanchego/snow/event" "github.com/ava-labs/avalanchego/utils/bag" + "github.com/ava-labs/avalanchego/utils/bimap" "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/math" @@ -59,13 +62,14 @@ type Transitive struct { *syncer.BlockBackfiller - RequestID uint32 + requestID uint32 // track outstanding preference requests polls poll.Set // blocks that have we have sent get requests for but haven't yet received - blkReqs common.Requests + blkReqs *bimap.BiMap[common.Request, ids.ID] + blkReqSourceMetric map[common.Request]prometheus.Counter // blocks that are queued to be issued to consensus once missing dependencies are fetched // Block ID --> Block @@ -139,6 +143,8 @@ func newTransitive(config Config) (*Transitive, error) { nonVerifiedCache: nonVerifiedCache, acceptedFrontiers: acceptedFrontiers, polls: polls, + blkReqs: bimap.New[common.Request, ids.ID](), + blkReqSourceMetric: make(map[common.Request]prometheus.Counter), } t.BlockBackfiller = syncer.NewBlockBackfiller( syncer.BlockBackfillerConfig{ @@ -149,7 +155,7 @@ func newTransitive(config Config) (*Transitive, error) { Peers: config.Peers, AncestorsMaxContainersSent: config.AncestorsMaxContainersSent, AncestorsMaxContainersReceived: config.AncestorsMaxContainersReceived, - SharedRequestID: &t.RequestID, + SharedRequestID: &t.requestID, }, ) @@ -179,20 +185,39 @@ func (t *Transitive) Put(ctx context.Context, nodeID ids.NodeID, requestID uint3 return t.GetFailed(ctx, nodeID, requestID) } - actualBlkID := blk.ID() - expectedBlkID, ok := t.blkReqs.Get(nodeID, requestID) - // If the provided block is not the requested block, we need to explicitly - // mark the request as failed to avoid having a dangling dependency. - if ok && actualBlkID != expectedBlkID { - t.Ctx.Log.Debug("incorrect block returned in Put", - zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", requestID), - zap.Stringer("blkID", actualBlkID), - zap.Stringer("expectedBlkID", expectedBlkID), - ) - // We assume that [blk] is useless because it doesn't match what we - // expected. - return t.GetFailed(ctx, nodeID, requestID) + var ( + req = common.Request{ + NodeID: nodeID, + RequestID: requestID, + } + issuedMetric prometheus.Counter + ) + switch expectedBlkID, ok := t.blkReqs.GetValue(req); { + case ok: + actualBlkID := blk.ID() + if actualBlkID != expectedBlkID { + t.Ctx.Log.Debug("incorrect block returned in Put", + zap.Stringer("nodeID", nodeID), + zap.Uint32("requestID", requestID), + zap.Stringer("blkID", actualBlkID), + zap.Stringer("expectedBlkID", expectedBlkID), + ) + // We assume that [blk] is useless because it doesn't match what we + // expected. + return t.GetFailed(ctx, nodeID, requestID) + } + + issuedMetric = t.blkReqSourceMetric[req] + case requestID == constants.GossipMsgRequestID: + issuedMetric = t.metrics.issued.WithLabelValues(putGossipSource) + default: + // This can happen if this block was provided to this engine while a Get + // request was outstanding. For example, the block may have been locally + // built or the node may have received a PushQuery with this block. + // + // Note: It is still possible this block will be issued here, because + // the block may have previously failed verification. + issuedMetric = t.metrics.issued.WithLabelValues(unknownSource) } if t.wasIssued(blk) { @@ -204,7 +229,7 @@ func (t *Transitive) Put(ctx context.Context, nodeID ids.NodeID, requestID uint3 // receive requests to fill the ancestry. dependencies that have already // been fetched, but with missing dependencies themselves won't be requested // from the vdr. - if _, err := t.issueFrom(ctx, nodeID, blk); err != nil { + if _, err := t.issueFrom(ctx, nodeID, blk, issuedMetric); err != nil { return err } return t.buildBlocks(ctx) @@ -212,8 +237,13 @@ func (t *Transitive) Put(ctx context.Context, nodeID ids.NodeID, requestID uint3 func (t *Transitive) GetFailed(ctx context.Context, nodeID ids.NodeID, requestID uint32) error { // We don't assume that this function is called after a failed Get message. - // Check to see if we have an outstanding request and also get what the request was for if it exists. - blkID, ok := t.blkReqs.Remove(nodeID, requestID) + // Check to see if we have an outstanding request and also get what the + // request was for if it exists. + req := common.Request{ + NodeID: nodeID, + RequestID: requestID, + } + blkID, ok := t.blkReqs.DeleteKey(req) if !ok { t.Ctx.Log.Debug("unexpected GetFailed", zap.Stringer("nodeID", nodeID), @@ -221,6 +251,7 @@ func (t *Transitive) GetFailed(ctx context.Context, nodeID ids.NodeID, requestID ) return nil } + delete(t.blkReqSourceMetric, req) // Because the get request was dropped, we no longer expect blkID to be issued. t.blocked.Abandon(ctx, blkID) @@ -232,9 +263,11 @@ func (t *Transitive) GetFailed(ctx context.Context, nodeID ids.NodeID, requestID func (t *Transitive) PullQuery(ctx context.Context, nodeID ids.NodeID, requestID uint32, blkID ids.ID, requestedHeight uint64) error { t.sendChits(ctx, nodeID, requestID, requestedHeight) + issuedMetric := t.metrics.issued.WithLabelValues(pushGossipSource) + // Try to issue [blkID] to consensus. // If we're missing an ancestor, request it from [vdr] - if _, err := t.issueFromByID(ctx, nodeID, blkID); err != nil { + if _, err := t.issueFromByID(ctx, nodeID, blkID, issuedMetric); err != nil { return err } @@ -268,12 +301,14 @@ func (t *Transitive) PushQuery(ctx context.Context, nodeID ids.NodeID, requestID t.metrics.numUselessPushQueryBytes.Add(float64(len(blkBytes))) } + issuedMetric := t.metrics.issued.WithLabelValues(pushGossipSource) + // issue the block into consensus. If the block has already been issued, // this will be a noop. If this block has missing dependencies, nodeID will // receive requests to fill the ancestry. dependencies that have already // been fetched, but with missing dependencies themselves won't be requested // from the vdr. - if _, err := t.issueFrom(ctx, nodeID, blk); err != nil { + if _, err := t.issueFrom(ctx, nodeID, blk, issuedMetric); err != nil { return err } @@ -291,7 +326,9 @@ func (t *Transitive) Chits(ctx context.Context, nodeID ids.NodeID, requestID uin zap.Stringer("acceptedID", acceptedID), ) - addedPreferred, err := t.issueFromByID(ctx, nodeID, preferredID) + issuedMetric := t.metrics.issued.WithLabelValues(pullGossipSource) + + addedPreferred, err := t.issueFromByID(ctx, nodeID, preferredID, issuedMetric) if err != nil { return err } @@ -305,7 +342,7 @@ func (t *Transitive) Chits(ctx context.Context, nodeID ids.NodeID, requestID uin responseOptions = []ids.ID{preferredID} ) if preferredID != preferredIDAtHeight { - addedPreferredIDAtHeight, err = t.issueFromByID(ctx, nodeID, preferredIDAtHeight) + addedPreferredIDAtHeight, err = t.issueFromByID(ctx, nodeID, preferredIDAtHeight, issuedMetric) if err != nil { return err } @@ -411,7 +448,7 @@ func (t *Transitive) Context() *snow.ConsensusContext { } func (t *Transitive) Start(ctx context.Context, startReqID uint32) error { - t.RequestID = startReqID + t.requestID = startReqID lastAcceptedID, err := t.VM.LastAccepted(ctx) if err != nil { return err @@ -444,9 +481,10 @@ func (t *Transitive) Start(ctx context.Context, startReqID uint32) error { case err != nil: return err default: + issuedMetric := t.metrics.issued.WithLabelValues(builtSource) for _, blk := range options { // note that deliver will set the VM's preference - if err := t.deliver(ctx, blk, false); err != nil { + if err := t.deliver(ctx, t.Ctx.NodeID, blk, false, issuedMetric); err != nil { return err } } @@ -492,10 +530,6 @@ func (t *Transitive) HealthCheck(ctx context.Context) (interface{}, error) { return intf, fmt.Errorf("vm: %w ; consensus: %w", vmErr, consensusErr) } -func (t *Transitive) GetVM() common.VM { - return t.VM -} - func (t *Transitive) GetBlock(ctx context.Context, blkID ids.ID) (snowman.Block, error) { if blk, ok := t.pending[blkID]; ok { return blk, nil @@ -612,7 +646,8 @@ func (t *Transitive) buildBlocks(ctx context.Context) error { ) } - added, err := t.issueWithAncestors(ctx, blk) + issuedMetric := t.metrics.issued.WithLabelValues(builtSource) + added, err := t.issueWithAncestors(ctx, blk, issuedMetric) if err != nil { return err } @@ -642,23 +677,33 @@ func (t *Transitive) repoll(ctx context.Context) { // issueFromByID attempts to issue the branch ending with a block [blkID] into consensus. // If we do not have [blkID], request it. // Returns true if the block is processing in consensus or is decided. -func (t *Transitive) issueFromByID(ctx context.Context, nodeID ids.NodeID, blkID ids.ID) (bool, error) { +func (t *Transitive) issueFromByID( + ctx context.Context, + nodeID ids.NodeID, + blkID ids.ID, + issuedMetric prometheus.Counter, +) (bool, error) { blk, err := t.GetBlock(ctx, blkID) if err != nil { - t.sendRequest(ctx, nodeID, blkID) + t.sendRequest(ctx, nodeID, blkID, issuedMetric) return false, nil } - return t.issueFrom(ctx, nodeID, blk) + return t.issueFrom(ctx, nodeID, blk, issuedMetric) } // issueFrom attempts to issue the branch ending with block [blkID] to consensus. // Returns true if the block is processing in consensus or is decided. // If a dependency is missing, request it from [vdr]. -func (t *Transitive) issueFrom(ctx context.Context, nodeID ids.NodeID, blk snowman.Block) (bool, error) { +func (t *Transitive) issueFrom( + ctx context.Context, + nodeID ids.NodeID, + blk snowman.Block, + issuedMetric prometheus.Counter, +) (bool, error) { // issue [blk] and its ancestors to consensus. blkID := blk.ID() for !t.wasIssued(blk) { - if err := t.issue(ctx, blk, false); err != nil { + if err := t.issue(ctx, nodeID, blk, false, issuedMetric); err != nil { return false, err } @@ -668,13 +713,15 @@ func (t *Transitive) issueFrom(ctx context.Context, nodeID ids.NodeID, blk snowm // If we don't have this ancestor, request it from [vdr] if err != nil || !blk.Status().Fetched() { - t.sendRequest(ctx, nodeID, blkID) + t.sendRequest(ctx, nodeID, blkID, issuedMetric) return false, nil } } // Remove any outstanding requests for this block - t.blkReqs.RemoveAny(blkID) + if req, ok := t.blkReqs.DeleteValue(blkID); ok { + delete(t.blkReqSourceMetric, req) + } issued := t.Consensus.Decided(blk) || t.Consensus.Processing(blkID) if issued { @@ -693,12 +740,16 @@ func (t *Transitive) issueFrom(ctx context.Context, nodeID ids.NodeID, blk snowm // issueWithAncestors attempts to issue the branch ending with [blk] to consensus. // Returns true if the block is processing in consensus or is decided. // If a dependency is missing and the dependency hasn't been requested, the issuance will be abandoned. -func (t *Transitive) issueWithAncestors(ctx context.Context, blk snowman.Block) (bool, error) { +func (t *Transitive) issueWithAncestors( + ctx context.Context, + blk snowman.Block, + issuedMetric prometheus.Counter, +) (bool, error) { blkID := blk.ID() // issue [blk] and its ancestors into consensus status := blk.Status() for status.Fetched() && !t.wasIssued(blk) { - err := t.issue(ctx, blk, true) + err := t.issue(ctx, t.Ctx.NodeID, blk, true, issuedMetric) if err != nil { return false, err } @@ -718,7 +769,7 @@ func (t *Transitive) issueWithAncestors(ctx context.Context, blk snowman.Block) // There's an outstanding request for this block. // We can just wait for that request to succeed or fail. - if t.blkReqs.Contains(blkID) { + if t.blkReqs.HasValue(blkID) { return false, nil } @@ -740,20 +791,30 @@ func (t *Transitive) wasIssued(blk snowman.Block) bool { // Issue [blk] to consensus once its ancestors have been issued. // If [push] is true, a push query will be used. Otherwise, a pull query will be // used. -func (t *Transitive) issue(ctx context.Context, blk snowman.Block, push bool) error { +func (t *Transitive) issue( + ctx context.Context, + nodeID ids.NodeID, + blk snowman.Block, + push bool, + issuedMetric prometheus.Counter, +) error { blkID := blk.ID() // mark that the block is queued to be added to consensus once its ancestors have been t.pending[blkID] = blk // Remove any outstanding requests for this block - t.blkReqs.RemoveAny(blkID) + if req, ok := t.blkReqs.DeleteValue(blkID); ok { + delete(t.blkReqSourceMetric, req) + } // Will add [blk] to consensus once its ancestors have been i := &issuer{ - t: t, - blk: blk, - push: push, + t: t, + nodeID: nodeID, + blk: blk, + issuedMetric: issuedMetric, + push: push, } // block on the parent if needed @@ -776,20 +837,31 @@ func (t *Transitive) issue(ctx context.Context, blk snowman.Block, push bool) er } // Request that [vdr] send us block [blkID] -func (t *Transitive) sendRequest(ctx context.Context, nodeID ids.NodeID, blkID ids.ID) { +func (t *Transitive) sendRequest( + ctx context.Context, + nodeID ids.NodeID, + blkID ids.ID, + issuedMetric prometheus.Counter, +) { // There is already an outstanding request for this block - if t.blkReqs.Contains(blkID) { + if t.blkReqs.HasValue(blkID) { return } - t.RequestID++ - t.blkReqs.Add(nodeID, t.RequestID, blkID) + t.requestID++ + req := common.Request{ + NodeID: nodeID, + RequestID: t.requestID, + } + t.blkReqs.Put(req, blkID) + t.blkReqSourceMetric[req] = issuedMetric + t.Ctx.Log.Verbo("sending Get request", zap.Stringer("nodeID", nodeID), - zap.Uint32("requestID", t.RequestID), + zap.Uint32("requestID", t.requestID), zap.Stringer("blkID", blkID), ) - t.Sender.SendGet(ctx, nodeID, t.RequestID, blkID) + t.Sender.SendGet(ctx, nodeID, t.requestID, blkID) // Tracks performance statistics t.metrics.numRequests.Set(float64(t.blkReqs.Len())) @@ -830,28 +902,34 @@ func (t *Transitive) sendQuery( } vdrBag := bag.Of(vdrIDs...) - t.RequestID++ - if !t.polls.Add(t.RequestID, vdrBag) { + t.requestID++ + if !t.polls.Add(t.requestID, vdrBag) { t.Ctx.Log.Error("dropped query for block", zap.String("reason", "failed to add poll"), zap.Stringer("blkID", blkID), - zap.Uint32("requestID", t.RequestID), + zap.Uint32("requestID", t.requestID), ) return } vdrSet := set.Of(vdrIDs...) if push { - t.Sender.SendPushQuery(ctx, vdrSet, t.RequestID, blkBytes, nextHeightToAccept) + t.Sender.SendPushQuery(ctx, vdrSet, t.requestID, blkBytes, nextHeightToAccept) } else { - t.Sender.SendPullQuery(ctx, vdrSet, t.RequestID, blkID, nextHeightToAccept) + t.Sender.SendPullQuery(ctx, vdrSet, t.requestID, blkID, nextHeightToAccept) } } // issue [blk] to consensus // If [push] is true, a push query will be used. Otherwise, a pull query will be // used. -func (t *Transitive) deliver(ctx context.Context, blk snowman.Block, push bool) error { +func (t *Transitive) deliver( + ctx context.Context, + nodeID ids.NodeID, + blk snowman.Block, + push bool, + issuedMetric prometheus.Counter, +) error { blkID := blk.ID() if t.Consensus.Decided(blk) || t.Consensus.Processing(blkID) { return nil @@ -877,7 +955,7 @@ func (t *Transitive) deliver(ctx context.Context, blk snowman.Block, push bool) // By ensuring that the parent is either processing or accepted, it is // guaranteed that the parent was successfully verified. This means that // calling Verify on this block is allowed. - blkAdded, err := t.addUnverifiedBlockToConsensus(ctx, blk) + blkAdded, err := t.addUnverifiedBlockToConsensus(ctx, nodeID, blk, issuedMetric) if err != nil { return err } @@ -901,7 +979,7 @@ func (t *Transitive) deliver(ctx context.Context, blk snowman.Block, push bool) } for _, blk := range options { - blkAdded, err := t.addUnverifiedBlockToConsensus(ctx, blk) + blkAdded, err := t.addUnverifiedBlockToConsensus(ctx, nodeID, blk, issuedMetric) if err != nil { return err } @@ -933,13 +1011,17 @@ func (t *Transitive) deliver(ctx context.Context, blk snowman.Block, push bool) t.removeFromPending(blk) t.blocked.Fulfill(ctx, blkID) - t.blkReqs.RemoveAny(blkID) + if req, ok := t.blkReqs.DeleteValue(blkID); ok { + delete(t.blkReqSourceMetric, req) + } } for _, blk := range dropped { blkID := blk.ID() t.removeFromPending(blk) t.blocked.Abandon(ctx, blkID) - t.blkReqs.RemoveAny(blkID) + if req, ok := t.blkReqs.DeleteValue(blkID); ok { + delete(t.blkReqSourceMetric, req) + } } // If we should issue multiple queries at the same time, we need to repoll @@ -981,12 +1063,18 @@ func (t *Transitive) addToNonVerifieds(blk snowman.Block) { // addUnverifiedBlockToConsensus returns whether the block was added and an // error if one occurred while adding it to consensus. -func (t *Transitive) addUnverifiedBlockToConsensus(ctx context.Context, blk snowman.Block) (bool, error) { +func (t *Transitive) addUnverifiedBlockToConsensus( + ctx context.Context, + nodeID ids.NodeID, + blk snowman.Block, + issuedMetric prometheus.Counter, +) (bool, error) { blkID := blk.ID() // make sure this block is valid if err := blk.Verify(ctx); err != nil { t.Ctx.Log.Debug("block verification failed", + zap.Stringer("nodeID", nodeID), zap.Stringer("blkID", blkID), zap.Error(err), ) @@ -996,10 +1084,13 @@ func (t *Transitive) addUnverifiedBlockToConsensus(ctx context.Context, blk snow return false, nil } + issuedMetric.Inc() t.nonVerifieds.Remove(blkID) t.nonVerifiedCache.Evict(blkID) t.metrics.numNonVerifieds.Set(float64(t.nonVerifieds.Len())) + t.metrics.issuerStake.Observe(float64(t.Validators.GetWeight(t.Ctx.SubnetID, nodeID))) t.Ctx.Log.Verbo("adding block to consensus", + zap.Stringer("nodeID", nodeID), zap.Stringer("blkID", blkID), ) return true, t.Consensus.Add(ctx, &memoryBlock{ diff --git a/snow/engine/snowman/transitive_block_backfilling_test.go b/snow/engine/snowman/transitive_block_backfilling_test.go index 2f4dd85cf584..c460712294cb 100644 --- a/snow/engine/snowman/transitive_block_backfilling_test.go +++ b/snow/engine/snowman/transitive_block_backfilling_test.go @@ -486,7 +486,7 @@ type fullVM struct { } func setupBlockBackfillingTests(t *testing.T) (Config, *fullVM, *common.SenderTest, error) { - engCfg := DefaultConfigs() + engCfg := DefaultConfig() var ( vm = &fullVM{ diff --git a/snow/engine/snowman/transitive_test.go b/snow/engine/snowman/transitive_test.go index 96cb2d72ba76..69ca9611cc3f 100644 --- a/snow/engine/snowman/transitive_test.go +++ b/snow/engine/snowman/transitive_test.go @@ -33,18 +33,17 @@ var ( Genesis = ids.GenerateTestID() ) -func setup(t *testing.T, commonCfg common.Config, engCfg Config) (ids.NodeID, validators.Manager, *common.SenderTest, *block.TestVM, *Transitive, snowman.Block) { +func setup(t *testing.T, engCfg Config) (ids.NodeID, validators.Manager, *common.SenderTest, *block.TestVM, *Transitive, snowman.Block) { require := require.New(t) vals := validators.NewManager() engCfg.Validators = vals vdr := ids.GenerateTestNodeID() - require.NoError(vals.AddStaker(commonCfg.Ctx.SubnetID, vdr, nil, ids.Empty, 1)) + require.NoError(vals.AddStaker(engCfg.Ctx.SubnetID, vdr, nil, ids.Empty, 1)) sender := &common.SenderTest{T: t} engCfg.Sender = sender - commonCfg.Sender = sender sender.Default(true) vm := &block.TestVM{} @@ -54,10 +53,10 @@ func setup(t *testing.T, commonCfg common.Config, engCfg Config) (ids.NodeID, va snowGetHandler, err := getter.New( vm, sender, - commonCfg.Ctx.Log, + engCfg.Ctx.Log, time.Second, 2000, - commonCfg.Ctx.Registerer, + engCfg.Ctx.Registerer, ) require.NoError(err) engCfg.AllGetsServer = snowGetHandler @@ -95,9 +94,8 @@ func setup(t *testing.T, commonCfg common.Config, engCfg Config) (ids.NodeID, va } func setupDefaultConfig(t *testing.T) (ids.NodeID, validators.Manager, *common.SenderTest, *block.TestVM, *Transitive, snowman.Block) { - commonCfg := common.DefaultConfigTest() - engCfg := DefaultConfigs() - return setup(t, commonCfg, engCfg) + engCfg := DefaultConfig() + return setup(t, engCfg) } func TestEngineShutdown(t *testing.T) { @@ -326,7 +324,7 @@ func TestEngineQuery(t *testing.T) { func TestEngineMultipleQuery(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() engCfg.Params = snowball.Parameters{ K: 3, AlphaPreference: 2, @@ -414,7 +412,13 @@ func TestEngineMultipleQuery(t *testing.T) { } } - require.NoError(te.issue(context.Background(), blk0, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk0, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) blk1 := &snowman.TestBlock{ TestDecidable: choices.TestDecidable{ @@ -524,10 +528,22 @@ func TestEngineBlockedIssue(t *testing.T) { } } - require.NoError(te.issue(context.Background(), blk1, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk1, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) blk0.StatusV = choices.Processing - require.NoError(te.issue(context.Background(), blk0, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk0, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) require.Equal(blk1.ID(), te.Consensus.Preference()) } @@ -560,7 +576,13 @@ func TestEngineAbandonResponse(t *testing.T) { return nil, errUnknownBlock } - require.NoError(te.issue(context.Background(), blk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) require.NoError(te.QueryFailed(context.Background(), vdr, 1)) require.Empty(te.blocked) @@ -721,7 +743,7 @@ func TestEngineRepoll(t *testing.T) { func TestVoteCanceling(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() engCfg.Params = snowball.Parameters{ K: 3, AlphaPreference: 2, @@ -799,7 +821,13 @@ func TestVoteCanceling(t *testing.T) { require.Equal(uint64(1), requestedHeight) } - require.NoError(te.issue(context.Background(), blk, true)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk, + true, + te.metrics.issued.WithLabelValues(unknownSource), + )) require.Equal(1, te.polls.Len()) @@ -819,7 +847,7 @@ func TestVoteCanceling(t *testing.T) { func TestEngineNoQuery(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() sender := &common.SenderTest{T: t} engCfg.Sender = sender @@ -860,13 +888,19 @@ func TestEngineNoQuery(t *testing.T) { BytesV: []byte{1}, } - require.NoError(te.issue(context.Background(), blk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) } func TestEngineNoRepollQuery(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() sender := &common.SenderTest{T: t} engCfg.Sender = sender @@ -963,7 +997,13 @@ func TestEngineAbandonChit(t *testing.T) { reqID = requestID } - require.NoError(te.issue(context.Background(), blk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) fakeBlkID := ids.GenerateTestID() vm.GetBlockF = func(_ context.Context, id ids.ID) (snowman.Block, error) { @@ -1018,7 +1058,13 @@ func TestEngineAbandonChitWithUnexpectedPutBlock(t *testing.T) { reqID = requestID } - require.NoError(te.issue(context.Background(), blk, true)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk, + true, + te.metrics.issued.WithLabelValues(unknownSource), + )) fakeBlkID := ids.GenerateTestID() vm.GetBlockF = func(_ context.Context, id ids.ID) (snowman.Block, error) { @@ -1101,7 +1147,13 @@ func TestEngineBlockingChitRequest(t *testing.T) { return blockingBlk, nil } - require.NoError(te.issue(context.Background(), parentBlk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + parentBlk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) sender.CantSendChits = false @@ -1112,7 +1164,13 @@ func TestEngineBlockingChitRequest(t *testing.T) { sender.CantSendPullQuery = false missingBlk.StatusV = choices.Processing - require.NoError(te.issue(context.Background(), missingBlk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + missingBlk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) require.Empty(te.blocked) } @@ -1165,7 +1223,13 @@ func TestEngineBlockingChitResponse(t *testing.T) { } } - require.NoError(te.issue(context.Background(), blockingBlk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blockingBlk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) queryRequestID := new(uint32) sender.SendPullQueryF = func(_ context.Context, inVdrs set.Set[ids.NodeID], requestID uint32, blkID ids.ID, requestedHeight uint64) { @@ -1176,7 +1240,13 @@ func TestEngineBlockingChitResponse(t *testing.T) { require.Equal(uint64(1), requestedHeight) } - require.NoError(te.issue(context.Background(), issuedBlk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + issuedBlk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) sender.SendPushQueryF = nil sender.CantSendPushQuery = false @@ -1187,7 +1257,13 @@ func TestEngineBlockingChitResponse(t *testing.T) { sender.CantSendPullQuery = false missingBlk.StatusV = choices.Processing - require.NoError(te.issue(context.Background(), missingBlk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + missingBlk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) } func TestEngineRetryFetch(t *testing.T) { @@ -1283,9 +1359,21 @@ func TestEngineUndeclaredDependencyDeadlock(t *testing.T) { return nil, errUnknownBlock } } - require.NoError(te.issue(context.Background(), validBlk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + validBlk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) sender.SendPushQueryF = nil - require.NoError(te.issue(context.Background(), invalidBlk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + invalidBlk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) require.NoError(te.Chits(context.Background(), vdr, *reqID, invalidBlkID, invalidBlkID, invalidBlkID)) require.Equal(choices.Accepted, validBlk.Status()) @@ -1504,7 +1592,7 @@ func TestEnginePushQueryRequestIDConflict(t *testing.T) { func TestEngineAggressivePolling(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() engCfg.Params.ConcurrentRepolls = 2 vals := validators.NewManager() @@ -1592,7 +1680,7 @@ func TestEngineAggressivePolling(t *testing.T) { func TestEngineDoubleChit(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() engCfg.Params = snowball.Parameters{ K: 2, AlphaPreference: 2, @@ -1668,7 +1756,13 @@ func TestEngineDoubleChit(t *testing.T) { require.Equal(blk.ID(), blkID) require.Equal(uint64(1), requestedHeight) } - require.NoError(te.issue(context.Background(), blk, false)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk, + false, + te.metrics.issued.WithLabelValues(unknownSource), + )) vm.GetBlockF = func(_ context.Context, id ids.ID) (snowman.Block, error) { switch id { @@ -1696,7 +1790,7 @@ func TestEngineDoubleChit(t *testing.T) { func TestEngineBuildBlockLimit(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() engCfg.Params.K = 1 engCfg.Params.AlphaPreference = 1 engCfg.Params.AlphaConfidence = 1 @@ -2718,7 +2812,7 @@ func TestEngineBuildBlockWithCachedNonVerifiedParent(t *testing.T) { func TestEngineApplyAcceptedFrontierInQueryFailed(t *testing.T) { require := require.New(t) - engCfg := DefaultConfigs() + engCfg := DefaultConfig() engCfg.Params = snowball.Parameters{ K: 1, AlphaPreference: 1, @@ -2787,7 +2881,13 @@ func TestEngineApplyAcceptedFrontierInQueryFailed(t *testing.T) { require.Equal(uint64(1), requestedHeight) } - require.NoError(te.issue(context.Background(), blk, true)) + require.NoError(te.issue( + context.Background(), + te.Ctx.NodeID, + blk, + true, + te.metrics.issued.WithLabelValues(unknownSource), + )) vm.GetBlockF = func(_ context.Context, id ids.ID) (snowman.Block, error) { switch id { diff --git a/snow/networking/handler/handler_test.go b/snow/networking/handler/handler_test.go index 0c87ed752f8b..bb434e2017d4 100644 --- a/snow/networking/handler/handler_test.go +++ b/snow/networking/handler/handler_test.go @@ -68,9 +68,6 @@ func TestHandlerDropsTimedOutMessages(t *testing.T) { handler := handlerIntf.(*handler) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -170,9 +167,6 @@ func TestHandlerClosesOnError(t *testing.T) { }) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -260,9 +254,6 @@ func TestHandlerDropsGossipDuringBootstrapping(t *testing.T) { handler.clock.Set(time.Now()) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -338,9 +329,6 @@ func TestHandlerDispatchInternal(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -415,9 +403,6 @@ func TestHandlerSubnetConnector(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -587,9 +572,6 @@ func TestDynamicEngineTypeDispatch(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, diff --git a/snow/networking/handler/health_test.go b/snow/networking/handler/health_test.go index 9767859a4abf..63b7dbea140c 100644 --- a/snow/networking/handler/health_test.go +++ b/snow/networking/handler/health_test.go @@ -82,9 +82,6 @@ func TestHealthCheckSubnet(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, diff --git a/snow/networking/router/chain_router_test.go b/snow/networking/router/chain_router_test.go index d4f71828799f..1e37c7c1d799 100644 --- a/snow/networking/router/chain_router_test.go +++ b/snow/networking/router/chain_router_test.go @@ -105,9 +105,6 @@ func TestShutdown(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -246,9 +243,6 @@ func TestShutdownTimesOut(t *testing.T) { bootstrapFinished := make(chan struct{}, 1) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -407,9 +401,6 @@ func TestRouterTimeout(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -886,9 +877,6 @@ func TestRouterClearTimeouts(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -1182,9 +1170,6 @@ func TestValidatorOnlyMessageDrops(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -1634,9 +1619,6 @@ func TestValidatorOnlyAllowedNodeMessageDrops(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, diff --git a/snow/networking/sender/sender_test.go b/snow/networking/sender/sender_test.go index 88c02b9a7f3f..a6da8738e1fa 100644 --- a/snow/networking/sender/sender_test.go +++ b/snow/networking/sender/sender_test.go @@ -134,9 +134,6 @@ func TestTimeout(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -392,9 +389,6 @@ func TestReliableMessages(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, @@ -540,9 +534,6 @@ func TestReliableMessagesToMyself(t *testing.T) { require.NoError(err) bootstrapper := &common.BootstrapperTest{ - BootstrapableTest: common.BootstrapableTest{ - T: t, - }, EngineTest: common.EngineTest{ T: t, }, diff --git a/utils/bimap/bimap.go b/utils/bimap/bimap.go new file mode 100644 index 000000000000..28d20750bace --- /dev/null +++ b/utils/bimap/bimap.go @@ -0,0 +1,102 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package bimap + +import "github.com/ava-labs/avalanchego/utils" + +type Entry[K, V any] struct { + Key K + Value V +} + +// BiMap is a bi-directional map. +type BiMap[K, V comparable] struct { + keyToValue map[K]V + valueToKey map[V]K +} + +// New creates a new empty bimap. +func New[K, V comparable]() *BiMap[K, V] { + return &BiMap[K, V]{ + keyToValue: make(map[K]V), + valueToKey: make(map[V]K), + } +} + +// Put the key value pair into the map. If either [key] or [val] was previously +// in the map, the previous entries will be removed and returned. +// +// Note: Unlike normal maps, it's possible that Put removes 0, 1, or 2 existing +// entries to ensure that mappings are one-to-one. +func (m *BiMap[K, V]) Put(key K, val V) []Entry[K, V] { + var removed []Entry[K, V] + oldVal, oldValDeleted := m.DeleteKey(key) + if oldValDeleted { + removed = append(removed, Entry[K, V]{ + Key: key, + Value: oldVal, + }) + } + oldKey, oldKeyDeleted := m.DeleteValue(val) + if oldKeyDeleted { + removed = append(removed, Entry[K, V]{ + Key: oldKey, + Value: val, + }) + } + m.keyToValue[key] = val + m.valueToKey[val] = key + return removed +} + +// GetKey that maps to the provided value. +func (m *BiMap[K, V]) GetKey(val V) (K, bool) { + key, ok := m.valueToKey[val] + return key, ok +} + +// GetValue that is mapped to the provided key. +func (m *BiMap[K, V]) GetValue(key K) (V, bool) { + val, ok := m.keyToValue[key] + return val, ok +} + +// HasKey returns true if [key] is in the map. +func (m *BiMap[K, _]) HasKey(key K) bool { + _, ok := m.keyToValue[key] + return ok +} + +// HasValue returns true if [val] is in the map. +func (m *BiMap[_, V]) HasValue(val V) bool { + _, ok := m.valueToKey[val] + return ok +} + +// DeleteKey removes [key] from the map and returns the value it mapped to. +func (m *BiMap[K, V]) DeleteKey(key K) (V, bool) { + val, ok := m.keyToValue[key] + if !ok { + return utils.Zero[V](), false + } + delete(m.keyToValue, key) + delete(m.valueToKey, val) + return val, true +} + +// DeleteValue removes [val] from the map and returns the key that mapped to it. +func (m *BiMap[K, V]) DeleteValue(val V) (K, bool) { + key, ok := m.valueToKey[val] + if !ok { + return utils.Zero[K](), false + } + delete(m.keyToValue, key) + delete(m.valueToKey, val) + return key, true +} + +// Len return the number of entries in this map. +func (m *BiMap[K, V]) Len() int { + return len(m.keyToValue) +} diff --git a/utils/bimap/bimap_test.go b/utils/bimap/bimap_test.go new file mode 100644 index 000000000000..9914578c6070 --- /dev/null +++ b/utils/bimap/bimap_test.go @@ -0,0 +1,328 @@ +// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package bimap + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestBiMapPut(t *testing.T) { + tests := []struct { + name string + state *BiMap[int, int] + key int + value int + expectedRemoved []Entry[int, int] + expectedState *BiMap[int, int] + }{ + { + name: "none removed", + state: New[int, int](), + key: 1, + value: 2, + expectedRemoved: nil, + expectedState: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 2, + }, + valueToKey: map[int]int{ + 2: 1, + }, + }, + }, + { + name: "key removed", + state: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 2, + }, + valueToKey: map[int]int{ + 2: 1, + }, + }, + key: 1, + value: 3, + expectedRemoved: []Entry[int, int]{ + { + Key: 1, + Value: 2, + }, + }, + expectedState: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 3, + }, + valueToKey: map[int]int{ + 3: 1, + }, + }, + }, + { + name: "value removed", + state: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 2, + }, + valueToKey: map[int]int{ + 2: 1, + }, + }, + key: 3, + value: 2, + expectedRemoved: []Entry[int, int]{ + { + Key: 1, + Value: 2, + }, + }, + expectedState: &BiMap[int, int]{ + keyToValue: map[int]int{ + 3: 2, + }, + valueToKey: map[int]int{ + 2: 3, + }, + }, + }, + { + name: "key and value removed", + state: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 2, + 3: 4, + }, + valueToKey: map[int]int{ + 2: 1, + 4: 3, + }, + }, + key: 1, + value: 4, + expectedRemoved: []Entry[int, int]{ + { + Key: 1, + Value: 2, + }, + { + Key: 3, + Value: 4, + }, + }, + expectedState: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 4, + }, + valueToKey: map[int]int{ + 4: 1, + }, + }, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + removed := test.state.Put(test.key, test.value) + require.Equal(test.expectedRemoved, removed) + require.Equal(test.expectedState, test.state) + }) + } +} + +func TestBiMapHasValueAndGetKey(t *testing.T) { + m := New[int, int]() + require.Empty(t, m.Put(1, 2)) + + tests := []struct { + name string + value int + expectedKey int + expectedExists bool + }{ + { + name: "fetch unknown", + value: 3, + expectedKey: 0, + expectedExists: false, + }, + { + name: "fetch known value", + value: 2, + expectedKey: 1, + expectedExists: true, + }, + { + name: "fetch known key", + value: 1, + expectedKey: 0, + expectedExists: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + exists := m.HasValue(test.value) + require.Equal(test.expectedExists, exists) + + key, exists := m.GetKey(test.value) + require.Equal(test.expectedKey, key) + require.Equal(test.expectedExists, exists) + }) + } +} + +func TestBiMapHasKeyAndGetValue(t *testing.T) { + m := New[int, int]() + require.Empty(t, m.Put(1, 2)) + + tests := []struct { + name string + key int + expectedValue int + expectedExists bool + }{ + { + name: "fetch unknown", + key: 3, + expectedValue: 0, + expectedExists: false, + }, + { + name: "fetch known key", + key: 1, + expectedValue: 2, + expectedExists: true, + }, + { + name: "fetch known value", + key: 2, + expectedValue: 0, + expectedExists: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + exists := m.HasKey(test.key) + require.Equal(test.expectedExists, exists) + + value, exists := m.GetValue(test.key) + require.Equal(test.expectedValue, value) + require.Equal(test.expectedExists, exists) + }) + } +} + +func TestBiMapDeleteKey(t *testing.T) { + tests := []struct { + name string + state *BiMap[int, int] + key int + expectedValue int + expectedRemoved bool + expectedState *BiMap[int, int] + }{ + { + name: "none removed", + state: New[int, int](), + key: 1, + expectedValue: 0, + expectedRemoved: false, + expectedState: New[int, int](), + }, + { + name: "key removed", + state: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 2, + }, + valueToKey: map[int]int{ + 2: 1, + }, + }, + key: 1, + expectedValue: 2, + expectedRemoved: true, + expectedState: New[int, int](), + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + value, removed := test.state.DeleteKey(test.key) + require.Equal(test.expectedValue, value) + require.Equal(test.expectedRemoved, removed) + require.Equal(test.expectedState, test.state) + }) + } +} + +func TestBiMapDeleteValue(t *testing.T) { + tests := []struct { + name string + state *BiMap[int, int] + value int + expectedKey int + expectedRemoved bool + expectedState *BiMap[int, int] + }{ + { + name: "none removed", + state: New[int, int](), + value: 1, + expectedKey: 0, + expectedRemoved: false, + expectedState: New[int, int](), + }, + { + name: "key removed", + state: &BiMap[int, int]{ + keyToValue: map[int]int{ + 1: 2, + }, + valueToKey: map[int]int{ + 2: 1, + }, + }, + value: 2, + expectedKey: 1, + expectedRemoved: true, + expectedState: New[int, int](), + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + require := require.New(t) + + key, removed := test.state.DeleteValue(test.value) + require.Equal(test.expectedKey, key) + require.Equal(test.expectedRemoved, removed) + require.Equal(test.expectedState, test.state) + }) + } +} + +func TestBiMapLen(t *testing.T) { + require := require.New(t) + + m := New[int, int]() + require.Zero(m.Len()) + + m.Put(1, 2) + require.Equal(1, m.Len()) + + m.Put(2, 3) + require.Equal(2, m.Len()) + + m.Put(1, 3) + require.Equal(1, m.Len()) + + m.DeleteKey(1) + require.Zero(m.Len()) +} diff --git a/utils/logging/log.go b/utils/logging/log.go index 006c487d608f..a5e6c9d79a05 100644 --- a/utils/logging/log.go +++ b/utils/logging/log.go @@ -5,6 +5,7 @@ package logging import ( "io" + "os" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -67,7 +68,9 @@ func (l *log) Write(p []byte) (int, error) { // TODO: return errors here func (l *log) Stop() { for _, wc := range l.wrappedCores { - _ = wc.Writer.Close() + if wc.Writer != os.Stdout && wc.Writer != os.Stderr { + _ = wc.Writer.Close() + } } } diff --git a/vms/avm/block/builder/builder.go b/vms/avm/block/builder/builder.go index 77bbf38a6a35..a3129d797808 100644 --- a/vms/avm/block/builder/builder.go +++ b/vms/avm/block/builder/builder.go @@ -13,7 +13,7 @@ import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/vms/avm/block" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" @@ -82,7 +82,7 @@ func (b *builder) BuildBlock(context.Context) (snowman.Block, error) { nextTimestamp = preferredTimestamp } - stateDiff, err := states.NewDiff(preferredID, b.manager) + stateDiff, err := state.NewDiff(preferredID, b.manager) if err != nil { return nil, err } @@ -168,15 +168,15 @@ func (b *builder) BuildBlock(context.Context) (snowman.Block, error) { } type stateGetter struct { - state states.Chain + state state.Chain } -func (s stateGetter) GetState(ids.ID) (states.Chain, bool) { +func (s stateGetter) GetState(ids.ID) (state.Chain, bool) { return s.state, true } -func wrapState(parentState states.Chain) (states.Diff, error) { - return states.NewDiff(ids.Empty, stateGetter{ +func wrapState(parentState state.Chain) (state.Diff, error) { + return state.NewDiff(ids.Empty, stateGetter{ state: parentState, }) } diff --git a/vms/avm/block/builder/builder_test.go b/vms/avm/block/builder/builder_test.go index fdab9d6cf064..7faeddbe71e6 100644 --- a/vms/avm/block/builder/builder_test.go +++ b/vms/avm/block/builder/builder_test.go @@ -29,7 +29,7 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/fxs" "github.com/ava-labs/avalanchego/vms/avm/metrics" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" "github.com/ava-labs/avalanchego/vms/components/avax" @@ -108,7 +108,7 @@ func TestBuilderBuildBlock(t *testing.T) { mempool, ) }, - expectedErr: states.ErrMissingParentState, + expectedErr: state.ErrMissingParentState, }, { name: "tx fails semantic verification", @@ -120,7 +120,7 @@ func TestBuilderBuildBlock(t *testing.T) { preferredBlock.EXPECT().Height().Return(preferredHeight) preferredBlock.EXPECT().Timestamp().Return(preferredTimestamp) - preferredState := states.NewMockChain(ctrl) + preferredState := state.NewMockChain(ctrl) preferredState.EXPECT().GetLastAccepted().Return(preferredID) preferredState.EXPECT().GetTimestamp().Return(preferredTimestamp) @@ -164,7 +164,7 @@ func TestBuilderBuildBlock(t *testing.T) { preferredBlock.EXPECT().Height().Return(preferredHeight) preferredBlock.EXPECT().Timestamp().Return(preferredTimestamp) - preferredState := states.NewMockChain(ctrl) + preferredState := state.NewMockChain(ctrl) preferredState.EXPECT().GetLastAccepted().Return(preferredID) preferredState.EXPECT().GetTimestamp().Return(preferredTimestamp) @@ -209,7 +209,7 @@ func TestBuilderBuildBlock(t *testing.T) { preferredBlock.EXPECT().Height().Return(preferredHeight) preferredBlock.EXPECT().Timestamp().Return(preferredTimestamp) - preferredState := states.NewMockChain(ctrl) + preferredState := state.NewMockChain(ctrl) preferredState.EXPECT().GetLastAccepted().Return(preferredID) preferredState.EXPECT().GetTimestamp().Return(preferredTimestamp) @@ -255,7 +255,7 @@ func TestBuilderBuildBlock(t *testing.T) { preferredBlock.EXPECT().Height().Return(preferredHeight) preferredBlock.EXPECT().Timestamp().Return(preferredTimestamp) - preferredState := states.NewMockChain(ctrl) + preferredState := state.NewMockChain(ctrl) preferredState.EXPECT().GetLastAccepted().Return(preferredID) preferredState.EXPECT().GetTimestamp().Return(preferredTimestamp) @@ -353,7 +353,7 @@ func TestBuilderBuildBlock(t *testing.T) { clock := &mockable.Clock{} clock.Set(preferredTimestamp.Add(-2 * time.Second)) - preferredState := states.NewMockChain(ctrl) + preferredState := state.NewMockChain(ctrl) preferredState.EXPECT().GetLastAccepted().Return(preferredID) preferredState.EXPECT().GetTimestamp().Return(preferredTimestamp) @@ -427,7 +427,7 @@ func TestBuilderBuildBlock(t *testing.T) { clock := &mockable.Clock{} clock.Set(now) - preferredState := states.NewMockChain(ctrl) + preferredState := state.NewMockChain(ctrl) preferredState.EXPECT().GetLastAccepted().Return(preferredID) preferredState.EXPECT().GetTimestamp().Return(preferredTimestamp) @@ -526,7 +526,7 @@ func TestBlockBuilderAddLocalTx(t *testing.T) { baseDB := versiondb.New(memdb.New()) - state, err := states.New(baseDB, parser, registerer, trackChecksums) + state, err := state.New(baseDB, parser, registerer, trackChecksums) require.NoError(err) clk := &mockable.Clock{} diff --git a/vms/avm/block/executor/block.go b/vms/avm/block/executor/block.go index 418ca0b539ca..5e643ad4ecc0 100644 --- a/vms/avm/block/executor/block.go +++ b/vms/avm/block/executor/block.go @@ -17,7 +17,7 @@ import ( "github.com/ava-labs/avalanchego/snow/choices" "github.com/ava-labs/avalanchego/snow/consensus/snowman" "github.com/ava-labs/avalanchego/vms/avm/block" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs/executor" ) @@ -106,7 +106,7 @@ func (b *Block) Verify(context.Context) error { ) } - stateDiff, err := states.NewDiff(parentID, b.manager) + stateDiff, err := state.NewDiff(parentID, b.manager) if err != nil { return err } diff --git a/vms/avm/block/executor/block_test.go b/vms/avm/block/executor/block_test.go index 9d7f291a8f60..da965884ae58 100644 --- a/vms/avm/block/executor/block_test.go +++ b/vms/avm/block/executor/block_test.go @@ -24,7 +24,7 @@ import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/metrics" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/executor" "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" @@ -153,7 +153,7 @@ func TestBlockVerify(t *testing.T) { parentID := ids.GenerateTestID() mockBlock.EXPECT().Parent().Return(parentID).AnyTimes() - mockState := states.NewMockState(ctrl) + mockState := state.NewMockState(ctrl) mockState.EXPECT().GetBlock(parentID).Return(nil, errTest) return &Block{ Block: mockBlock, @@ -186,7 +186,7 @@ func TestBlockVerify(t *testing.T) { parentID := ids.GenerateTestID() mockBlock.EXPECT().Parent().Return(parentID).AnyTimes() - mockState := states.NewMockState(ctrl) + mockState := state.NewMockState(ctrl) mockParentBlock := block.NewMockBlock(ctrl) mockParentBlock.EXPECT().Height().Return(blockHeight) // Should be blockHeight - 1 mockState.EXPECT().GetBlock(parentID).Return(mockParentBlock, nil) @@ -226,7 +226,7 @@ func TestBlockVerify(t *testing.T) { mockParentBlock := block.NewMockBlock(ctrl) mockParentBlock.EXPECT().Height().Return(blockHeight - 1) - mockParentState := states.NewMockDiff(ctrl) + mockParentState := state.NewMockDiff(ctrl) mockParentState.EXPECT().GetLastAccepted().Return(parentID) mockParentState.EXPECT().GetTimestamp().Return(blockTimestamp.Add(1)) @@ -271,7 +271,7 @@ func TestBlockVerify(t *testing.T) { mockParentBlock := block.NewMockBlock(ctrl) mockParentBlock.EXPECT().Height().Return(blockHeight - 1) - mockParentState := states.NewMockDiff(ctrl) + mockParentState := state.NewMockDiff(ctrl) mockParentState.EXPECT().GetLastAccepted().Return(parentID) mockParentState.EXPECT().GetTimestamp().Return(blockTimestamp) @@ -321,7 +321,7 @@ func TestBlockVerify(t *testing.T) { mockParentBlock := block.NewMockBlock(ctrl) mockParentBlock.EXPECT().Height().Return(blockHeight - 1) - mockParentState := states.NewMockDiff(ctrl) + mockParentState := state.NewMockDiff(ctrl) mockParentState.EXPECT().GetLastAccepted().Return(parentID) mockParentState.EXPECT().GetTimestamp().Return(blockTimestamp) @@ -399,7 +399,7 @@ func TestBlockVerify(t *testing.T) { mockParentBlock := block.NewMockBlock(ctrl) mockParentBlock.EXPECT().Height().Return(blockHeight - 1) - mockParentState := states.NewMockDiff(ctrl) + mockParentState := state.NewMockDiff(ctrl) mockParentState.EXPECT().GetLastAccepted().Return(parentID) mockParentState.EXPECT().GetTimestamp().Return(blockTimestamp) @@ -461,7 +461,7 @@ func TestBlockVerify(t *testing.T) { mockParentBlock := block.NewMockBlock(ctrl) mockParentBlock.EXPECT().Height().Return(blockHeight - 1) - mockParentState := states.NewMockDiff(ctrl) + mockParentState := state.NewMockDiff(ctrl) mockParentState.EXPECT().GetLastAccepted().Return(parentID) mockParentState.EXPECT().GetTimestamp().Return(blockTimestamp) @@ -509,7 +509,7 @@ func TestBlockVerify(t *testing.T) { mockParentBlock := block.NewMockBlock(ctrl) mockParentBlock.EXPECT().Height().Return(blockHeight - 1) - mockParentState := states.NewMockDiff(ctrl) + mockParentState := state.NewMockDiff(ctrl) mockParentState.EXPECT().GetLastAccepted().Return(parentID) mockParentState.EXPECT().GetTimestamp().Return(blockTimestamp) @@ -616,11 +616,11 @@ func TestBlockAccept(t *testing.T) { mempool := mempool.NewMockMempool(ctrl) mempool.EXPECT().Remove(gomock.Any()).AnyTimes() - mockManagerState := states.NewMockState(ctrl) + mockManagerState := state.NewMockState(ctrl) mockManagerState.EXPECT().CommitBatch().Return(nil, errTest) mockManagerState.EXPECT().Abort() - mockOnAcceptState := states.NewMockDiff(ctrl) + mockOnAcceptState := state.NewMockDiff(ctrl) mockOnAcceptState.EXPECT().Apply(mockManagerState) return &Block{ @@ -654,7 +654,7 @@ func TestBlockAccept(t *testing.T) { mempool := mempool.NewMockMempool(ctrl) mempool.EXPECT().Remove(gomock.Any()).AnyTimes() - mockManagerState := states.NewMockState(ctrl) + mockManagerState := state.NewMockState(ctrl) // Note the returned batch is nil but not used // because we mock the call to shared memory mockManagerState.EXPECT().CommitBatch().Return(nil, nil) @@ -663,7 +663,7 @@ func TestBlockAccept(t *testing.T) { mockSharedMemory := atomic.NewMockSharedMemory(ctrl) mockSharedMemory.EXPECT().Apply(gomock.Any(), gomock.Any()).Return(errTest) - mockOnAcceptState := states.NewMockDiff(ctrl) + mockOnAcceptState := state.NewMockDiff(ctrl) mockOnAcceptState.EXPECT().Apply(mockManagerState) return &Block{ @@ -698,7 +698,7 @@ func TestBlockAccept(t *testing.T) { mempool := mempool.NewMockMempool(ctrl) mempool.EXPECT().Remove(gomock.Any()).AnyTimes() - mockManagerState := states.NewMockState(ctrl) + mockManagerState := state.NewMockState(ctrl) // Note the returned batch is nil but not used // because we mock the call to shared memory mockManagerState.EXPECT().CommitBatch().Return(nil, nil) @@ -707,7 +707,7 @@ func TestBlockAccept(t *testing.T) { mockSharedMemory := atomic.NewMockSharedMemory(ctrl) mockSharedMemory.EXPECT().Apply(gomock.Any(), gomock.Any()).Return(nil) - mockOnAcceptState := states.NewMockDiff(ctrl) + mockOnAcceptState := state.NewMockDiff(ctrl) mockOnAcceptState.EXPECT().Apply(mockManagerState) metrics := metrics.NewMockMetrics(ctrl) @@ -748,7 +748,7 @@ func TestBlockAccept(t *testing.T) { mempool := mempool.NewMockMempool(ctrl) mempool.EXPECT().Remove(gomock.Any()).AnyTimes() - mockManagerState := states.NewMockState(ctrl) + mockManagerState := state.NewMockState(ctrl) // Note the returned batch is nil but not used // because we mock the call to shared memory mockManagerState.EXPECT().CommitBatch().Return(nil, nil) @@ -758,7 +758,7 @@ func TestBlockAccept(t *testing.T) { mockSharedMemory := atomic.NewMockSharedMemory(ctrl) mockSharedMemory.EXPECT().Apply(gomock.Any(), gomock.Any()).Return(nil) - mockOnAcceptState := states.NewMockDiff(ctrl) + mockOnAcceptState := state.NewMockDiff(ctrl) mockOnAcceptState.EXPECT().Apply(mockManagerState) metrics := metrics.NewMockMetrics(ctrl) @@ -859,7 +859,7 @@ func TestBlockReject(t *testing.T) { mempool.EXPECT().Add(validTx).Return(nil) // Only add the one that passes verification preferredID := ids.GenerateTestID() - mockPreferredState := states.NewMockDiff(ctrl) + mockPreferredState := state.NewMockDiff(ctrl) mockPreferredState.EXPECT().GetLastAccepted().Return(ids.GenerateTestID()).AnyTimes() mockPreferredState.EXPECT().GetTimestamp().Return(time.Now()).AnyTimes() @@ -918,7 +918,7 @@ func TestBlockReject(t *testing.T) { mempool.EXPECT().Add(tx2).Return(nil) preferredID := ids.GenerateTestID() - mockPreferredState := states.NewMockDiff(ctrl) + mockPreferredState := state.NewMockDiff(ctrl) mockPreferredState.EXPECT().GetLastAccepted().Return(ids.GenerateTestID()).AnyTimes() mockPreferredState.EXPECT().GetTimestamp().Return(time.Now()).AnyTimes() @@ -1014,7 +1014,7 @@ func TestBlockStatus(t *testing.T) { mockBlock := block.NewMockBlock(ctrl) mockBlock.EXPECT().ID().Return(blockID).AnyTimes() - mockState := states.NewMockState(ctrl) + mockState := state.NewMockState(ctrl) mockState.EXPECT().GetBlock(blockID).Return(nil, nil) return &Block{ @@ -1034,7 +1034,7 @@ func TestBlockStatus(t *testing.T) { mockBlock := block.NewMockBlock(ctrl) mockBlock.EXPECT().ID().Return(blockID).AnyTimes() - mockState := states.NewMockState(ctrl) + mockState := state.NewMockState(ctrl) mockState.EXPECT().GetBlock(blockID).Return(nil, database.ErrNotFound) return &Block{ diff --git a/vms/avm/block/executor/manager.go b/vms/avm/block/executor/manager.go index dd9b8bfab400..48eea701bbd9 100644 --- a/vms/avm/block/executor/manager.go +++ b/vms/avm/block/executor/manager.go @@ -13,7 +13,7 @@ import ( "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/metrics" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/executor" "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" @@ -27,7 +27,7 @@ var ( ) type Manager interface { - states.Versions + state.Versions // Returns the ID of the most recently accepted block. LastAccepted() ids.ID @@ -51,7 +51,7 @@ type Manager interface { func NewManager( mempool mempool.Mempool, metrics metrics.Metrics, - state states.State, + state state.State, backend *executor.Backend, clk *mockable.Clock, onAccept func(*txs.Tx) error, @@ -72,7 +72,7 @@ func NewManager( type manager struct { backend *executor.Backend - state states.State + state state.State metrics metrics.Metrics mempool mempool.Mempool clk *mockable.Clock @@ -93,12 +93,12 @@ type manager struct { type blockState struct { statelessBlock block.Block - onAcceptState states.Diff + onAcceptState state.Diff importedInputs set.Set[ids.ID] atomicRequests map[ids.ID]*atomic.Requests } -func (m *manager) GetState(blkID ids.ID) (states.Chain, bool) { +func (m *manager) GetState(blkID ids.ID) (state.Chain, bool) { // If the block is in the map, it is processing. if state, ok := m.blkIDToState[blkID]; ok { return state.onAcceptState, true @@ -155,7 +155,7 @@ func (m *manager) VerifyTx(tx *txs.Tx) error { return err } - stateDiff, err := states.NewDiff(m.preferred, m) + stateDiff, err := state.NewDiff(m.preferred, m) if err != nil { return err } diff --git a/vms/avm/block/executor/manager_test.go b/vms/avm/block/executor/manager_test.go index c21201417add..904154bf7030 100644 --- a/vms/avm/block/executor/manager_test.go +++ b/vms/avm/block/executor/manager_test.go @@ -15,7 +15,7 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/vms/avm/block" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/executor" ) @@ -31,7 +31,7 @@ func TestManagerGetStatelessBlock(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) m := &manager{ state: state, blkIDToState: map[ids.ID]*blockState{}, @@ -73,16 +73,16 @@ func TestManagerGetState(t *testing.T) { require := require.New(t) ctrl := gomock.NewController(t) - state := states.NewMockState(ctrl) + s := state.NewMockState(ctrl) m := &manager{ - state: state, + state: s, blkIDToState: map[ids.ID]*blockState{}, lastAccepted: ids.GenerateTestID(), } // Case: Block is in memory { - diff := states.NewMockDiff(ctrl) + diff := state.NewMockDiff(ctrl) blkID := ids.GenerateTestID() m.blkIDToState[blkID] = &blockState{ onAcceptState: diff, @@ -97,14 +97,14 @@ func TestManagerGetState(t *testing.T) { blkID := ids.GenerateTestID() gotState, ok := m.GetState(blkID) require.False(ok) - require.Equal(state, gotState) + require.Equal(s, gotState) } // Case: Block isn't in memory; block is last accepted { gotState, ok := m.GetState(m.lastAccepted) require.True(ok) - require.Equal(state, gotState) + require.Equal(s, gotState) } } @@ -164,7 +164,7 @@ func TestManagerVerifyTx(t *testing.T) { preferred := ids.GenerateTestID() // These values don't matter for this test - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(preferred) state.EXPECT().GetTimestamp().Return(time.Time{}) @@ -197,7 +197,7 @@ func TestManagerVerifyTx(t *testing.T) { preferred := ids.GenerateTestID() // These values don't matter for this test - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(preferred) state.EXPECT().GetTimestamp().Return(time.Time{}) @@ -237,7 +237,7 @@ func TestManagerVerifyTx(t *testing.T) { preferred.EXPECT().Parent().Return(lastAcceptedID).AnyTimes() // These values don't matter for this test - diffState := states.NewMockDiff(ctrl) + diffState := state.NewMockDiff(ctrl) diffState.EXPECT().GetLastAccepted().Return(preferredID) diffState.EXPECT().GetTimestamp().Return(time.Time{}) @@ -276,7 +276,7 @@ func TestManagerVerifyTx(t *testing.T) { preferred := ids.GenerateTestID() // These values don't matter for this test - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(preferred) state.EXPECT().GetTimestamp().Return(time.Time{}) diff --git a/vms/avm/block/executor/mock_manager.go b/vms/avm/block/executor/mock_manager.go index b3560f2e8afa..5e27089b19fa 100644 --- a/vms/avm/block/executor/mock_manager.go +++ b/vms/avm/block/executor/mock_manager.go @@ -14,7 +14,7 @@ import ( snowman "github.com/ava-labs/avalanchego/snow/consensus/snowman" set "github.com/ava-labs/avalanchego/utils/set" block "github.com/ava-labs/avalanchego/vms/avm/block" - states "github.com/ava-labs/avalanchego/vms/avm/states" + state "github.com/ava-labs/avalanchego/vms/avm/state" txs "github.com/ava-labs/avalanchego/vms/avm/txs" gomock "go.uber.org/mock/gomock" ) @@ -58,10 +58,10 @@ func (mr *MockManagerMockRecorder) GetBlock(arg0 interface{}) *gomock.Call { } // GetState mocks base method. -func (m *MockManager) GetState(arg0 ids.ID) (states.Chain, bool) { +func (m *MockManager) GetState(arg0 ids.ID) (state.Chain, bool) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetState", arg0) - ret0, _ := ret[0].(states.Chain) + ret0, _ := ret[0].(state.Chain) ret1, _ := ret[1].(bool) return ret0, ret1 } diff --git a/vms/avm/service_test.go b/vms/avm/service_test.go index 67a92a663879..19cacb158d13 100644 --- a/vms/avm/service_test.go +++ b/vms/avm/service_test.go @@ -36,7 +36,7 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/block/executor" "github.com/ava-labs/avalanchego/vms/avm/config" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/index" @@ -2266,7 +2266,7 @@ func TestServiceGetBlockByHeight(t *testing.T) { { name: "block height not found", serviceAndExpectedBlockFunc: func(_ *testing.T, ctrl *gomock.Controller) (*Service, interface{}) { - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(ids.Empty, database.ErrNotFound) manager := executor.NewMockManager(ctrl) @@ -2286,7 +2286,7 @@ func TestServiceGetBlockByHeight(t *testing.T) { { name: "block not found", serviceAndExpectedBlockFunc: func(_ *testing.T, ctrl *gomock.Controller) (*Service, interface{}) { - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil) manager := executor.NewMockManager(ctrl) @@ -2311,7 +2311,7 @@ func TestServiceGetBlockByHeight(t *testing.T) { block.EXPECT().InitCtx(gomock.Any()) block.EXPECT().Txs().Return(nil) - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil) manager := executor.NewMockManager(ctrl) @@ -2336,7 +2336,7 @@ func TestServiceGetBlockByHeight(t *testing.T) { blockBytes := []byte("hi mom") block.EXPECT().Bytes().Return(blockBytes) - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil) expected, err := formatting.Encode(formatting.Hex, blockBytes) @@ -2364,7 +2364,7 @@ func TestServiceGetBlockByHeight(t *testing.T) { blockBytes := []byte("hi mom") block.EXPECT().Bytes().Return(blockBytes) - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil) expected, err := formatting.Encode(formatting.HexC, blockBytes) @@ -2392,7 +2392,7 @@ func TestServiceGetBlockByHeight(t *testing.T) { blockBytes := []byte("hi mom") block.EXPECT().Bytes().Return(blockBytes) - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetBlockIDAtHeight(blockHeight).Return(blockID, nil) expected, err := formatting.Encode(formatting.HexNC, blockBytes) @@ -2470,7 +2470,7 @@ func TestServiceGetHeight(t *testing.T) { { name: "block not found", serviceFunc: func(ctrl *gomock.Controller) *Service { - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(blockID) manager := executor.NewMockManager(ctrl) @@ -2490,7 +2490,7 @@ func TestServiceGetHeight(t *testing.T) { { name: "happy path", serviceFunc: func(ctrl *gomock.Controller) *Service { - state := states.NewMockState(ctrl) + state := state.NewMockState(ctrl) state.EXPECT().GetLastAccepted().Return(blockID) block := block.NewMockBlock(ctrl) diff --git a/vms/avm/states/diff.go b/vms/avm/state/diff.go similarity index 99% rename from vms/avm/states/diff.go rename to vms/avm/state/diff.go index 2ca6d58cd5ee..1d53fa37da3e 100644 --- a/vms/avm/states/diff.go +++ b/vms/avm/state/diff.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package states +package state import ( "errors" diff --git a/vms/avm/states/mock_states.go b/vms/avm/state/mock_state.go similarity index 99% rename from vms/avm/states/mock_states.go rename to vms/avm/state/mock_state.go index 007b8622042e..3bb615283ce6 100644 --- a/vms/avm/states/mock_states.go +++ b/vms/avm/state/mock_state.go @@ -2,10 +2,10 @@ // See the file LICENSE for licensing terms. // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/avalanchego/vms/avm/states (interfaces: Chain,State,Diff) +// Source: github.com/ava-labs/avalanchego/vms/avm/state (interfaces: Chain,State,Diff) -// Package states is a generated GoMock package. -package states +// Package state is a generated GoMock package. +package state import ( reflect "reflect" diff --git a/vms/avm/states/state.go b/vms/avm/state/state.go similarity index 99% rename from vms/avm/states/state.go rename to vms/avm/state/state.go index 1167cdb37dce..e290f093aa22 100644 --- a/vms/avm/states/state.go +++ b/vms/avm/state/state.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package states +package state import ( "bytes" diff --git a/vms/avm/states/state_test.go b/vms/avm/state/state_test.go similarity index 99% rename from vms/avm/states/state_test.go rename to vms/avm/state/state_test.go index b64fa3aa7933..c97836aee794 100644 --- a/vms/avm/states/state_test.go +++ b/vms/avm/state/state_test.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package states +package state import ( "testing" diff --git a/vms/avm/states/versions.go b/vms/avm/state/versions.go similarity index 95% rename from vms/avm/states/versions.go rename to vms/avm/state/versions.go index 409c47becfff..da84182bb683 100644 --- a/vms/avm/states/versions.go +++ b/vms/avm/state/versions.go @@ -1,7 +1,7 @@ // Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. // See the file LICENSE for licensing terms. -package states +package state import "github.com/ava-labs/avalanchego/ids" diff --git a/vms/avm/txs/executor/executor.go b/vms/avm/txs/executor/executor.go index 040b1d9c816f..6a5991cade04 100644 --- a/vms/avm/txs/executor/executor.go +++ b/vms/avm/txs/executor/executor.go @@ -10,7 +10,7 @@ import ( "github.com/ava-labs/avalanchego/codec" "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/set" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" ) @@ -19,7 +19,7 @@ var _ txs.Visitor = (*Executor)(nil) type Executor struct { Codec codec.Manager - State states.Chain // state will be modified + State state.Chain // state will be modified Tx *txs.Tx Inputs set.Set[ids.ID] // imported inputs AtomicRequests map[ids.ID]*atomic.Requests // may be nil diff --git a/vms/avm/txs/executor/executor_test.go b/vms/avm/txs/executor/executor_test.go index 042ae39a9048..81d301ad6bae 100644 --- a/vms/avm/txs/executor/executor_test.go +++ b/vms/avm/txs/executor/executor_test.go @@ -19,7 +19,7 @@ import ( "github.com/ava-labs/avalanchego/utils/units" "github.com/ava-labs/avalanchego/vms/avm/block" "github.com/ava-labs/avalanchego/vms/avm/fxs" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -44,7 +44,7 @@ func TestBaseTxExecutor(t *testing.T) { db := memdb.New() vdb := versiondb.New(db) registerer := prometheus.NewRegistry() - state, err := states.New(vdb, parser, registerer, trackChecksums) + state, err := state.New(vdb, parser, registerer, trackChecksums) require.NoError(err) utxoID := avax.UTXOID{ @@ -149,7 +149,7 @@ func TestCreateAssetTxExecutor(t *testing.T) { db := memdb.New() vdb := versiondb.New(db) registerer := prometheus.NewRegistry() - state, err := states.New(vdb, parser, registerer, trackChecksums) + state, err := state.New(vdb, parser, registerer, trackChecksums) require.NoError(err) utxoID := avax.UTXOID{ @@ -292,7 +292,7 @@ func TestOperationTxExecutor(t *testing.T) { db := memdb.New() vdb := versiondb.New(db) registerer := prometheus.NewRegistry() - state, err := states.New(vdb, parser, registerer, trackChecksums) + state, err := state.New(vdb, parser, registerer, trackChecksums) require.NoError(err) outputOwners := secp256k1fx.OutputOwners{ diff --git a/vms/avm/txs/executor/semantic_verifier.go b/vms/avm/txs/executor/semantic_verifier.go index 0a8d59083255..1fd94fb0e131 100644 --- a/vms/avm/txs/executor/semantic_verifier.go +++ b/vms/avm/txs/executor/semantic_verifier.go @@ -9,7 +9,7 @@ import ( "reflect" "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -26,7 +26,7 @@ var ( type SemanticVerifier struct { *Backend - State states.ReadOnlyChain + State state.ReadOnlyChain Tx *txs.Tx } diff --git a/vms/avm/txs/executor/semantic_verifier_test.go b/vms/avm/txs/executor/semantic_verifier_test.go index 72638762c39b..7c659f7ec227 100644 --- a/vms/avm/txs/executor/semantic_verifier_test.go +++ b/vms/avm/txs/executor/semantic_verifier_test.go @@ -22,7 +22,7 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/vms/avm/fxs" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/components/avax" "github.com/ava-labs/avalanchego/vms/components/verify" @@ -117,14 +117,14 @@ func TestSemanticVerifierBaseTx(t *testing.T) { tests := []struct { name string - stateFunc func(*gomock.Controller) states.Chain + stateFunc func(*gomock.Controller) state.Chain txFunc func(*require.Assertions) *txs.Tx err error }{ { name: "valid", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil) state.EXPECT().GetTx(asset.ID).Return(&createAssetTx, nil) @@ -147,8 +147,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "assetID mismatch", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) utxo := utxo utxo.Asset.ID = ids.GenerateTestID() @@ -173,8 +173,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "not allowed input feature extension", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) unsignedCreateAssetTx := unsignedCreateAssetTx unsignedCreateAssetTx.States = nil @@ -204,8 +204,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "invalid signature", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil) state.EXPECT().GetTx(asset.ID).Return(&createAssetTx, nil) @@ -228,8 +228,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "missing UTXO", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(nil, database.ErrNotFound) @@ -251,8 +251,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "invalid UTXO amount", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) output := output output.Amt-- @@ -281,8 +281,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "not allowed output feature extension", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) unsignedCreateAssetTx := unsignedCreateAssetTx unsignedCreateAssetTx.States = nil @@ -317,8 +317,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "unknown asset", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil) state.EXPECT().GetTx(asset.ID).Return(nil, database.ErrNotFound) @@ -341,8 +341,8 @@ func TestSemanticVerifierBaseTx(t *testing.T) { }, { name: "not an asset", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) tx := txs.Tx{ Unsigned: &baseTx, @@ -483,14 +483,14 @@ func TestSemanticVerifierExportTx(t *testing.T) { tests := []struct { name string - stateFunc func(*gomock.Controller) states.Chain + stateFunc func(*gomock.Controller) state.Chain txFunc func(*require.Assertions) *txs.Tx err error }{ { name: "valid", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil) state.EXPECT().GetTx(asset.ID).Return(&createAssetTx, nil) @@ -513,8 +513,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "assetID mismatch", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) utxo := utxo utxo.Asset.ID = ids.GenerateTestID() @@ -539,8 +539,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "not allowed input feature extension", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) unsignedCreateAssetTx := unsignedCreateAssetTx unsignedCreateAssetTx.States = nil @@ -570,8 +570,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "invalid signature", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil) state.EXPECT().GetTx(asset.ID).Return(&createAssetTx, nil) @@ -594,8 +594,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "missing UTXO", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(nil, database.ErrNotFound) @@ -617,8 +617,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "invalid UTXO amount", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) output := output output.Amt-- @@ -647,8 +647,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "not allowed output feature extension", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) unsignedCreateAssetTx := unsignedCreateAssetTx unsignedCreateAssetTx.States = nil @@ -683,8 +683,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "unknown asset", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil) state.EXPECT().GetTx(asset.ID).Return(nil, database.ErrNotFound) @@ -707,8 +707,8 @@ func TestSemanticVerifierExportTx(t *testing.T) { }, { name: "not an asset", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) tx := txs.Tx{ Unsigned: &baseTx, @@ -849,7 +849,7 @@ func TestSemanticVerifierExportTxDifferentSubnet(t *testing.T) { Unsigned: &unsignedCreateAssetTx, } - state := states.NewMockChain(ctrl) + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil) state.EXPECT().GetTx(asset.ID).Return(&createAssetTx, nil) @@ -999,14 +999,14 @@ func TestSemanticVerifierImportTx(t *testing.T) { } tests := []struct { name string - stateFunc func(*gomock.Controller) states.Chain + stateFunc func(*gomock.Controller) state.Chain txFunc func(*require.Assertions) *txs.Tx expectedErr error }{ { name: "valid", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil).AnyTimes() state.EXPECT().GetTx(asset.ID).Return(&createAssetTx, nil).AnyTimes() return state @@ -1018,8 +1018,8 @@ func TestSemanticVerifierImportTx(t *testing.T) { }, { name: "not allowed input feature extension", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) unsignedCreateAssetTx := unsignedCreateAssetTx unsignedCreateAssetTx.States = nil createAssetTx := txs.Tx{ @@ -1036,8 +1036,8 @@ func TestSemanticVerifierImportTx(t *testing.T) { }, { name: "invalid signature", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil).AnyTimes() state.EXPECT().GetTx(asset.ID).Return(&createAssetTx, nil).AnyTimes() return state @@ -1058,8 +1058,8 @@ func TestSemanticVerifierImportTx(t *testing.T) { }, { name: "not allowed output feature extension", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) unsignedCreateAssetTx := unsignedCreateAssetTx unsignedCreateAssetTx.States = nil createAssetTx := txs.Tx{ @@ -1087,8 +1087,8 @@ func TestSemanticVerifierImportTx(t *testing.T) { }, { name: "unknown asset", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) state.EXPECT().GetUTXO(utxoID.InputID()).Return(&utxo, nil).AnyTimes() state.EXPECT().GetTx(asset.ID).Return(nil, database.ErrNotFound) return state @@ -1100,8 +1100,8 @@ func TestSemanticVerifierImportTx(t *testing.T) { }, { name: "not an asset", - stateFunc: func(ctrl *gomock.Controller) states.Chain { - state := states.NewMockChain(ctrl) + stateFunc: func(ctrl *gomock.Controller) state.Chain { + state := state.NewMockChain(ctrl) tx := txs.Tx{ Unsigned: &baseTx, } diff --git a/vms/avm/vm.go b/vms/avm/vm.go index cae4514ff3a6..36049befd07c 100644 --- a/vms/avm/vm.go +++ b/vms/avm/vm.go @@ -38,7 +38,7 @@ import ( "github.com/ava-labs/avalanchego/vms/avm/config" "github.com/ava-labs/avalanchego/vms/avm/metrics" "github.com/ava-labs/avalanchego/vms/avm/network" - "github.com/ava-labs/avalanchego/vms/avm/states" + "github.com/ava-labs/avalanchego/vms/avm/state" "github.com/ava-labs/avalanchego/vms/avm/txs" "github.com/ava-labs/avalanchego/vms/avm/txs/mempool" "github.com/ava-labs/avalanchego/vms/avm/utxo" @@ -91,7 +91,7 @@ type VM struct { appSender common.AppSender // State management - state states.State + state state.State // Set to true once this VM is marked as `Bootstrapped` by the engine bootstrapped bool @@ -220,7 +220,7 @@ func (vm *VM) Initialize( vm.AtomicUTXOManager = avax.NewAtomicUTXOManager(ctx.SharedMemory, codec) vm.Spender = utxo.NewSpender(&vm.clock, codec) - state, err := states.New( + state, err := state.New( vm.db, vm.parser, vm.registerer, diff --git a/vms/platformvm/api/static_service.go b/vms/platformvm/api/static_service.go index 1cf2fbe29096..ea1cfcb2d63f 100644 --- a/vms/platformvm/api/static_service.go +++ b/vms/platformvm/api/static_service.go @@ -138,10 +138,11 @@ type PermissionlessValidator struct { // GenesisPermissionlessValidator should to be used for genesis validators only. type GenesisPermissionlessValidator struct { GenesisValidator - RewardOwner *Owner `json:"rewardOwner,omitempty"` - DelegationFee json.Float32 `json:"delegationFee"` - ExactDelegationFee *json.Uint32 `json:"exactDelegationFee,omitempty"` - Staked []UTXO `json:"staked,omitempty"` + RewardOwner *Owner `json:"rewardOwner,omitempty"` + DelegationFee json.Float32 `json:"delegationFee"` + ExactDelegationFee *json.Uint32 `json:"exactDelegationFee,omitempty"` + Staked []UTXO `json:"staked,omitempty"` + Signer *signer.ProofOfPossession `json:"signer,omitempty"` } // PermissionedValidator is the repr. of a permissioned validator sent over APIs. @@ -315,21 +316,39 @@ func (*StaticService) BuildGenesis(_ *http.Request, args *BuildGenesisArgs, repl delegationFee = uint32(*vdr.ExactDelegationFee) } - tx := &txs.Tx{Unsigned: &txs.AddValidatorTx{ - BaseTx: txs.BaseTx{BaseTx: avax.BaseTx{ + var ( + baseTx = txs.BaseTx{BaseTx: avax.BaseTx{ NetworkID: uint32(args.NetworkID), BlockchainID: ids.Empty, - }}, - Validator: txs.Validator{ + }} + validator = txs.Validator{ NodeID: vdr.NodeID, Start: uint64(args.Time), End: uint64(vdr.EndTime), Wght: weight, - }, - StakeOuts: stake, - RewardsOwner: owner, - DelegationShares: delegationFee, - }} + } + tx *txs.Tx + ) + if vdr.Signer == nil { + tx = &txs.Tx{Unsigned: &txs.AddValidatorTx{ + BaseTx: baseTx, + Validator: validator, + StakeOuts: stake, + RewardsOwner: owner, + DelegationShares: delegationFee, + }} + } else { + tx = &txs.Tx{Unsigned: &txs.AddPermissionlessValidatorTx{ + BaseTx: baseTx, + Validator: validator, + Signer: vdr.Signer, + StakeOuts: stake, + ValidatorRewardsOwner: owner, + DelegatorRewardsOwner: owner, + DelegationShares: delegationFee, + }} + } + if err := tx.Initialize(txs.GenesisCodec); err != nil { return err } diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index 8923857d579e..b8476e19b032 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -13,7 +13,6 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/consensus/snowman" - "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils/timer" "github.com/ava-labs/avalanchego/utils/timer/mockable" "github.com/ava-labs/avalanchego/utils/units" @@ -40,7 +39,11 @@ var ( type Builder interface { mempool.Mempool - mempool.BlockTimer + + // ResetBlockTimer schedules a timer to notify the consensus engine once + // there is a block ready to be built. If a block is ready to be built when + // this function is called, the engine will be notified directly. + ResetBlockTimer() // BuildBlock is called on timer clock to attempt to create // next block @@ -58,9 +61,6 @@ type builder struct { txExecutorBackend *txexecutor.Backend blkManager blockexecutor.Manager - // channel to send messages to the consensus engine - toEngine chan<- common.Message - // This timer goes off when it is time for the next validator to add/leave // the validator set. When it goes off ResetTimer() is called, potentially // triggering creation of a new block. @@ -72,14 +72,12 @@ func New( txBuilder txbuilder.Builder, txExecutorBackend *txexecutor.Backend, blkManager blockexecutor.Manager, - toEngine chan<- common.Message, ) Builder { builder := &builder{ Mempool: mempool, txBuilder: txBuilder, txExecutorBackend: txExecutorBackend, blkManager: blkManager, - toEngine: toEngine, } builder.timer = timer.NewTimer(builder.setNextBuildBlockTime) @@ -192,7 +190,7 @@ func (b *builder) setNextBuildBlockTime() { if _, err := b.buildBlock(); err == nil { // We can build a block now - b.notifyBlockReady() + b.Mempool.RequestBuildBlock(true /*=emptyBlockPermitted*/) return } @@ -229,16 +227,6 @@ func (b *builder) setNextBuildBlockTime() { b.timer.SetTimeoutIn(waitTime) } -// notifyBlockReady tells the consensus engine that a new block is ready to be -// created -func (b *builder) notifyBlockReady() { - select { - case b.toEngine <- common.PendingTxs: - default: - b.txExecutorBackend.Ctx.Log.Debug("dropping message to consensus engine") - } -} - // [timestamp] is min(max(now, parent timestamp), next staker change time) func buildBlock( builder *builder, diff --git a/vms/platformvm/block/builder/helpers_test.go b/vms/platformvm/block/builder/helpers_test.go index 84778add2864..de37d08ff0dd 100644 --- a/vms/platformvm/block/builder/helpers_test.go +++ b/vms/platformvm/block/builder/helpers_test.go @@ -169,7 +169,7 @@ func newEnvironment(t *testing.T) *environment { metrics, err := metrics.New("", registerer) require.NoError(err) - res.mempool, err = mempool.New("mempool", registerer, res) + res.mempool, err = mempool.New("mempool", registerer, nil) require.NoError(err) res.blkManager = blockexecutor.NewManager( @@ -193,7 +193,6 @@ func newEnvironment(t *testing.T) *environment { res.txBuilder, &res.backend, res.blkManager, - nil, // toEngine, ) res.blkManager.SetPreference(genesisID) diff --git a/vms/platformvm/block/executor/helpers_test.go b/vms/platformvm/block/executor/helpers_test.go index ff0aa13a2ea1..778d9b203181 100644 --- a/vms/platformvm/block/executor/helpers_test.go +++ b/vms/platformvm/block/executor/helpers_test.go @@ -63,8 +63,6 @@ const ( ) var ( - _ mempool.BlockTimer = (*environment)(nil) - defaultMinStakingDuration = 24 * time.Hour defaultMaxStakingDuration = 365 * 24 * time.Hour defaultGenesisTime = time.Date(1997, 1, 1, 0, 0, 0, 0, time.UTC) @@ -131,10 +129,6 @@ type environment struct { backend *executor.Backend } -func (*environment) ResetBlockTimer() { - // dummy call, do nothing for now -} - func newEnvironment(t *testing.T, ctrl *gomock.Controller) *environment { res := &environment{ isBootstrapped: &utils.Atomic[bool]{}, @@ -199,7 +193,7 @@ func newEnvironment(t *testing.T, ctrl *gomock.Controller) *environment { metrics := metrics.Noop var err error - res.mempool, err = mempool.New("mempool", registerer, res) + res.mempool, err = mempool.New("mempool", registerer, nil) if err != nil { panic(fmt.Errorf("failed to create mempool: %w", err)) } diff --git a/vms/platformvm/block/executor/rejector.go b/vms/platformvm/block/executor/rejector.go index daa6939f05cd..cfc64b050be4 100644 --- a/vms/platformvm/block/executor/rejector.go +++ b/vms/platformvm/block/executor/rejector.go @@ -82,5 +82,7 @@ func (r *rejector) rejectBlock(b block.Block, blockType string) error { } } + r.Mempool.RequestBuildBlock(false) + return nil } diff --git a/vms/platformvm/block/executor/rejector_test.go b/vms/platformvm/block/executor/rejector_test.go index 1e1e5768618d..3ccd9c0d66b1 100644 --- a/vms/platformvm/block/executor/rejector_test.go +++ b/vms/platformvm/block/executor/rejector_test.go @@ -142,6 +142,8 @@ func TestRejectBlock(t *testing.T) { mempool.EXPECT().Add(tx).Return(nil).Times(1) } + mempool.EXPECT().RequestBuildBlock(false).Times(1) + require.NoError(tt.rejectFunc(rejector, blk)) // Make sure block and its parent are removed from the state map. require.NotContains(rejector.blkIDToState, blk.ID()) diff --git a/vms/platformvm/network/network.go b/vms/platformvm/network/network.go index 0bbfc4f86eaf..5f4945093d60 100644 --- a/vms/platformvm/network/network.go +++ b/vms/platformvm/network/network.go @@ -181,6 +181,8 @@ func (n *network) issueTx(tx *txs.Tx) error { return err } + n.mempool.RequestBuildBlock(false) + return nil } diff --git a/vms/platformvm/network/network_test.go b/vms/platformvm/network/network_test.go index 8c17bb0491b5..000cbda7e195 100644 --- a/vms/platformvm/network/network_test.go +++ b/vms/platformvm/network/network_test.go @@ -284,6 +284,7 @@ func TestNetworkIssueTx(t *testing.T) { mempool := mempool.NewMockMempool(ctrl) mempool.EXPECT().Has(gomock.Any()).Return(false) mempool.EXPECT().Add(gomock.Any()).Return(nil) + mempool.EXPECT().RequestBuildBlock(false) return mempool }, managerFunc: func(ctrl *gomock.Controller) executor.Manager { diff --git a/vms/platformvm/state/diff.go b/vms/platformvm/state/diff.go index 91a5f040a2b4..1aafcf079969 100644 --- a/vms/platformvm/state/diff.go +++ b/vms/platformvm/state/diff.go @@ -25,7 +25,7 @@ var ( type Diff interface { Chain - Apply(State) error + Apply(Chain) error } type diff struct { @@ -479,7 +479,7 @@ func (d *diff) DeleteUTXO(utxoID ids.ID) { } } -func (d *diff) Apply(baseState State) error { +func (d *diff) Apply(baseState Chain) error { baseState.SetTimestamp(d.timestamp) for subnetID, supply := range d.currentSupply { baseState.SetCurrentSupply(subnetID, supply) diff --git a/vms/platformvm/state/diff_test.go b/vms/platformvm/state/diff_test.go index c35fb925594b..9b833f8482a8 100644 --- a/vms/platformvm/state/diff_test.go +++ b/vms/platformvm/state/diff_test.go @@ -578,3 +578,111 @@ func TestDiffSubnetOwner(t *testing.T) { require.NoError(err) require.Equal(owner2, owner) } + +func TestDiffStacking(t *testing.T) { + require := require.New(t) + ctrl := gomock.NewController(t) + + state, _ := newInitializedState(require) + + states := NewMockVersions(ctrl) + lastAcceptedID := ids.GenerateTestID() + states.EXPECT().GetState(lastAcceptedID).Return(state, true).AnyTimes() + + var ( + owner1 = fx.NewMockOwner(ctrl) + owner2 = fx.NewMockOwner(ctrl) + owner3 = fx.NewMockOwner(ctrl) + + createSubnetTx = &txs.Tx{ + Unsigned: &txs.CreateSubnetTx{ + BaseTx: txs.BaseTx{}, + Owner: owner1, + }, + } + + subnetID = createSubnetTx.ID() + ) + + // Create subnet on base state + owner, err := state.GetSubnetOwner(subnetID) + require.ErrorIs(err, database.ErrNotFound) + require.Nil(owner) + + state.AddSubnet(createSubnetTx) + state.SetSubnetOwner(subnetID, owner1) + + owner, err = state.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner1, owner) + + // Create first diff and verify that subnet owner returns correctly + statesDiff, err := NewDiff(lastAcceptedID, states) + require.NoError(err) + + owner, err = statesDiff.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner1, owner) + + // Transferring subnet ownership on first diff should be reflected on first diff not state + statesDiff.SetSubnetOwner(subnetID, owner2) + owner, err = statesDiff.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner2, owner) + + owner, err = state.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner1, owner) + + // Create a second diff on first diff and verify that subnet owner returns correctly + stackedDiff, err := wrapState(statesDiff) + require.NoError(err) + owner, err = stackedDiff.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner2, owner) + + // Transfer ownership on stacked diff and verify it is only reflected on stacked diff + stackedDiff.SetSubnetOwner(subnetID, owner3) + owner, err = stackedDiff.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner3, owner) + + owner, err = statesDiff.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner2, owner) + + owner, err = state.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner1, owner) + + // Applying both diffs successively should work as expected. + require.NoError(stackedDiff.Apply(statesDiff)) + + owner, err = statesDiff.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner3, owner) + + owner, err = state.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner1, owner) + + require.NoError(statesDiff.Apply(state)) + + owner, err = state.GetSubnetOwner(subnetID) + require.NoError(err) + require.Equal(owner3, owner) +} + +type stateGetter struct { + state Chain +} + +func (s stateGetter) GetState(ids.ID) (Chain, bool) { + return s.state, true +} + +func wrapState(parentState Chain) (Diff, error) { + return NewDiff(ids.Empty, stateGetter{ + state: parentState, + }) +} diff --git a/vms/platformvm/state/mock_chain.go b/vms/platformvm/state/mock_chain.go deleted file mode 100644 index c82ceb3af831..000000000000 --- a/vms/platformvm/state/mock_chain.go +++ /dev/null @@ -1,513 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/avalanchego/vms/platformvm/state (interfaces: Chain) - -// Package state is a generated GoMock package. -package state - -import ( - reflect "reflect" - time "time" - - ids "github.com/ava-labs/avalanchego/ids" - avax "github.com/ava-labs/avalanchego/vms/components/avax" - fx "github.com/ava-labs/avalanchego/vms/platformvm/fx" - status "github.com/ava-labs/avalanchego/vms/platformvm/status" - txs "github.com/ava-labs/avalanchego/vms/platformvm/txs" - gomock "go.uber.org/mock/gomock" -) - -// MockChain is a mock of Chain interface. -type MockChain struct { - ctrl *gomock.Controller - recorder *MockChainMockRecorder -} - -// MockChainMockRecorder is the mock recorder for MockChain. -type MockChainMockRecorder struct { - mock *MockChain -} - -// NewMockChain creates a new mock instance. -func NewMockChain(ctrl *gomock.Controller) *MockChain { - mock := &MockChain{ctrl: ctrl} - mock.recorder = &MockChainMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockChain) EXPECT() *MockChainMockRecorder { - return m.recorder -} - -// AddChain mocks base method. -func (m *MockChain) AddChain(arg0 *txs.Tx) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddChain", arg0) -} - -// AddChain indicates an expected call of AddChain. -func (mr *MockChainMockRecorder) AddChain(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddChain", reflect.TypeOf((*MockChain)(nil).AddChain), arg0) -} - -// AddRewardUTXO mocks base method. -func (m *MockChain) AddRewardUTXO(arg0 ids.ID, arg1 *avax.UTXO) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddRewardUTXO", arg0, arg1) -} - -// AddRewardUTXO indicates an expected call of AddRewardUTXO. -func (mr *MockChainMockRecorder) AddRewardUTXO(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRewardUTXO", reflect.TypeOf((*MockChain)(nil).AddRewardUTXO), arg0, arg1) -} - -// AddSubnet mocks base method. -func (m *MockChain) AddSubnet(arg0 *txs.Tx) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddSubnet", arg0) -} - -// AddSubnet indicates an expected call of AddSubnet. -func (mr *MockChainMockRecorder) AddSubnet(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnet", reflect.TypeOf((*MockChain)(nil).AddSubnet), arg0) -} - -// AddSubnetTransformation mocks base method. -func (m *MockChain) AddSubnetTransformation(arg0 *txs.Tx) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddSubnetTransformation", arg0) -} - -// AddSubnetTransformation indicates an expected call of AddSubnetTransformation. -func (mr *MockChainMockRecorder) AddSubnetTransformation(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnetTransformation", reflect.TypeOf((*MockChain)(nil).AddSubnetTransformation), arg0) -} - -// AddTx mocks base method. -func (m *MockChain) AddTx(arg0 *txs.Tx, arg1 status.Status) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddTx", arg0, arg1) -} - -// AddTx indicates an expected call of AddTx. -func (mr *MockChainMockRecorder) AddTx(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTx", reflect.TypeOf((*MockChain)(nil).AddTx), arg0, arg1) -} - -// AddUTXO mocks base method. -func (m *MockChain) AddUTXO(arg0 *avax.UTXO) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddUTXO", arg0) -} - -// AddUTXO indicates an expected call of AddUTXO. -func (mr *MockChainMockRecorder) AddUTXO(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUTXO", reflect.TypeOf((*MockChain)(nil).AddUTXO), arg0) -} - -// DeleteCurrentDelegator mocks base method. -func (m *MockChain) DeleteCurrentDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteCurrentDelegator", arg0) -} - -// DeleteCurrentDelegator indicates an expected call of DeleteCurrentDelegator. -func (mr *MockChainMockRecorder) DeleteCurrentDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentDelegator", reflect.TypeOf((*MockChain)(nil).DeleteCurrentDelegator), arg0) -} - -// DeleteCurrentValidator mocks base method. -func (m *MockChain) DeleteCurrentValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteCurrentValidator", arg0) -} - -// DeleteCurrentValidator indicates an expected call of DeleteCurrentValidator. -func (mr *MockChainMockRecorder) DeleteCurrentValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentValidator", reflect.TypeOf((*MockChain)(nil).DeleteCurrentValidator), arg0) -} - -// DeletePendingDelegator mocks base method. -func (m *MockChain) DeletePendingDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeletePendingDelegator", arg0) -} - -// DeletePendingDelegator indicates an expected call of DeletePendingDelegator. -func (mr *MockChainMockRecorder) DeletePendingDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingDelegator", reflect.TypeOf((*MockChain)(nil).DeletePendingDelegator), arg0) -} - -// DeletePendingValidator mocks base method. -func (m *MockChain) DeletePendingValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeletePendingValidator", arg0) -} - -// DeletePendingValidator indicates an expected call of DeletePendingValidator. -func (mr *MockChainMockRecorder) DeletePendingValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingValidator", reflect.TypeOf((*MockChain)(nil).DeletePendingValidator), arg0) -} - -// DeleteUTXO mocks base method. -func (m *MockChain) DeleteUTXO(arg0 ids.ID) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteUTXO", arg0) -} - -// DeleteUTXO indicates an expected call of DeleteUTXO. -func (mr *MockChainMockRecorder) DeleteUTXO(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUTXO", reflect.TypeOf((*MockChain)(nil).DeleteUTXO), arg0) -} - -// GetChains mocks base method. -func (m *MockChain) GetChains(arg0 ids.ID) ([]*txs.Tx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetChains", arg0) - ret0, _ := ret[0].([]*txs.Tx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetChains indicates an expected call of GetChains. -func (mr *MockChainMockRecorder) GetChains(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChains", reflect.TypeOf((*MockChain)(nil).GetChains), arg0) -} - -// GetCurrentDelegatorIterator mocks base method. -func (m *MockChain) GetCurrentDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentDelegatorIterator", arg0, arg1) - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentDelegatorIterator indicates an expected call of GetCurrentDelegatorIterator. -func (mr *MockChainMockRecorder) GetCurrentDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentDelegatorIterator", reflect.TypeOf((*MockChain)(nil).GetCurrentDelegatorIterator), arg0, arg1) -} - -// GetCurrentStakerIterator mocks base method. -func (m *MockChain) GetCurrentStakerIterator() (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentStakerIterator") - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentStakerIterator indicates an expected call of GetCurrentStakerIterator. -func (mr *MockChainMockRecorder) GetCurrentStakerIterator() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentStakerIterator", reflect.TypeOf((*MockChain)(nil).GetCurrentStakerIterator)) -} - -// GetCurrentSupply mocks base method. -func (m *MockChain) GetCurrentSupply(arg0 ids.ID) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentSupply", arg0) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentSupply indicates an expected call of GetCurrentSupply. -func (mr *MockChainMockRecorder) GetCurrentSupply(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSupply", reflect.TypeOf((*MockChain)(nil).GetCurrentSupply), arg0) -} - -// GetCurrentValidator mocks base method. -func (m *MockChain) GetCurrentValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentValidator", arg0, arg1) - ret0, _ := ret[0].(*Staker) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentValidator indicates an expected call of GetCurrentValidator. -func (mr *MockChainMockRecorder) GetCurrentValidator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidator", reflect.TypeOf((*MockChain)(nil).GetCurrentValidator), arg0, arg1) -} - -// GetDelegateeReward mocks base method. -func (m *MockChain) GetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDelegateeReward", arg0, arg1) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetDelegateeReward indicates an expected call of GetDelegateeReward. -func (mr *MockChainMockRecorder) GetDelegateeReward(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegateeReward", reflect.TypeOf((*MockChain)(nil).GetDelegateeReward), arg0, arg1) -} - -// GetPendingDelegatorIterator mocks base method. -func (m *MockChain) GetPendingDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPendingDelegatorIterator", arg0, arg1) - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPendingDelegatorIterator indicates an expected call of GetPendingDelegatorIterator. -func (mr *MockChainMockRecorder) GetPendingDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingDelegatorIterator", reflect.TypeOf((*MockChain)(nil).GetPendingDelegatorIterator), arg0, arg1) -} - -// GetPendingStakerIterator mocks base method. -func (m *MockChain) GetPendingStakerIterator() (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPendingStakerIterator") - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPendingStakerIterator indicates an expected call of GetPendingStakerIterator. -func (mr *MockChainMockRecorder) GetPendingStakerIterator() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingStakerIterator", reflect.TypeOf((*MockChain)(nil).GetPendingStakerIterator)) -} - -// GetPendingValidator mocks base method. -func (m *MockChain) GetPendingValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPendingValidator", arg0, arg1) - ret0, _ := ret[0].(*Staker) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPendingValidator indicates an expected call of GetPendingValidator. -func (mr *MockChainMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockChain)(nil).GetPendingValidator), arg0, arg1) -} - -// GetRewardUTXOs mocks base method. -func (m *MockChain) GetRewardUTXOs(arg0 ids.ID) ([]*avax.UTXO, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRewardUTXOs", arg0) - ret0, _ := ret[0].([]*avax.UTXO) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetRewardUTXOs indicates an expected call of GetRewardUTXOs. -func (mr *MockChainMockRecorder) GetRewardUTXOs(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRewardUTXOs", reflect.TypeOf((*MockChain)(nil).GetRewardUTXOs), arg0) -} - -// GetSubnetOwner mocks base method. -func (m *MockChain) GetSubnetOwner(arg0 ids.ID) (fx.Owner, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSubnetOwner", arg0) - ret0, _ := ret[0].(fx.Owner) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSubnetOwner indicates an expected call of GetSubnetOwner. -func (mr *MockChainMockRecorder) GetSubnetOwner(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetOwner", reflect.TypeOf((*MockChain)(nil).GetSubnetOwner), arg0) -} - -// GetSubnetTransformation mocks base method. -func (m *MockChain) GetSubnetTransformation(arg0 ids.ID) (*txs.Tx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSubnetTransformation", arg0) - ret0, _ := ret[0].(*txs.Tx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSubnetTransformation indicates an expected call of GetSubnetTransformation. -func (mr *MockChainMockRecorder) GetSubnetTransformation(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetTransformation", reflect.TypeOf((*MockChain)(nil).GetSubnetTransformation), arg0) -} - -// GetSubnets mocks base method. -func (m *MockChain) GetSubnets() ([]*txs.Tx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSubnets") - ret0, _ := ret[0].([]*txs.Tx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSubnets indicates an expected call of GetSubnets. -func (mr *MockChainMockRecorder) GetSubnets() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnets", reflect.TypeOf((*MockChain)(nil).GetSubnets)) -} - -// GetTimestamp mocks base method. -func (m *MockChain) GetTimestamp() time.Time { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTimestamp") - ret0, _ := ret[0].(time.Time) - return ret0 -} - -// GetTimestamp indicates an expected call of GetTimestamp. -func (mr *MockChainMockRecorder) GetTimestamp() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTimestamp", reflect.TypeOf((*MockChain)(nil).GetTimestamp)) -} - -// GetTx mocks base method. -func (m *MockChain) GetTx(arg0 ids.ID) (*txs.Tx, status.Status, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTx", arg0) - ret0, _ := ret[0].(*txs.Tx) - ret1, _ := ret[1].(status.Status) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// GetTx indicates an expected call of GetTx. -func (mr *MockChainMockRecorder) GetTx(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTx", reflect.TypeOf((*MockChain)(nil).GetTx), arg0) -} - -// GetUTXO mocks base method. -func (m *MockChain) GetUTXO(arg0 ids.ID) (*avax.UTXO, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUTXO", arg0) - ret0, _ := ret[0].(*avax.UTXO) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetUTXO indicates an expected call of GetUTXO. -func (mr *MockChainMockRecorder) GetUTXO(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUTXO", reflect.TypeOf((*MockChain)(nil).GetUTXO), arg0) -} - -// PutCurrentDelegator mocks base method. -func (m *MockChain) PutCurrentDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutCurrentDelegator", arg0) -} - -// PutCurrentDelegator indicates an expected call of PutCurrentDelegator. -func (mr *MockChainMockRecorder) PutCurrentDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentDelegator", reflect.TypeOf((*MockChain)(nil).PutCurrentDelegator), arg0) -} - -// PutCurrentValidator mocks base method. -func (m *MockChain) PutCurrentValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutCurrentValidator", arg0) -} - -// PutCurrentValidator indicates an expected call of PutCurrentValidator. -func (mr *MockChainMockRecorder) PutCurrentValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentValidator", reflect.TypeOf((*MockChain)(nil).PutCurrentValidator), arg0) -} - -// PutPendingDelegator mocks base method. -func (m *MockChain) PutPendingDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutPendingDelegator", arg0) -} - -// PutPendingDelegator indicates an expected call of PutPendingDelegator. -func (mr *MockChainMockRecorder) PutPendingDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingDelegator", reflect.TypeOf((*MockChain)(nil).PutPendingDelegator), arg0) -} - -// PutPendingValidator mocks base method. -func (m *MockChain) PutPendingValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutPendingValidator", arg0) -} - -// PutPendingValidator indicates an expected call of PutPendingValidator. -func (mr *MockChainMockRecorder) PutPendingValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingValidator", reflect.TypeOf((*MockChain)(nil).PutPendingValidator), arg0) -} - -// SetCurrentSupply mocks base method. -func (m *MockChain) SetCurrentSupply(arg0 ids.ID, arg1 uint64) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetCurrentSupply", arg0, arg1) -} - -// SetCurrentSupply indicates an expected call of SetCurrentSupply. -func (mr *MockChainMockRecorder) SetCurrentSupply(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCurrentSupply", reflect.TypeOf((*MockChain)(nil).SetCurrentSupply), arg0, arg1) -} - -// SetDelegateeReward mocks base method. -func (m *MockChain) SetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID, arg2 uint64) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetDelegateeReward", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// SetDelegateeReward indicates an expected call of SetDelegateeReward. -func (mr *MockChainMockRecorder) SetDelegateeReward(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDelegateeReward", reflect.TypeOf((*MockChain)(nil).SetDelegateeReward), arg0, arg1, arg2) -} - -// SetSubnetOwner mocks base method. -func (m *MockChain) SetSubnetOwner(arg0 ids.ID, arg1 fx.Owner) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetSubnetOwner", arg0, arg1) -} - -// SetSubnetOwner indicates an expected call of SetSubnetOwner. -func (mr *MockChainMockRecorder) SetSubnetOwner(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSubnetOwner", reflect.TypeOf((*MockChain)(nil).SetSubnetOwner), arg0, arg1) -} - -// SetTimestamp mocks base method. -func (m *MockChain) SetTimestamp(arg0 time.Time) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetTimestamp", arg0) -} - -// SetTimestamp indicates an expected call of SetTimestamp. -func (mr *MockChainMockRecorder) SetTimestamp(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTimestamp", reflect.TypeOf((*MockChain)(nil).SetTimestamp), arg0) -} diff --git a/vms/platformvm/state/mock_diff.go b/vms/platformvm/state/mock_diff.go deleted file mode 100644 index 49bab7897009..000000000000 --- a/vms/platformvm/state/mock_diff.go +++ /dev/null @@ -1,527 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/avalanchego/vms/platformvm/state (interfaces: Diff) - -// Package state is a generated GoMock package. -package state - -import ( - reflect "reflect" - time "time" - - ids "github.com/ava-labs/avalanchego/ids" - avax "github.com/ava-labs/avalanchego/vms/components/avax" - fx "github.com/ava-labs/avalanchego/vms/platformvm/fx" - status "github.com/ava-labs/avalanchego/vms/platformvm/status" - txs "github.com/ava-labs/avalanchego/vms/platformvm/txs" - gomock "go.uber.org/mock/gomock" -) - -// MockDiff is a mock of Diff interface. -type MockDiff struct { - ctrl *gomock.Controller - recorder *MockDiffMockRecorder -} - -// MockDiffMockRecorder is the mock recorder for MockDiff. -type MockDiffMockRecorder struct { - mock *MockDiff -} - -// NewMockDiff creates a new mock instance. -func NewMockDiff(ctrl *gomock.Controller) *MockDiff { - mock := &MockDiff{ctrl: ctrl} - mock.recorder = &MockDiffMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockDiff) EXPECT() *MockDiffMockRecorder { - return m.recorder -} - -// AddChain mocks base method. -func (m *MockDiff) AddChain(arg0 *txs.Tx) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddChain", arg0) -} - -// AddChain indicates an expected call of AddChain. -func (mr *MockDiffMockRecorder) AddChain(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddChain", reflect.TypeOf((*MockDiff)(nil).AddChain), arg0) -} - -// AddRewardUTXO mocks base method. -func (m *MockDiff) AddRewardUTXO(arg0 ids.ID, arg1 *avax.UTXO) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddRewardUTXO", arg0, arg1) -} - -// AddRewardUTXO indicates an expected call of AddRewardUTXO. -func (mr *MockDiffMockRecorder) AddRewardUTXO(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRewardUTXO", reflect.TypeOf((*MockDiff)(nil).AddRewardUTXO), arg0, arg1) -} - -// AddSubnet mocks base method. -func (m *MockDiff) AddSubnet(arg0 *txs.Tx) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddSubnet", arg0) -} - -// AddSubnet indicates an expected call of AddSubnet. -func (mr *MockDiffMockRecorder) AddSubnet(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnet", reflect.TypeOf((*MockDiff)(nil).AddSubnet), arg0) -} - -// AddSubnetTransformation mocks base method. -func (m *MockDiff) AddSubnetTransformation(arg0 *txs.Tx) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddSubnetTransformation", arg0) -} - -// AddSubnetTransformation indicates an expected call of AddSubnetTransformation. -func (mr *MockDiffMockRecorder) AddSubnetTransformation(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnetTransformation", reflect.TypeOf((*MockDiff)(nil).AddSubnetTransformation), arg0) -} - -// AddTx mocks base method. -func (m *MockDiff) AddTx(arg0 *txs.Tx, arg1 status.Status) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddTx", arg0, arg1) -} - -// AddTx indicates an expected call of AddTx. -func (mr *MockDiffMockRecorder) AddTx(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTx", reflect.TypeOf((*MockDiff)(nil).AddTx), arg0, arg1) -} - -// AddUTXO mocks base method. -func (m *MockDiff) AddUTXO(arg0 *avax.UTXO) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "AddUTXO", arg0) -} - -// AddUTXO indicates an expected call of AddUTXO. -func (mr *MockDiffMockRecorder) AddUTXO(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUTXO", reflect.TypeOf((*MockDiff)(nil).AddUTXO), arg0) -} - -// Apply mocks base method. -func (m *MockDiff) Apply(arg0 State) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Apply", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// Apply indicates an expected call of Apply. -func (mr *MockDiffMockRecorder) Apply(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockDiff)(nil).Apply), arg0) -} - -// DeleteCurrentDelegator mocks base method. -func (m *MockDiff) DeleteCurrentDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteCurrentDelegator", arg0) -} - -// DeleteCurrentDelegator indicates an expected call of DeleteCurrentDelegator. -func (mr *MockDiffMockRecorder) DeleteCurrentDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentDelegator", reflect.TypeOf((*MockDiff)(nil).DeleteCurrentDelegator), arg0) -} - -// DeleteCurrentValidator mocks base method. -func (m *MockDiff) DeleteCurrentValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteCurrentValidator", arg0) -} - -// DeleteCurrentValidator indicates an expected call of DeleteCurrentValidator. -func (mr *MockDiffMockRecorder) DeleteCurrentValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentValidator", reflect.TypeOf((*MockDiff)(nil).DeleteCurrentValidator), arg0) -} - -// DeletePendingDelegator mocks base method. -func (m *MockDiff) DeletePendingDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeletePendingDelegator", arg0) -} - -// DeletePendingDelegator indicates an expected call of DeletePendingDelegator. -func (mr *MockDiffMockRecorder) DeletePendingDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingDelegator", reflect.TypeOf((*MockDiff)(nil).DeletePendingDelegator), arg0) -} - -// DeletePendingValidator mocks base method. -func (m *MockDiff) DeletePendingValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeletePendingValidator", arg0) -} - -// DeletePendingValidator indicates an expected call of DeletePendingValidator. -func (mr *MockDiffMockRecorder) DeletePendingValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingValidator", reflect.TypeOf((*MockDiff)(nil).DeletePendingValidator), arg0) -} - -// DeleteUTXO mocks base method. -func (m *MockDiff) DeleteUTXO(arg0 ids.ID) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteUTXO", arg0) -} - -// DeleteUTXO indicates an expected call of DeleteUTXO. -func (mr *MockDiffMockRecorder) DeleteUTXO(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUTXO", reflect.TypeOf((*MockDiff)(nil).DeleteUTXO), arg0) -} - -// GetChains mocks base method. -func (m *MockDiff) GetChains(arg0 ids.ID) ([]*txs.Tx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetChains", arg0) - ret0, _ := ret[0].([]*txs.Tx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetChains indicates an expected call of GetChains. -func (mr *MockDiffMockRecorder) GetChains(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChains", reflect.TypeOf((*MockDiff)(nil).GetChains), arg0) -} - -// GetCurrentDelegatorIterator mocks base method. -func (m *MockDiff) GetCurrentDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentDelegatorIterator", arg0, arg1) - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentDelegatorIterator indicates an expected call of GetCurrentDelegatorIterator. -func (mr *MockDiffMockRecorder) GetCurrentDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentDelegatorIterator", reflect.TypeOf((*MockDiff)(nil).GetCurrentDelegatorIterator), arg0, arg1) -} - -// GetCurrentStakerIterator mocks base method. -func (m *MockDiff) GetCurrentStakerIterator() (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentStakerIterator") - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentStakerIterator indicates an expected call of GetCurrentStakerIterator. -func (mr *MockDiffMockRecorder) GetCurrentStakerIterator() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentStakerIterator", reflect.TypeOf((*MockDiff)(nil).GetCurrentStakerIterator)) -} - -// GetCurrentSupply mocks base method. -func (m *MockDiff) GetCurrentSupply(arg0 ids.ID) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentSupply", arg0) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentSupply indicates an expected call of GetCurrentSupply. -func (mr *MockDiffMockRecorder) GetCurrentSupply(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSupply", reflect.TypeOf((*MockDiff)(nil).GetCurrentSupply), arg0) -} - -// GetCurrentValidator mocks base method. -func (m *MockDiff) GetCurrentValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCurrentValidator", arg0, arg1) - ret0, _ := ret[0].(*Staker) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCurrentValidator indicates an expected call of GetCurrentValidator. -func (mr *MockDiffMockRecorder) GetCurrentValidator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidator", reflect.TypeOf((*MockDiff)(nil).GetCurrentValidator), arg0, arg1) -} - -// GetDelegateeReward mocks base method. -func (m *MockDiff) GetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID) (uint64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetDelegateeReward", arg0, arg1) - ret0, _ := ret[0].(uint64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetDelegateeReward indicates an expected call of GetDelegateeReward. -func (mr *MockDiffMockRecorder) GetDelegateeReward(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegateeReward", reflect.TypeOf((*MockDiff)(nil).GetDelegateeReward), arg0, arg1) -} - -// GetPendingDelegatorIterator mocks base method. -func (m *MockDiff) GetPendingDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPendingDelegatorIterator", arg0, arg1) - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPendingDelegatorIterator indicates an expected call of GetPendingDelegatorIterator. -func (mr *MockDiffMockRecorder) GetPendingDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingDelegatorIterator", reflect.TypeOf((*MockDiff)(nil).GetPendingDelegatorIterator), arg0, arg1) -} - -// GetPendingStakerIterator mocks base method. -func (m *MockDiff) GetPendingStakerIterator() (StakerIterator, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPendingStakerIterator") - ret0, _ := ret[0].(StakerIterator) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPendingStakerIterator indicates an expected call of GetPendingStakerIterator. -func (mr *MockDiffMockRecorder) GetPendingStakerIterator() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingStakerIterator", reflect.TypeOf((*MockDiff)(nil).GetPendingStakerIterator)) -} - -// GetPendingValidator mocks base method. -func (m *MockDiff) GetPendingValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetPendingValidator", arg0, arg1) - ret0, _ := ret[0].(*Staker) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetPendingValidator indicates an expected call of GetPendingValidator. -func (mr *MockDiffMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockDiff)(nil).GetPendingValidator), arg0, arg1) -} - -// GetRewardUTXOs mocks base method. -func (m *MockDiff) GetRewardUTXOs(arg0 ids.ID) ([]*avax.UTXO, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetRewardUTXOs", arg0) - ret0, _ := ret[0].([]*avax.UTXO) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetRewardUTXOs indicates an expected call of GetRewardUTXOs. -func (mr *MockDiffMockRecorder) GetRewardUTXOs(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRewardUTXOs", reflect.TypeOf((*MockDiff)(nil).GetRewardUTXOs), arg0) -} - -// GetSubnetOwner mocks base method. -func (m *MockDiff) GetSubnetOwner(arg0 ids.ID) (fx.Owner, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSubnetOwner", arg0) - ret0, _ := ret[0].(fx.Owner) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSubnetOwner indicates an expected call of GetSubnetOwner. -func (mr *MockDiffMockRecorder) GetSubnetOwner(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetOwner", reflect.TypeOf((*MockDiff)(nil).GetSubnetOwner), arg0) -} - -// GetSubnetTransformation mocks base method. -func (m *MockDiff) GetSubnetTransformation(arg0 ids.ID) (*txs.Tx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSubnetTransformation", arg0) - ret0, _ := ret[0].(*txs.Tx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSubnetTransformation indicates an expected call of GetSubnetTransformation. -func (mr *MockDiffMockRecorder) GetSubnetTransformation(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetTransformation", reflect.TypeOf((*MockDiff)(nil).GetSubnetTransformation), arg0) -} - -// GetSubnets mocks base method. -func (m *MockDiff) GetSubnets() ([]*txs.Tx, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetSubnets") - ret0, _ := ret[0].([]*txs.Tx) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetSubnets indicates an expected call of GetSubnets. -func (mr *MockDiffMockRecorder) GetSubnets() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnets", reflect.TypeOf((*MockDiff)(nil).GetSubnets)) -} - -// GetTimestamp mocks base method. -func (m *MockDiff) GetTimestamp() time.Time { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTimestamp") - ret0, _ := ret[0].(time.Time) - return ret0 -} - -// GetTimestamp indicates an expected call of GetTimestamp. -func (mr *MockDiffMockRecorder) GetTimestamp() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTimestamp", reflect.TypeOf((*MockDiff)(nil).GetTimestamp)) -} - -// GetTx mocks base method. -func (m *MockDiff) GetTx(arg0 ids.ID) (*txs.Tx, status.Status, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetTx", arg0) - ret0, _ := ret[0].(*txs.Tx) - ret1, _ := ret[1].(status.Status) - ret2, _ := ret[2].(error) - return ret0, ret1, ret2 -} - -// GetTx indicates an expected call of GetTx. -func (mr *MockDiffMockRecorder) GetTx(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTx", reflect.TypeOf((*MockDiff)(nil).GetTx), arg0) -} - -// GetUTXO mocks base method. -func (m *MockDiff) GetUTXO(arg0 ids.ID) (*avax.UTXO, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetUTXO", arg0) - ret0, _ := ret[0].(*avax.UTXO) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetUTXO indicates an expected call of GetUTXO. -func (mr *MockDiffMockRecorder) GetUTXO(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUTXO", reflect.TypeOf((*MockDiff)(nil).GetUTXO), arg0) -} - -// PutCurrentDelegator mocks base method. -func (m *MockDiff) PutCurrentDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutCurrentDelegator", arg0) -} - -// PutCurrentDelegator indicates an expected call of PutCurrentDelegator. -func (mr *MockDiffMockRecorder) PutCurrentDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentDelegator", reflect.TypeOf((*MockDiff)(nil).PutCurrentDelegator), arg0) -} - -// PutCurrentValidator mocks base method. -func (m *MockDiff) PutCurrentValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutCurrentValidator", arg0) -} - -// PutCurrentValidator indicates an expected call of PutCurrentValidator. -func (mr *MockDiffMockRecorder) PutCurrentValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentValidator", reflect.TypeOf((*MockDiff)(nil).PutCurrentValidator), arg0) -} - -// PutPendingDelegator mocks base method. -func (m *MockDiff) PutPendingDelegator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutPendingDelegator", arg0) -} - -// PutPendingDelegator indicates an expected call of PutPendingDelegator. -func (mr *MockDiffMockRecorder) PutPendingDelegator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingDelegator", reflect.TypeOf((*MockDiff)(nil).PutPendingDelegator), arg0) -} - -// PutPendingValidator mocks base method. -func (m *MockDiff) PutPendingValidator(arg0 *Staker) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "PutPendingValidator", arg0) -} - -// PutPendingValidator indicates an expected call of PutPendingValidator. -func (mr *MockDiffMockRecorder) PutPendingValidator(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingValidator", reflect.TypeOf((*MockDiff)(nil).PutPendingValidator), arg0) -} - -// SetCurrentSupply mocks base method. -func (m *MockDiff) SetCurrentSupply(arg0 ids.ID, arg1 uint64) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetCurrentSupply", arg0, arg1) -} - -// SetCurrentSupply indicates an expected call of SetCurrentSupply. -func (mr *MockDiffMockRecorder) SetCurrentSupply(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCurrentSupply", reflect.TypeOf((*MockDiff)(nil).SetCurrentSupply), arg0, arg1) -} - -// SetDelegateeReward mocks base method. -func (m *MockDiff) SetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID, arg2 uint64) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SetDelegateeReward", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// SetDelegateeReward indicates an expected call of SetDelegateeReward. -func (mr *MockDiffMockRecorder) SetDelegateeReward(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDelegateeReward", reflect.TypeOf((*MockDiff)(nil).SetDelegateeReward), arg0, arg1, arg2) -} - -// SetSubnetOwner mocks base method. -func (m *MockDiff) SetSubnetOwner(arg0 ids.ID, arg1 fx.Owner) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetSubnetOwner", arg0, arg1) -} - -// SetSubnetOwner indicates an expected call of SetSubnetOwner. -func (mr *MockDiffMockRecorder) SetSubnetOwner(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSubnetOwner", reflect.TypeOf((*MockDiff)(nil).SetSubnetOwner), arg0, arg1) -} - -// SetTimestamp mocks base method. -func (m *MockDiff) SetTimestamp(arg0 time.Time) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "SetTimestamp", arg0) -} - -// SetTimestamp indicates an expected call of SetTimestamp. -func (mr *MockDiffMockRecorder) SetTimestamp(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTimestamp", reflect.TypeOf((*MockDiff)(nil).SetTimestamp), arg0) -} diff --git a/vms/platformvm/state/mock_state.go b/vms/platformvm/state/mock_state.go index 41ce946a12e0..465b3fda2bac 100644 --- a/vms/platformvm/state/mock_state.go +++ b/vms/platformvm/state/mock_state.go @@ -2,7 +2,7 @@ // See the file LICENSE for licensing terms. // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/avalanchego/vms/platformvm/state (interfaces: State) +// Source: github.com/ava-labs/avalanchego/vms/platformvm/state (interfaces: Chain,Diff,State,Versions) // Package state is a generated GoMock package. package state @@ -25,6 +25,1006 @@ import ( gomock "go.uber.org/mock/gomock" ) +// MockChain is a mock of Chain interface. +type MockChain struct { + ctrl *gomock.Controller + recorder *MockChainMockRecorder +} + +// MockChainMockRecorder is the mock recorder for MockChain. +type MockChainMockRecorder struct { + mock *MockChain +} + +// NewMockChain creates a new mock instance. +func NewMockChain(ctrl *gomock.Controller) *MockChain { + mock := &MockChain{ctrl: ctrl} + mock.recorder = &MockChainMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockChain) EXPECT() *MockChainMockRecorder { + return m.recorder +} + +// AddChain mocks base method. +func (m *MockChain) AddChain(arg0 *txs.Tx) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddChain", arg0) +} + +// AddChain indicates an expected call of AddChain. +func (mr *MockChainMockRecorder) AddChain(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddChain", reflect.TypeOf((*MockChain)(nil).AddChain), arg0) +} + +// AddRewardUTXO mocks base method. +func (m *MockChain) AddRewardUTXO(arg0 ids.ID, arg1 *avax.UTXO) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddRewardUTXO", arg0, arg1) +} + +// AddRewardUTXO indicates an expected call of AddRewardUTXO. +func (mr *MockChainMockRecorder) AddRewardUTXO(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRewardUTXO", reflect.TypeOf((*MockChain)(nil).AddRewardUTXO), arg0, arg1) +} + +// AddSubnet mocks base method. +func (m *MockChain) AddSubnet(arg0 *txs.Tx) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddSubnet", arg0) +} + +// AddSubnet indicates an expected call of AddSubnet. +func (mr *MockChainMockRecorder) AddSubnet(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnet", reflect.TypeOf((*MockChain)(nil).AddSubnet), arg0) +} + +// AddSubnetTransformation mocks base method. +func (m *MockChain) AddSubnetTransformation(arg0 *txs.Tx) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddSubnetTransformation", arg0) +} + +// AddSubnetTransformation indicates an expected call of AddSubnetTransformation. +func (mr *MockChainMockRecorder) AddSubnetTransformation(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnetTransformation", reflect.TypeOf((*MockChain)(nil).AddSubnetTransformation), arg0) +} + +// AddTx mocks base method. +func (m *MockChain) AddTx(arg0 *txs.Tx, arg1 status.Status) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddTx", arg0, arg1) +} + +// AddTx indicates an expected call of AddTx. +func (mr *MockChainMockRecorder) AddTx(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTx", reflect.TypeOf((*MockChain)(nil).AddTx), arg0, arg1) +} + +// AddUTXO mocks base method. +func (m *MockChain) AddUTXO(arg0 *avax.UTXO) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddUTXO", arg0) +} + +// AddUTXO indicates an expected call of AddUTXO. +func (mr *MockChainMockRecorder) AddUTXO(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUTXO", reflect.TypeOf((*MockChain)(nil).AddUTXO), arg0) +} + +// DeleteCurrentDelegator mocks base method. +func (m *MockChain) DeleteCurrentDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeleteCurrentDelegator", arg0) +} + +// DeleteCurrentDelegator indicates an expected call of DeleteCurrentDelegator. +func (mr *MockChainMockRecorder) DeleteCurrentDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentDelegator", reflect.TypeOf((*MockChain)(nil).DeleteCurrentDelegator), arg0) +} + +// DeleteCurrentValidator mocks base method. +func (m *MockChain) DeleteCurrentValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeleteCurrentValidator", arg0) +} + +// DeleteCurrentValidator indicates an expected call of DeleteCurrentValidator. +func (mr *MockChainMockRecorder) DeleteCurrentValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentValidator", reflect.TypeOf((*MockChain)(nil).DeleteCurrentValidator), arg0) +} + +// DeletePendingDelegator mocks base method. +func (m *MockChain) DeletePendingDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeletePendingDelegator", arg0) +} + +// DeletePendingDelegator indicates an expected call of DeletePendingDelegator. +func (mr *MockChainMockRecorder) DeletePendingDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingDelegator", reflect.TypeOf((*MockChain)(nil).DeletePendingDelegator), arg0) +} + +// DeletePendingValidator mocks base method. +func (m *MockChain) DeletePendingValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeletePendingValidator", arg0) +} + +// DeletePendingValidator indicates an expected call of DeletePendingValidator. +func (mr *MockChainMockRecorder) DeletePendingValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingValidator", reflect.TypeOf((*MockChain)(nil).DeletePendingValidator), arg0) +} + +// DeleteUTXO mocks base method. +func (m *MockChain) DeleteUTXO(arg0 ids.ID) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeleteUTXO", arg0) +} + +// DeleteUTXO indicates an expected call of DeleteUTXO. +func (mr *MockChainMockRecorder) DeleteUTXO(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUTXO", reflect.TypeOf((*MockChain)(nil).DeleteUTXO), arg0) +} + +// GetChains mocks base method. +func (m *MockChain) GetChains(arg0 ids.ID) ([]*txs.Tx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetChains", arg0) + ret0, _ := ret[0].([]*txs.Tx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetChains indicates an expected call of GetChains. +func (mr *MockChainMockRecorder) GetChains(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChains", reflect.TypeOf((*MockChain)(nil).GetChains), arg0) +} + +// GetCurrentDelegatorIterator mocks base method. +func (m *MockChain) GetCurrentDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentDelegatorIterator", arg0, arg1) + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentDelegatorIterator indicates an expected call of GetCurrentDelegatorIterator. +func (mr *MockChainMockRecorder) GetCurrentDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentDelegatorIterator", reflect.TypeOf((*MockChain)(nil).GetCurrentDelegatorIterator), arg0, arg1) +} + +// GetCurrentStakerIterator mocks base method. +func (m *MockChain) GetCurrentStakerIterator() (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentStakerIterator") + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentStakerIterator indicates an expected call of GetCurrentStakerIterator. +func (mr *MockChainMockRecorder) GetCurrentStakerIterator() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentStakerIterator", reflect.TypeOf((*MockChain)(nil).GetCurrentStakerIterator)) +} + +// GetCurrentSupply mocks base method. +func (m *MockChain) GetCurrentSupply(arg0 ids.ID) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentSupply", arg0) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentSupply indicates an expected call of GetCurrentSupply. +func (mr *MockChainMockRecorder) GetCurrentSupply(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSupply", reflect.TypeOf((*MockChain)(nil).GetCurrentSupply), arg0) +} + +// GetCurrentValidator mocks base method. +func (m *MockChain) GetCurrentValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentValidator", arg0, arg1) + ret0, _ := ret[0].(*Staker) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentValidator indicates an expected call of GetCurrentValidator. +func (mr *MockChainMockRecorder) GetCurrentValidator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidator", reflect.TypeOf((*MockChain)(nil).GetCurrentValidator), arg0, arg1) +} + +// GetDelegateeReward mocks base method. +func (m *MockChain) GetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDelegateeReward", arg0, arg1) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDelegateeReward indicates an expected call of GetDelegateeReward. +func (mr *MockChainMockRecorder) GetDelegateeReward(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegateeReward", reflect.TypeOf((*MockChain)(nil).GetDelegateeReward), arg0, arg1) +} + +// GetPendingDelegatorIterator mocks base method. +func (m *MockChain) GetPendingDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPendingDelegatorIterator", arg0, arg1) + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPendingDelegatorIterator indicates an expected call of GetPendingDelegatorIterator. +func (mr *MockChainMockRecorder) GetPendingDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingDelegatorIterator", reflect.TypeOf((*MockChain)(nil).GetPendingDelegatorIterator), arg0, arg1) +} + +// GetPendingStakerIterator mocks base method. +func (m *MockChain) GetPendingStakerIterator() (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPendingStakerIterator") + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPendingStakerIterator indicates an expected call of GetPendingStakerIterator. +func (mr *MockChainMockRecorder) GetPendingStakerIterator() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingStakerIterator", reflect.TypeOf((*MockChain)(nil).GetPendingStakerIterator)) +} + +// GetPendingValidator mocks base method. +func (m *MockChain) GetPendingValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPendingValidator", arg0, arg1) + ret0, _ := ret[0].(*Staker) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPendingValidator indicates an expected call of GetPendingValidator. +func (mr *MockChainMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockChain)(nil).GetPendingValidator), arg0, arg1) +} + +// GetRewardUTXOs mocks base method. +func (m *MockChain) GetRewardUTXOs(arg0 ids.ID) ([]*avax.UTXO, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRewardUTXOs", arg0) + ret0, _ := ret[0].([]*avax.UTXO) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRewardUTXOs indicates an expected call of GetRewardUTXOs. +func (mr *MockChainMockRecorder) GetRewardUTXOs(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRewardUTXOs", reflect.TypeOf((*MockChain)(nil).GetRewardUTXOs), arg0) +} + +// GetSubnetOwner mocks base method. +func (m *MockChain) GetSubnetOwner(arg0 ids.ID) (fx.Owner, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubnetOwner", arg0) + ret0, _ := ret[0].(fx.Owner) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubnetOwner indicates an expected call of GetSubnetOwner. +func (mr *MockChainMockRecorder) GetSubnetOwner(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetOwner", reflect.TypeOf((*MockChain)(nil).GetSubnetOwner), arg0) +} + +// GetSubnetTransformation mocks base method. +func (m *MockChain) GetSubnetTransformation(arg0 ids.ID) (*txs.Tx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubnetTransformation", arg0) + ret0, _ := ret[0].(*txs.Tx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubnetTransformation indicates an expected call of GetSubnetTransformation. +func (mr *MockChainMockRecorder) GetSubnetTransformation(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetTransformation", reflect.TypeOf((*MockChain)(nil).GetSubnetTransformation), arg0) +} + +// GetSubnets mocks base method. +func (m *MockChain) GetSubnets() ([]*txs.Tx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubnets") + ret0, _ := ret[0].([]*txs.Tx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubnets indicates an expected call of GetSubnets. +func (mr *MockChainMockRecorder) GetSubnets() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnets", reflect.TypeOf((*MockChain)(nil).GetSubnets)) +} + +// GetTimestamp mocks base method. +func (m *MockChain) GetTimestamp() time.Time { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTimestamp") + ret0, _ := ret[0].(time.Time) + return ret0 +} + +// GetTimestamp indicates an expected call of GetTimestamp. +func (mr *MockChainMockRecorder) GetTimestamp() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTimestamp", reflect.TypeOf((*MockChain)(nil).GetTimestamp)) +} + +// GetTx mocks base method. +func (m *MockChain) GetTx(arg0 ids.ID) (*txs.Tx, status.Status, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTx", arg0) + ret0, _ := ret[0].(*txs.Tx) + ret1, _ := ret[1].(status.Status) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetTx indicates an expected call of GetTx. +func (mr *MockChainMockRecorder) GetTx(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTx", reflect.TypeOf((*MockChain)(nil).GetTx), arg0) +} + +// GetUTXO mocks base method. +func (m *MockChain) GetUTXO(arg0 ids.ID) (*avax.UTXO, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUTXO", arg0) + ret0, _ := ret[0].(*avax.UTXO) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetUTXO indicates an expected call of GetUTXO. +func (mr *MockChainMockRecorder) GetUTXO(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUTXO", reflect.TypeOf((*MockChain)(nil).GetUTXO), arg0) +} + +// PutCurrentDelegator mocks base method. +func (m *MockChain) PutCurrentDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutCurrentDelegator", arg0) +} + +// PutCurrentDelegator indicates an expected call of PutCurrentDelegator. +func (mr *MockChainMockRecorder) PutCurrentDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentDelegator", reflect.TypeOf((*MockChain)(nil).PutCurrentDelegator), arg0) +} + +// PutCurrentValidator mocks base method. +func (m *MockChain) PutCurrentValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutCurrentValidator", arg0) +} + +// PutCurrentValidator indicates an expected call of PutCurrentValidator. +func (mr *MockChainMockRecorder) PutCurrentValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentValidator", reflect.TypeOf((*MockChain)(nil).PutCurrentValidator), arg0) +} + +// PutPendingDelegator mocks base method. +func (m *MockChain) PutPendingDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutPendingDelegator", arg0) +} + +// PutPendingDelegator indicates an expected call of PutPendingDelegator. +func (mr *MockChainMockRecorder) PutPendingDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingDelegator", reflect.TypeOf((*MockChain)(nil).PutPendingDelegator), arg0) +} + +// PutPendingValidator mocks base method. +func (m *MockChain) PutPendingValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutPendingValidator", arg0) +} + +// PutPendingValidator indicates an expected call of PutPendingValidator. +func (mr *MockChainMockRecorder) PutPendingValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingValidator", reflect.TypeOf((*MockChain)(nil).PutPendingValidator), arg0) +} + +// SetCurrentSupply mocks base method. +func (m *MockChain) SetCurrentSupply(arg0 ids.ID, arg1 uint64) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetCurrentSupply", arg0, arg1) +} + +// SetCurrentSupply indicates an expected call of SetCurrentSupply. +func (mr *MockChainMockRecorder) SetCurrentSupply(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCurrentSupply", reflect.TypeOf((*MockChain)(nil).SetCurrentSupply), arg0, arg1) +} + +// SetDelegateeReward mocks base method. +func (m *MockChain) SetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID, arg2 uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetDelegateeReward", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetDelegateeReward indicates an expected call of SetDelegateeReward. +func (mr *MockChainMockRecorder) SetDelegateeReward(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDelegateeReward", reflect.TypeOf((*MockChain)(nil).SetDelegateeReward), arg0, arg1, arg2) +} + +// SetSubnetOwner mocks base method. +func (m *MockChain) SetSubnetOwner(arg0 ids.ID, arg1 fx.Owner) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetSubnetOwner", arg0, arg1) +} + +// SetSubnetOwner indicates an expected call of SetSubnetOwner. +func (mr *MockChainMockRecorder) SetSubnetOwner(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSubnetOwner", reflect.TypeOf((*MockChain)(nil).SetSubnetOwner), arg0, arg1) +} + +// SetTimestamp mocks base method. +func (m *MockChain) SetTimestamp(arg0 time.Time) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetTimestamp", arg0) +} + +// SetTimestamp indicates an expected call of SetTimestamp. +func (mr *MockChainMockRecorder) SetTimestamp(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTimestamp", reflect.TypeOf((*MockChain)(nil).SetTimestamp), arg0) +} + +// MockDiff is a mock of Diff interface. +type MockDiff struct { + ctrl *gomock.Controller + recorder *MockDiffMockRecorder +} + +// MockDiffMockRecorder is the mock recorder for MockDiff. +type MockDiffMockRecorder struct { + mock *MockDiff +} + +// NewMockDiff creates a new mock instance. +func NewMockDiff(ctrl *gomock.Controller) *MockDiff { + mock := &MockDiff{ctrl: ctrl} + mock.recorder = &MockDiffMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockDiff) EXPECT() *MockDiffMockRecorder { + return m.recorder +} + +// AddChain mocks base method. +func (m *MockDiff) AddChain(arg0 *txs.Tx) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddChain", arg0) +} + +// AddChain indicates an expected call of AddChain. +func (mr *MockDiffMockRecorder) AddChain(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddChain", reflect.TypeOf((*MockDiff)(nil).AddChain), arg0) +} + +// AddRewardUTXO mocks base method. +func (m *MockDiff) AddRewardUTXO(arg0 ids.ID, arg1 *avax.UTXO) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddRewardUTXO", arg0, arg1) +} + +// AddRewardUTXO indicates an expected call of AddRewardUTXO. +func (mr *MockDiffMockRecorder) AddRewardUTXO(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRewardUTXO", reflect.TypeOf((*MockDiff)(nil).AddRewardUTXO), arg0, arg1) +} + +// AddSubnet mocks base method. +func (m *MockDiff) AddSubnet(arg0 *txs.Tx) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddSubnet", arg0) +} + +// AddSubnet indicates an expected call of AddSubnet. +func (mr *MockDiffMockRecorder) AddSubnet(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnet", reflect.TypeOf((*MockDiff)(nil).AddSubnet), arg0) +} + +// AddSubnetTransformation mocks base method. +func (m *MockDiff) AddSubnetTransformation(arg0 *txs.Tx) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddSubnetTransformation", arg0) +} + +// AddSubnetTransformation indicates an expected call of AddSubnetTransformation. +func (mr *MockDiffMockRecorder) AddSubnetTransformation(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddSubnetTransformation", reflect.TypeOf((*MockDiff)(nil).AddSubnetTransformation), arg0) +} + +// AddTx mocks base method. +func (m *MockDiff) AddTx(arg0 *txs.Tx, arg1 status.Status) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddTx", arg0, arg1) +} + +// AddTx indicates an expected call of AddTx. +func (mr *MockDiffMockRecorder) AddTx(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddTx", reflect.TypeOf((*MockDiff)(nil).AddTx), arg0, arg1) +} + +// AddUTXO mocks base method. +func (m *MockDiff) AddUTXO(arg0 *avax.UTXO) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "AddUTXO", arg0) +} + +// AddUTXO indicates an expected call of AddUTXO. +func (mr *MockDiffMockRecorder) AddUTXO(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddUTXO", reflect.TypeOf((*MockDiff)(nil).AddUTXO), arg0) +} + +// Apply mocks base method. +func (m *MockDiff) Apply(arg0 Chain) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Apply", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Apply indicates an expected call of Apply. +func (mr *MockDiffMockRecorder) Apply(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Apply", reflect.TypeOf((*MockDiff)(nil).Apply), arg0) +} + +// DeleteCurrentDelegator mocks base method. +func (m *MockDiff) DeleteCurrentDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeleteCurrentDelegator", arg0) +} + +// DeleteCurrentDelegator indicates an expected call of DeleteCurrentDelegator. +func (mr *MockDiffMockRecorder) DeleteCurrentDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentDelegator", reflect.TypeOf((*MockDiff)(nil).DeleteCurrentDelegator), arg0) +} + +// DeleteCurrentValidator mocks base method. +func (m *MockDiff) DeleteCurrentValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeleteCurrentValidator", arg0) +} + +// DeleteCurrentValidator indicates an expected call of DeleteCurrentValidator. +func (mr *MockDiffMockRecorder) DeleteCurrentValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCurrentValidator", reflect.TypeOf((*MockDiff)(nil).DeleteCurrentValidator), arg0) +} + +// DeletePendingDelegator mocks base method. +func (m *MockDiff) DeletePendingDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeletePendingDelegator", arg0) +} + +// DeletePendingDelegator indicates an expected call of DeletePendingDelegator. +func (mr *MockDiffMockRecorder) DeletePendingDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingDelegator", reflect.TypeOf((*MockDiff)(nil).DeletePendingDelegator), arg0) +} + +// DeletePendingValidator mocks base method. +func (m *MockDiff) DeletePendingValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeletePendingValidator", arg0) +} + +// DeletePendingValidator indicates an expected call of DeletePendingValidator. +func (mr *MockDiffMockRecorder) DeletePendingValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePendingValidator", reflect.TypeOf((*MockDiff)(nil).DeletePendingValidator), arg0) +} + +// DeleteUTXO mocks base method. +func (m *MockDiff) DeleteUTXO(arg0 ids.ID) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "DeleteUTXO", arg0) +} + +// DeleteUTXO indicates an expected call of DeleteUTXO. +func (mr *MockDiffMockRecorder) DeleteUTXO(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUTXO", reflect.TypeOf((*MockDiff)(nil).DeleteUTXO), arg0) +} + +// GetChains mocks base method. +func (m *MockDiff) GetChains(arg0 ids.ID) ([]*txs.Tx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetChains", arg0) + ret0, _ := ret[0].([]*txs.Tx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetChains indicates an expected call of GetChains. +func (mr *MockDiffMockRecorder) GetChains(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetChains", reflect.TypeOf((*MockDiff)(nil).GetChains), arg0) +} + +// GetCurrentDelegatorIterator mocks base method. +func (m *MockDiff) GetCurrentDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentDelegatorIterator", arg0, arg1) + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentDelegatorIterator indicates an expected call of GetCurrentDelegatorIterator. +func (mr *MockDiffMockRecorder) GetCurrentDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentDelegatorIterator", reflect.TypeOf((*MockDiff)(nil).GetCurrentDelegatorIterator), arg0, arg1) +} + +// GetCurrentStakerIterator mocks base method. +func (m *MockDiff) GetCurrentStakerIterator() (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentStakerIterator") + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentStakerIterator indicates an expected call of GetCurrentStakerIterator. +func (mr *MockDiffMockRecorder) GetCurrentStakerIterator() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentStakerIterator", reflect.TypeOf((*MockDiff)(nil).GetCurrentStakerIterator)) +} + +// GetCurrentSupply mocks base method. +func (m *MockDiff) GetCurrentSupply(arg0 ids.ID) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentSupply", arg0) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentSupply indicates an expected call of GetCurrentSupply. +func (mr *MockDiffMockRecorder) GetCurrentSupply(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSupply", reflect.TypeOf((*MockDiff)(nil).GetCurrentSupply), arg0) +} + +// GetCurrentValidator mocks base method. +func (m *MockDiff) GetCurrentValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCurrentValidator", arg0, arg1) + ret0, _ := ret[0].(*Staker) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCurrentValidator indicates an expected call of GetCurrentValidator. +func (mr *MockDiffMockRecorder) GetCurrentValidator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidator", reflect.TypeOf((*MockDiff)(nil).GetCurrentValidator), arg0, arg1) +} + +// GetDelegateeReward mocks base method. +func (m *MockDiff) GetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID) (uint64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDelegateeReward", arg0, arg1) + ret0, _ := ret[0].(uint64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDelegateeReward indicates an expected call of GetDelegateeReward. +func (mr *MockDiffMockRecorder) GetDelegateeReward(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDelegateeReward", reflect.TypeOf((*MockDiff)(nil).GetDelegateeReward), arg0, arg1) +} + +// GetPendingDelegatorIterator mocks base method. +func (m *MockDiff) GetPendingDelegatorIterator(arg0 ids.ID, arg1 ids.NodeID) (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPendingDelegatorIterator", arg0, arg1) + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPendingDelegatorIterator indicates an expected call of GetPendingDelegatorIterator. +func (mr *MockDiffMockRecorder) GetPendingDelegatorIterator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingDelegatorIterator", reflect.TypeOf((*MockDiff)(nil).GetPendingDelegatorIterator), arg0, arg1) +} + +// GetPendingStakerIterator mocks base method. +func (m *MockDiff) GetPendingStakerIterator() (StakerIterator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPendingStakerIterator") + ret0, _ := ret[0].(StakerIterator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPendingStakerIterator indicates an expected call of GetPendingStakerIterator. +func (mr *MockDiffMockRecorder) GetPendingStakerIterator() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingStakerIterator", reflect.TypeOf((*MockDiff)(nil).GetPendingStakerIterator)) +} + +// GetPendingValidator mocks base method. +func (m *MockDiff) GetPendingValidator(arg0 ids.ID, arg1 ids.NodeID) (*Staker, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPendingValidator", arg0, arg1) + ret0, _ := ret[0].(*Staker) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPendingValidator indicates an expected call of GetPendingValidator. +func (mr *MockDiffMockRecorder) GetPendingValidator(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPendingValidator", reflect.TypeOf((*MockDiff)(nil).GetPendingValidator), arg0, arg1) +} + +// GetRewardUTXOs mocks base method. +func (m *MockDiff) GetRewardUTXOs(arg0 ids.ID) ([]*avax.UTXO, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRewardUTXOs", arg0) + ret0, _ := ret[0].([]*avax.UTXO) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRewardUTXOs indicates an expected call of GetRewardUTXOs. +func (mr *MockDiffMockRecorder) GetRewardUTXOs(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRewardUTXOs", reflect.TypeOf((*MockDiff)(nil).GetRewardUTXOs), arg0) +} + +// GetSubnetOwner mocks base method. +func (m *MockDiff) GetSubnetOwner(arg0 ids.ID) (fx.Owner, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubnetOwner", arg0) + ret0, _ := ret[0].(fx.Owner) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubnetOwner indicates an expected call of GetSubnetOwner. +func (mr *MockDiffMockRecorder) GetSubnetOwner(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetOwner", reflect.TypeOf((*MockDiff)(nil).GetSubnetOwner), arg0) +} + +// GetSubnetTransformation mocks base method. +func (m *MockDiff) GetSubnetTransformation(arg0 ids.ID) (*txs.Tx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubnetTransformation", arg0) + ret0, _ := ret[0].(*txs.Tx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubnetTransformation indicates an expected call of GetSubnetTransformation. +func (mr *MockDiffMockRecorder) GetSubnetTransformation(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnetTransformation", reflect.TypeOf((*MockDiff)(nil).GetSubnetTransformation), arg0) +} + +// GetSubnets mocks base method. +func (m *MockDiff) GetSubnets() ([]*txs.Tx, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSubnets") + ret0, _ := ret[0].([]*txs.Tx) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSubnets indicates an expected call of GetSubnets. +func (mr *MockDiffMockRecorder) GetSubnets() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSubnets", reflect.TypeOf((*MockDiff)(nil).GetSubnets)) +} + +// GetTimestamp mocks base method. +func (m *MockDiff) GetTimestamp() time.Time { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTimestamp") + ret0, _ := ret[0].(time.Time) + return ret0 +} + +// GetTimestamp indicates an expected call of GetTimestamp. +func (mr *MockDiffMockRecorder) GetTimestamp() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTimestamp", reflect.TypeOf((*MockDiff)(nil).GetTimestamp)) +} + +// GetTx mocks base method. +func (m *MockDiff) GetTx(arg0 ids.ID) (*txs.Tx, status.Status, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTx", arg0) + ret0, _ := ret[0].(*txs.Tx) + ret1, _ := ret[1].(status.Status) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetTx indicates an expected call of GetTx. +func (mr *MockDiffMockRecorder) GetTx(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTx", reflect.TypeOf((*MockDiff)(nil).GetTx), arg0) +} + +// GetUTXO mocks base method. +func (m *MockDiff) GetUTXO(arg0 ids.ID) (*avax.UTXO, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetUTXO", arg0) + ret0, _ := ret[0].(*avax.UTXO) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetUTXO indicates an expected call of GetUTXO. +func (mr *MockDiffMockRecorder) GetUTXO(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUTXO", reflect.TypeOf((*MockDiff)(nil).GetUTXO), arg0) +} + +// PutCurrentDelegator mocks base method. +func (m *MockDiff) PutCurrentDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutCurrentDelegator", arg0) +} + +// PutCurrentDelegator indicates an expected call of PutCurrentDelegator. +func (mr *MockDiffMockRecorder) PutCurrentDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentDelegator", reflect.TypeOf((*MockDiff)(nil).PutCurrentDelegator), arg0) +} + +// PutCurrentValidator mocks base method. +func (m *MockDiff) PutCurrentValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutCurrentValidator", arg0) +} + +// PutCurrentValidator indicates an expected call of PutCurrentValidator. +func (mr *MockDiffMockRecorder) PutCurrentValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutCurrentValidator", reflect.TypeOf((*MockDiff)(nil).PutCurrentValidator), arg0) +} + +// PutPendingDelegator mocks base method. +func (m *MockDiff) PutPendingDelegator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutPendingDelegator", arg0) +} + +// PutPendingDelegator indicates an expected call of PutPendingDelegator. +func (mr *MockDiffMockRecorder) PutPendingDelegator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingDelegator", reflect.TypeOf((*MockDiff)(nil).PutPendingDelegator), arg0) +} + +// PutPendingValidator mocks base method. +func (m *MockDiff) PutPendingValidator(arg0 *Staker) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "PutPendingValidator", arg0) +} + +// PutPendingValidator indicates an expected call of PutPendingValidator. +func (mr *MockDiffMockRecorder) PutPendingValidator(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PutPendingValidator", reflect.TypeOf((*MockDiff)(nil).PutPendingValidator), arg0) +} + +// SetCurrentSupply mocks base method. +func (m *MockDiff) SetCurrentSupply(arg0 ids.ID, arg1 uint64) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetCurrentSupply", arg0, arg1) +} + +// SetCurrentSupply indicates an expected call of SetCurrentSupply. +func (mr *MockDiffMockRecorder) SetCurrentSupply(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCurrentSupply", reflect.TypeOf((*MockDiff)(nil).SetCurrentSupply), arg0, arg1) +} + +// SetDelegateeReward mocks base method. +func (m *MockDiff) SetDelegateeReward(arg0 ids.ID, arg1 ids.NodeID, arg2 uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetDelegateeReward", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// SetDelegateeReward indicates an expected call of SetDelegateeReward. +func (mr *MockDiffMockRecorder) SetDelegateeReward(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetDelegateeReward", reflect.TypeOf((*MockDiff)(nil).SetDelegateeReward), arg0, arg1, arg2) +} + +// SetSubnetOwner mocks base method. +func (m *MockDiff) SetSubnetOwner(arg0 ids.ID, arg1 fx.Owner) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetSubnetOwner", arg0, arg1) +} + +// SetSubnetOwner indicates an expected call of SetSubnetOwner. +func (mr *MockDiffMockRecorder) SetSubnetOwner(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetSubnetOwner", reflect.TypeOf((*MockDiff)(nil).SetSubnetOwner), arg0, arg1) +} + +// SetTimestamp mocks base method. +func (m *MockDiff) SetTimestamp(arg0 time.Time) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetTimestamp", arg0) +} + +// SetTimestamp indicates an expected call of SetTimestamp. +func (mr *MockDiffMockRecorder) SetTimestamp(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTimestamp", reflect.TypeOf((*MockDiff)(nil).SetTimestamp), arg0) +} + // MockState is a mock of State interface. type MockState struct { ctrl *gomock.Controller @@ -783,3 +1783,41 @@ func (mr *MockStateMockRecorder) UTXOIDs(arg0, arg1, arg2 interface{}) *gomock.C mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UTXOIDs", reflect.TypeOf((*MockState)(nil).UTXOIDs), arg0, arg1, arg2) } + +// MockVersions is a mock of Versions interface. +type MockVersions struct { + ctrl *gomock.Controller + recorder *MockVersionsMockRecorder +} + +// MockVersionsMockRecorder is the mock recorder for MockVersions. +type MockVersionsMockRecorder struct { + mock *MockVersions +} + +// NewMockVersions creates a new mock instance. +func NewMockVersions(ctrl *gomock.Controller) *MockVersions { + mock := &MockVersions{ctrl: ctrl} + mock.recorder = &MockVersionsMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockVersions) EXPECT() *MockVersionsMockRecorder { + return m.recorder +} + +// GetState mocks base method. +func (m *MockVersions) GetState(arg0 ids.ID) (Chain, bool) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetState", arg0) + ret0, _ := ret[0].(Chain) + ret1, _ := ret[1].(bool) + return ret0, ret1 +} + +// GetState indicates an expected call of GetState. +func (mr *MockVersionsMockRecorder) GetState(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetState", reflect.TypeOf((*MockVersions)(nil).GetState), arg0) +} diff --git a/vms/platformvm/state/mock_versions.go b/vms/platformvm/state/mock_versions.go deleted file mode 100644 index 3f8a20550b22..000000000000 --- a/vms/platformvm/state/mock_versions.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ava-labs/avalanchego/vms/platformvm/state (interfaces: Versions) - -// Package state is a generated GoMock package. -package state - -import ( - reflect "reflect" - - ids "github.com/ava-labs/avalanchego/ids" - gomock "go.uber.org/mock/gomock" -) - -// MockVersions is a mock of Versions interface. -type MockVersions struct { - ctrl *gomock.Controller - recorder *MockVersionsMockRecorder -} - -// MockVersionsMockRecorder is the mock recorder for MockVersions. -type MockVersionsMockRecorder struct { - mock *MockVersions -} - -// NewMockVersions creates a new mock instance. -func NewMockVersions(ctrl *gomock.Controller) *MockVersions { - mock := &MockVersions{ctrl: ctrl} - mock.recorder = &MockVersionsMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockVersions) EXPECT() *MockVersionsMockRecorder { - return m.recorder -} - -// GetState mocks base method. -func (m *MockVersions) GetState(arg0 ids.ID) (Chain, bool) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetState", arg0) - ret0, _ := ret[0].(Chain) - ret1, _ := ret[1].(bool) - return ret0, ret1 -} - -// GetState indicates an expected call of GetState. -func (mr *MockVersionsMockRecorder) GetState(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetState", reflect.TypeOf((*MockVersions)(nil).GetState), arg0) -} diff --git a/vms/platformvm/state/state.go b/vms/platformvm/state/state.go index 199b245008f7..4b2b59cf2f70 100644 --- a/vms/platformvm/state/state.go +++ b/vms/platformvm/state/state.go @@ -1319,13 +1319,13 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er // Persist primary network validator set at genesis for _, vdrTx := range genesis.Validators { - tx, ok := vdrTx.Unsigned.(*txs.AddValidatorTx) + validatorTx, ok := vdrTx.Unsigned.(txs.ValidatorTx) if !ok { - return fmt.Errorf("expected tx type *txs.AddValidatorTx but got %T", vdrTx.Unsigned) + return fmt.Errorf("expected tx type txs.ValidatorTx but got %T", vdrTx.Unsigned) } - stakeAmount := tx.Validator.Wght - stakeDuration := tx.Validator.Duration() + stakeAmount := validatorTx.Weight() + stakeDuration := validatorTx.EndTime().Sub(validatorTx.StartTime()) currentSupply, err := s.GetCurrentSupply(constants.PrimaryNetworkID) if err != nil { return err @@ -1341,7 +1341,7 @@ func (s *state) syncGenesis(genesisBlk block.Block, genesis *genesis.Genesis) er return err } - staker, err := NewCurrentStaker(vdrTx.ID(), tx, potentialReward) + staker, err := NewCurrentStaker(vdrTx.ID(), validatorTx, potentialReward) if err != nil { return err } diff --git a/vms/platformvm/txs/mempool/mempool.go b/vms/platformvm/txs/mempool/mempool.go index 675ec3c5c763..ce0d6a96f071 100644 --- a/vms/platformvm/txs/mempool/mempool.go +++ b/vms/platformvm/txs/mempool/mempool.go @@ -12,6 +12,7 @@ import ( "github.com/ava-labs/avalanchego/cache" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils/linkedhashmap" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/units" @@ -43,13 +44,6 @@ var ( errCantIssueRewardValidatorTx = errors.New("can not issue a reward validator tx") ) -type BlockTimer interface { - // ResetBlockTimer schedules a timer to notify the consensus engine once - // there is a block ready to be built. If a block is ready to be built when - // this function is called, the engine will be notified directly. - ResetBlockTimer() -} - type Mempool interface { // we may want to be able to stop valid transactions // from entering the mempool, e.g. during blocks creation @@ -75,6 +69,13 @@ type Mempool interface { // TODO: Remove once [StartTime] field is ignored in staker txs DropExpiredStakerTxs(minStartTime time.Time) []ids.ID + // RequestBuildBlock notifies the consensus engine that a block should be + // built. If [emptyBlockPermitted] is true, the notification will be sent + // regardless of whether there are no transactions in the mempool. If not, + // a notification will only be sent if there is at least one transaction in + // the mempool. + RequestBuildBlock(emptyBlockPermitted bool) + // Note: dropped txs are added to droppedTxIDs but are not evicted from // unissued decision/staker txs. This allows previously dropped txs to be // possibly reissued. @@ -100,13 +101,13 @@ type mempool struct { consumedUTXOs set.Set[ids.ID] - blkTimer BlockTimer + toEngine chan<- common.Message } func New( namespace string, registerer prometheus.Registerer, - blkTimer BlockTimer, + toEngine chan<- common.Message, ) (Mempool, error) { bytesAvailableMetric := prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: namespace, @@ -137,7 +138,7 @@ func New( droppedTxIDs: &cache.LRU[ids.ID, error]{Size: droppedTxIDsCacheSize}, consumedUTXOs: set.NewSet[ids.ID](initialConsumedUTXOsSize), dropIncoming: false, // enable tx adding by default - blkTimer: blkTimer, + toEngine: toEngine, }, nil } @@ -202,7 +203,6 @@ func (m *mempool) Add(tx *txs.Tx) error { // An explicitly added tx must not be marked as dropped. m.droppedTxIDs.Evict(txID) - m.blkTimer.ResetBlockTimer() return nil } @@ -259,6 +259,17 @@ func (m *mempool) GetDropReason(txID ids.ID) error { return err } +func (m *mempool) RequestBuildBlock(emptyBlockPermitted bool) { + if !emptyBlockPermitted && !m.HasTxs() { + return + } + + select { + case m.toEngine <- common.PendingTxs: + default: + } +} + // Drops all [txs.Staker] transactions whose [StartTime] is before // [minStartTime] from [mempool]. The dropped tx ids are returned. // diff --git a/vms/platformvm/txs/mempool/mempool_test.go b/vms/platformvm/txs/mempool/mempool_test.go index a56ae4702155..1d92132ebbcd 100644 --- a/vms/platformvm/txs/mempool/mempool_test.go +++ b/vms/platformvm/txs/mempool/mempool_test.go @@ -20,15 +20,7 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" ) -var ( - _ BlockTimer = (*noopBlkTimer)(nil) - - preFundedKeys = secp256k1.TestKeys() -) - -type noopBlkTimer struct{} - -func (*noopBlkTimer) ResetBlockTimer() {} +var preFundedKeys = secp256k1.TestKeys() // shows that valid tx is not added to mempool if this would exceed its maximum // size @@ -36,7 +28,7 @@ func TestBlockBuilderMaxMempoolSizeHandling(t *testing.T) { require := require.New(t) registerer := prometheus.NewRegistry() - mpool, err := New("mempool", registerer, &noopBlkTimer{}) + mpool, err := New("mempool", registerer, nil) require.NoError(err) decisionTxs, err := createTestDecisionTxs(1) @@ -60,7 +52,7 @@ func TestDecisionTxsInMempool(t *testing.T) { require := require.New(t) registerer := prometheus.NewRegistry() - mpool, err := New("mempool", registerer, &noopBlkTimer{}) + mpool, err := New("mempool", registerer, nil) require.NoError(err) decisionTxs, err := createTestDecisionTxs(2) @@ -112,7 +104,7 @@ func TestProposalTxsInMempool(t *testing.T) { require := require.New(t) registerer := prometheus.NewRegistry() - mpool, err := New("mempool", registerer, &noopBlkTimer{}) + mpool, err := New("mempool", registerer, nil) require.NoError(err) // The proposal txs are ordered by decreasing start time. This means after @@ -245,7 +237,7 @@ func TestDropExpiredStakerTxs(t *testing.T) { require := require.New(t) registerer := prometheus.NewRegistry() - mempool, err := New("mempool", registerer, &noopBlkTimer{}) + mempool, err := New("mempool", registerer, nil) require.NoError(err) tx1, err := generateAddValidatorTx(10, 20) diff --git a/vms/platformvm/txs/mempool/mock_mempool.go b/vms/platformvm/txs/mempool/mock_mempool.go index 8f8c90eb2d07..edc134a42ddf 100644 --- a/vms/platformvm/txs/mempool/mock_mempool.go +++ b/vms/platformvm/txs/mempool/mock_mempool.go @@ -184,3 +184,15 @@ func (mr *MockMempoolMockRecorder) Remove(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Remove", reflect.TypeOf((*MockMempool)(nil).Remove), arg0) } + +// RequestBuildBlock mocks base method. +func (m *MockMempool) RequestBuildBlock(arg0 bool) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "RequestBuildBlock", arg0) +} + +// RequestBuildBlock indicates an expected call of RequestBuildBlock. +func (mr *MockMempoolMockRecorder) RequestBuildBlock(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RequestBuildBlock", reflect.TypeOf((*MockMempool)(nil).RequestBuildBlock), arg0) +} diff --git a/vms/platformvm/txs/txheap/with_metrics.go b/vms/platformvm/txs/txheap/with_metrics.go deleted file mode 100644 index 60ab4f93244d..000000000000 --- a/vms/platformvm/txs/txheap/with_metrics.go +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package txheap - -import ( - "github.com/prometheus/client_golang/prometheus" - - "github.com/ava-labs/avalanchego/ids" - "github.com/ava-labs/avalanchego/vms/platformvm/txs" -) - -var _ Heap = (*withMetrics)(nil) - -type withMetrics struct { - Heap - - numTxs prometheus.Gauge -} - -func NewWithMetrics( - txHeap Heap, - namespace string, - registerer prometheus.Registerer, -) (Heap, error) { - h := &withMetrics{ - Heap: txHeap, - numTxs: prometheus.NewGauge(prometheus.GaugeOpts{ - Namespace: namespace, - Name: "count", - Help: "Number of transactions in the heap", - }), - } - return h, registerer.Register(h.numTxs) -} - -func (h *withMetrics) Add(tx *txs.Tx) { - h.Heap.Add(tx) - h.numTxs.Set(float64(h.Heap.Len())) -} - -func (h *withMetrics) Remove(txID ids.ID) *txs.Tx { - tx := h.Heap.Remove(txID) - h.numTxs.Set(float64(h.Heap.Len())) - return tx -} - -func (h *withMetrics) RemoveTop() *txs.Tx { - tx := h.Heap.RemoveTop() - h.numTxs.Set(float64(h.Heap.Len())) - return tx -} diff --git a/vms/platformvm/vm.go b/vms/platformvm/vm.go index c312e4044e8b..d9898b873137 100644 --- a/vms/platformvm/vm.go +++ b/vms/platformvm/vm.go @@ -177,9 +177,7 @@ func (vm *VM) Initialize( Bootstrapped: &vm.bootstrapped, } - // Note: There is a circular dependency between the mempool and block - // builder which is broken by passing in the vm. - mempool, err := mempool.New("mempool", registerer, vm) + mempool, err := mempool.New("mempool", registerer, toEngine) if err != nil { return fmt.Errorf("failed to create mempool: %w", err) } @@ -203,7 +201,6 @@ func (vm *VM) Initialize( vm.txBuilder, txExecutorBackend, vm.manager, - toEngine, ) // Create all of the chains that the database says exist diff --git a/vms/platformvm/vm_test.go b/vms/platformvm/vm_test.go index 613000da30be..a097e574ea82 100644 --- a/vms/platformvm/vm_test.go +++ b/vms/platformvm/vm_test.go @@ -1482,23 +1482,17 @@ func TestBootstrapPartiallyAccepted(t *testing.T) { ) require.NoError(err) - commonCfg := common.Config{ + bootstrapConfig := bootstrap.Config{ + AllGetsServer: snowGetHandler, Ctx: consensusCtx, Beacons: beacons, SampleK: beacons.Count(ctx.SubnetID), StartupTracker: startup, - Alpha: (totalWeight + 1) / 2, Sender: sender, BootstrapTracker: bootstrapTracker, AncestorsMaxContainersReceived: 2000, - SharedCfg: &common.SharedConfig{}, - } - - bootstrapConfig := bootstrap.Config{ - Config: commonCfg, - AllGetsServer: snowGetHandler, - Blocked: blocked, - VM: vm, + Blocked: blocked, + VM: vm, } // Asynchronously passes messages from the network to the consensus engine diff --git a/vms/proposervm/state_syncable_vm.go b/vms/proposervm/state_syncable_vm.go index 68a35b1e66bc..d5d0e3212e04 100644 --- a/vms/proposervm/state_syncable_vm.go +++ b/vms/proposervm/state_syncable_vm.go @@ -193,7 +193,7 @@ func (vm *VM) BackfillBlocks(ctx context.Context, blksBytes [][]byte) (ids.ID, u // 2. Validate blocks, checking that they are continguous blkHeights := maps.Keys(blks) sort.Slice(blkHeights, func(i, j int) bool { - return blkHeights[i] < blkHeights[j] // sort in ascending order by heights + return blkHeights[i] < blkHeights[j] }) var ( diff --git a/x/sync/network_client.go b/x/sync/network_client.go index 65f939019d7f..efc3c6ef089e 100644 --- a/x/sync/network_client.go +++ b/x/sync/network_client.go @@ -17,6 +17,7 @@ import ( "golang.org/x/sync/semaphore" "github.com/ava-labs/avalanchego/ids" + "github.com/ava-labs/avalanchego/network/p2p" "github.com/ava-labs/avalanchego/snow/engine/common" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" @@ -87,7 +88,7 @@ type networkClient struct { // controls maximum number of active outbound requests activeRequests *semaphore.Weighted // tracking of peers & bandwidth usage - peers *peerTracker + peers *p2p.PeerTracker // For sending messages to peers appSender common.AppSender } @@ -100,7 +101,7 @@ func NewNetworkClient( metricsNamespace string, registerer prometheus.Registerer, ) (NetworkClient, error) { - peerTracker, err := newPeerTracker(log, metricsNamespace, registerer) + peerTracker, err := p2p.NewPeerTracker(log, metricsNamespace, registerer) if err != nil { return nil, fmt.Errorf("failed to create peer tracker: %w", err) }