Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [v0.14.1](https://github.com/ava-labs/coreth/releases/tag/v0.14.1)
- Remove API eth_getAssetBalance that was used to query ANT balances (deprecated since v0.10.0)
- Remove legacy gossip handler and metrics (deprecated since v0.10.0)

## [v0.14.0](https://github.com/ava-labs/coreth/releases/tag/v0.14.0)
- Minor version update to correspond to avalanchego v1.12.0 / Etna.
Expand Down
21 changes: 1 addition & 20 deletions peer/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ type Network interface {
// by calling OnPeerConnected for each peer
Shutdown()

// SetGossipHandler sets the provided gossip handler as the gossip handler
SetGossipHandler(handler message.GossipHandler)

// SetRequestHandler sets the provided request handler as the request handler
SetRequestHandler(handler message.RequestHandler)

Expand Down Expand Up @@ -87,7 +84,6 @@ type network struct {
appSender common.AppSender // avalanchego AppSender for sending messages
codec codec.Manager // Codec used for parsing messages
appRequestHandler message.RequestHandler // maps request type => handler
gossipHandler message.GossipHandler // maps gossip type => handler
peers *peerTracker // tracking of peers & bandwidth
appStats stats.RequestHandlerStats // Provide request handler metrics

Expand All @@ -110,7 +106,6 @@ func NewNetwork(p2pNetwork *p2p.Network, appSender common.AppSender, codec codec
outstandingRequestHandlers: make(map[uint32]message.ResponseHandler),
activeAppRequests: semaphore.NewWeighted(maxActiveAppRequests),
p2pNetwork: p2pNetwork,
gossipHandler: message.NoopMempoolGossipHandler{},
appRequestHandler: message.NoopRequestHandler{},
peers: NewPeerTracker(),
appStats: stats.NewRequestHandlerStats(),
Expand Down Expand Up @@ -345,14 +340,7 @@ func (n *network) markRequestFulfilled(requestID uint32) (message.ResponseHandle
// from a peer. An error returned by this function is treated as fatal by the
// engine.
func (n *network) AppGossip(ctx context.Context, nodeID ids.NodeID, gossipBytes []byte) error {
var gossipMsg message.GossipMessage
if _, err := n.codec.Unmarshal(gossipBytes, &gossipMsg); err != nil {
log.Debug("forwarding AppGossip to SDK network", "nodeID", nodeID, "gossipLen", len(gossipBytes), "err", err)
return n.p2pNetwork.AppGossip(ctx, nodeID, gossipBytes)
}

log.Debug("processing AppGossip from node", "nodeID", nodeID, "msg", gossipMsg)
return gossipMsg.Handle(n.gossipHandler, nodeID)
return n.p2pNetwork.AppGossip(ctx, nodeID, gossipBytes)
}

// Connected adds the given nodeID to the peer list so that it can receive messages
Expand Down Expand Up @@ -407,13 +395,6 @@ func (n *network) Shutdown() {
n.closed.Set(true) // mark network as closed
}

func (n *network) SetGossipHandler(handler message.GossipHandler) {
n.lock.Lock()
defer n.lock.Unlock()

n.gossipHandler = handler
}

func (n *network) SetRequestHandler(handler message.RequestHandler) {
n.lock.Lock()
defer n.lock.Unlock()
Expand Down
59 changes: 22 additions & 37 deletions peer/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ import (
"github.com/ava-labs/avalanchego/version"
)

const (
codecVersion uint16 = 0
)

var (
defaultPeerVersion = &version.Application{
Major: 1,
Expand All @@ -46,9 +50,7 @@ var (
_ message.RequestHandler = &HelloGreetingRequestHandler{}
_ message.RequestHandler = &testRequestHandler{}

_ common.AppSender = testAppSender{}
_ message.GossipMessage = HelloGossip{}
_ message.GossipHandler = &testGossipHandler{}
_ common.AppSender = testAppSender{}

_ p2p.Handler = &testSDKHandler{}
)
Expand Down Expand Up @@ -393,7 +395,7 @@ func TestRequestMinVersion(t *testing.T) {
go func() {
time.Sleep(200 * time.Millisecond)
atomic.AddUint32(&callNum, 1)
responseBytes, err := codecManager.Marshal(message.Version, TestMessage{Message: "this is a response"})
responseBytes, err := codecManager.Marshal(codecVersion, TestMessage{Message: "this is a response"})
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -503,15 +505,15 @@ func TestHandleInvalidMessages(t *testing.T) {
p2pNetwork, err := p2p.NewNetwork(logging.NoLog{}, sender, prometheus.NewRegistry(), "")
require.NoError(t, err)
clientNetwork := NewNetwork(p2pNetwork, sender, codecManager, ids.EmptyNodeID, 1)
clientNetwork.SetGossipHandler(message.NoopMempoolGossipHandler{})
clientNetwork.SetRequestHandler(&testRequestHandler{})

assert.NoError(t, clientNetwork.Connected(context.Background(), nodeID, defaultPeerVersion))

defer clientNetwork.Shutdown()

// Ensure a valid gossip message sent as any App specific message type does not trigger a fatal error
gossipMsg, err := buildGossip(codecManager, HelloGossip{Msg: "hello there!"})
marshaller := helloGossipMarshaller{codec: codecManager}
gossipMsg, err := marshaller.MarshalGossip(&HelloGossip{Msg: "hello there!"})
assert.NoError(t, err)

// Ensure a valid request message sent as any App specific message type does not trigger a fatal error
Expand Down Expand Up @@ -552,7 +554,6 @@ func TestNetworkPropagatesRequestHandlerError(t *testing.T) {
p2pNetwork, err := p2p.NewNetwork(logging.NoLog{}, nil, prometheus.NewRegistry(), "")
require.NoError(t, err)
clientNetwork := NewNetwork(p2pNetwork, sender, codecManager, ids.EmptyNodeID, 1)
clientNetwork.SetGossipHandler(message.NoopMempoolGossipHandler{})
clientNetwork.SetRequestHandler(&testRequestHandler{err: errors.New("fail")}) // Return an error from the request handler

assert.NoError(t, clientNetwork.Connected(context.Background(), nodeID, defaultPeerVersion))
Expand Down Expand Up @@ -615,18 +616,14 @@ func buildCodec(t *testing.T, types ...interface{}) codec.Manager {
for _, typ := range types {
assert.NoError(t, c.RegisterType(typ))
}
assert.NoError(t, codecManager.RegisterCodec(message.Version, c))
assert.NoError(t, codecManager.RegisterCodec(codecVersion, c))
return codecManager
}

// marshalStruct is a helper method used to marshal an object as `interface{}`
// so that the codec is able to include the TypeID in the resulting bytes
func marshalStruct(codec codec.Manager, obj interface{}) ([]byte, error) {
return codec.Marshal(message.Version, &obj)
}

func buildGossip(codec codec.Manager, msg message.GossipMessage) ([]byte, error) {
return codec.Marshal(message.Version, &msg)
return codec.Marshal(codecVersion, &obj)
}

type testAppSender struct {
Expand Down Expand Up @@ -696,11 +693,11 @@ type HelloGreetingRequestHandler struct {
}

func (h *HelloGreetingRequestHandler) HandleHelloRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request *HelloRequest) ([]byte, error) {
return h.codec.Marshal(message.Version, HelloResponse{Response: "Hi"})
return h.codec.Marshal(codecVersion, HelloResponse{Response: "Hi"})
}

func (h *HelloGreetingRequestHandler) HandleGreetingRequest(ctx context.Context, nodeID ids.NodeID, requestID uint32, request *GreetingRequest) ([]byte, error) {
return h.codec.Marshal(message.Version, GreetingResponse{Greet: "Hey there"})
return h.codec.Marshal(codecVersion, GreetingResponse{Greet: "Hey there"})
}

type TestMessage struct {
Expand All @@ -719,34 +716,22 @@ type HelloGossip struct {
Msg string `serialize:"true"`
}

func (h HelloGossip) Handle(handler message.GossipHandler, nodeID ids.NodeID) error {
return handler.HandleEthTxs(nodeID, message.EthTxsGossip{})
func (tx *HelloGossip) GossipID() ids.ID {
return ids.FromStringOrPanic(tx.Msg)
}

func (h HelloGossip) String() string {
return fmt.Sprintf("HelloGossip(%s)", h.Msg)
}

func (h HelloGossip) Bytes() []byte {
// no op
return nil
}

type testGossipHandler struct {
received bool
nodeID ids.NodeID
type helloGossipMarshaller struct {
codec codec.Manager
}

func (t *testGossipHandler) HandleAtomicTx(nodeID ids.NodeID, msg message.AtomicTxGossip) error {
t.received = true
t.nodeID = nodeID
return nil
func (g helloGossipMarshaller) MarshalGossip(tx *HelloGossip) ([]byte, error) {
return g.codec.Marshal(0, tx)
}

func (t *testGossipHandler) HandleEthTxs(nodeID ids.NodeID, msg message.EthTxsGossip) error {
t.received = true
t.nodeID = nodeID
return nil
func (g helloGossipMarshaller) UnmarshalGossip(bytes []byte) (*HelloGossip, error) {
h := &HelloGossip{}
_, err := g.codec.Unmarshal(bytes, h)
return h, err
}

type testRequestHandler struct {
Expand Down
6 changes: 1 addition & 5 deletions plugin/evm/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,7 @@ func (p *Admin) SetLogLevel(_ *http.Request, args *client.SetLogLevelArgs, reply
return nil
}

type ConfigReply struct {
Config *Config `json:"config"`
}

func (p *Admin) GetVMConfig(_ *http.Request, _ *struct{}, reply *ConfigReply) error {
func (p *Admin) GetVMConfig(_ *http.Request, _ *struct{}, reply *client.ConfigReply) error {
reply.Config = &p.vm.config
return nil
}
35 changes: 35 additions & 0 deletions plugin/evm/atomic/gossip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// (c) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package atomic

import (
"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/network/p2p/gossip"
)

var (
_ gossip.Gossipable = (*GossipAtomicTx)(nil)
_ gossip.Marshaller[*GossipAtomicTx] = (*GossipAtomicTxMarshaller)(nil)
)

type GossipAtomicTxMarshaller struct{}

func (g GossipAtomicTxMarshaller) MarshalGossip(tx *GossipAtomicTx) ([]byte, error) {
return tx.Tx.SignedBytes(), nil
}

func (g GossipAtomicTxMarshaller) UnmarshalGossip(bytes []byte) (*GossipAtomicTx, error) {
tx, err := ExtractAtomicTx(bytes, Codec)
return &GossipAtomicTx{
Tx: tx,
}, err
}

type GossipAtomicTx struct {
Tx *Tx
}

func (tx *GossipAtomicTx) GossipID() ids.ID {
return tx.Tx.ID()
}
117 changes: 117 additions & 0 deletions plugin/evm/atomic/gossip_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// (c) 2019-2025, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package atomic

import (
"testing"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/snow"
"github.com/ava-labs/avalanchego/utils/crypto/secp256k1"
"github.com/ava-labs/avalanchego/vms/components/verify"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)

func TestGossipAtomicTxMarshaller(t *testing.T) {
require := require.New(t)

want := &GossipAtomicTx{
Tx: &Tx{
UnsignedAtomicTx: &UnsignedImportTx{},
Creds: []verify.Verifiable{},
},
}
marshaller := GossipAtomicTxMarshaller{}

key0, err := secp256k1.NewPrivateKey()
require.NoError(err)
err = want.Tx.Sign(Codec, [][]*secp256k1.PrivateKey{{key0}})
require.NoError(err)

bytes, err := marshaller.MarshalGossip(want)
require.NoError(err)

got, err := marshaller.UnmarshalGossip(bytes)
require.NoError(err)
require.Equal(want.GossipID(), got.GossipID())
}

func TestAtomicMempoolIterate(t *testing.T) {
txs := []*GossipAtomicTx{
{
Tx: &Tx{
UnsignedAtomicTx: &TestUnsignedTx{
IDV: ids.GenerateTestID(),
},
},
},
{
Tx: &Tx{
UnsignedAtomicTx: &TestUnsignedTx{
IDV: ids.GenerateTestID(),
},
},
},
}

tests := []struct {
name string
add []*GossipAtomicTx
f func(tx *GossipAtomicTx) bool
expectedTxs []*GossipAtomicTx
}{
{
name: "func matches nothing",
add: txs,
f: func(*GossipAtomicTx) bool {
return false
},
expectedTxs: []*GossipAtomicTx{},
},
{
name: "func matches all",
add: txs,
f: func(*GossipAtomicTx) bool {
return true
},
expectedTxs: txs,
},
{
name: "func matches subset",
add: txs,
f: func(tx *GossipAtomicTx) bool {
return tx.Tx == txs[0].Tx
},
expectedTxs: []*GossipAtomicTx{txs[0]},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)
m, err := NewMempool(&snow.Context{}, prometheus.NewRegistry(), 10, nil)
require.NoError(err)

for _, add := range tt.add {
require.NoError(m.Add(add))
}

matches := make([]*GossipAtomicTx, 0)
f := func(tx *GossipAtomicTx) bool {
match := tt.f(tx)

if match {
matches = append(matches, tx)
}

return match
}

m.Iterate(f)

require.ElementsMatch(tt.expectedTxs, matches)
})
}
}
Loading
Loading