diff --git a/vms/avm/network/network.go b/vms/avm/network/network.go index 1c3e7e5558ae..a1d3337ddb23 100644 --- a/vms/avm/network/network.go +++ b/vms/avm/network/network.go @@ -180,8 +180,6 @@ func (n *network) issueTx(tx *txs.Tx) error { } func (n *network) gossipTx(ctx context.Context, txID ids.ID, msgBytes []byte) { - // This lock is just to ensure there isn't racy behavior between checking if - // the tx was gossiped and marking the tx as gossiped. n.recentTxsLock.Lock() _, has := n.recentTxs.Get(txID) n.recentTxs.Put(txID, struct{}{}) diff --git a/vms/platformvm/block/builder/builder.go b/vms/platformvm/block/builder/builder.go index 8b41881edca6..aecc4c358f10 100644 --- a/vms/platformvm/block/builder/builder.go +++ b/vms/platformvm/block/builder/builder.go @@ -132,7 +132,7 @@ func (b *builder) AddUnverifiedTx(tx *txs.Tx) error { return err } } - return b.GossipTx(tx) + return b.GossipTx(context.TODO(), tx) } // BuildBlock builds a block to be added to consensus. diff --git a/vms/platformvm/block/builder/network.go b/vms/platformvm/block/builder/network.go index da5e122d38f4..d263561bfe74 100644 --- a/vms/platformvm/block/builder/network.go +++ b/vms/platformvm/block/builder/network.go @@ -7,7 +7,7 @@ package builder import ( "context" - "fmt" + "sync" "go.uber.org/zap" @@ -29,7 +29,7 @@ type Network interface { common.AppHandler // GossipTx gossips the transaction to some of the connected peers - GossipTx(tx *txs.Tx) error + GossipTx(ctx context.Context, tx *txs.Tx) error } type network struct { @@ -38,10 +38,11 @@ type network struct { ctx *snow.Context blkBuilder *builder + appSender common.AppSender // gossip related attributes - appSender common.AppSender - recentTxs *cache.LRU[ids.ID, struct{}] + recentTxsLock sync.Mutex + recentTxs *cache.LRU[ids.ID, struct{}] } func NewNetwork( @@ -120,22 +121,40 @@ func (n *network) AppGossip(_ context.Context, nodeID ids.NodeID, msgBytes []byt return nil } -func (n *network) GossipTx(tx *txs.Tx) error { +func (n *network) GossipTx(ctx context.Context, tx *txs.Tx) error { + txBytes := tx.Bytes() + msg := &message.Tx{ + Tx: txBytes, + } + msgBytes, err := message.Build(msg) + if err != nil { + return err + } + txID := tx.ID() + n.gossipTx(ctx, txID, msgBytes) + return nil +} + +func (n *network) gossipTx(ctx context.Context, txID ids.ID, msgBytes []byte) { + n.recentTxsLock.Lock() + _, has := n.recentTxs.Get(txID) + n.recentTxs.Put(txID, struct{}{}) + n.recentTxsLock.Unlock() + // Don't gossip a transaction if it has been recently gossiped. - if _, has := n.recentTxs.Get(txID); has { - return nil + if has { + return } - n.recentTxs.Put(txID, struct{}{}) n.ctx.Log.Debug("gossiping tx", zap.Stringer("txID", txID), ) - msg := &message.Tx{Tx: tx.Bytes()} - msgBytes, err := message.Build(msg) - if err != nil { - return fmt.Errorf("GossipTx: failed to build Tx message: %w", err) + if err := n.appSender.SendAppGossip(ctx, msgBytes); err != nil { + n.ctx.Log.Error("failed to gossip tx", + zap.Stringer("txID", txID), + zap.Error(err), + ) } - return n.appSender.SendAppGossip(context.TODO(), msgBytes) }