From d9970911a966a7d6ed29b5daf708e457c2b99a06 Mon Sep 17 00:00:00 2001 From: Jim Date: Mon, 8 Jul 2024 14:03:32 +0800 Subject: [PATCH] bugfix get metadata when start --- chains/substrate/chain.go | 11 +++--- chains/substrate/connection.go | 26 +++++++++---- chains/substrate/connection_test.go | 6 +-- chains/substrate/listener.go | 58 ++++++++++++++-------------- chains/substrate/test_helper_test.go | 6 +-- 5 files changed, 59 insertions(+), 48 deletions(-) diff --git a/chains/substrate/chain.go b/chains/substrate/chain.go index b5acff6f0..a9a18769b 100644 --- a/chains/substrate/chain.go +++ b/chains/substrate/chain.go @@ -7,30 +7,29 @@ The current supported transfer types are Fungible, Nonfungible, and generic. There are 3 major components: the connection, the listener, and the writer. -Connection +# Connection The Connection handles connecting to the substrate client, and submitting transactions to the client. It also handles state queries. The connection is shared by the writer and listener. -Listener +# Listener The substrate listener polls blocks and parses the associated events for the three transfer types. It then forwards these into the router. -Writer +# Writer As the writer receives messages from the router, it constructs proposals. If a proposal is still active, the writer will attempt to vote on it. Resource IDs are resolved to method name on-chain, which are then used in the proposals when constructing the resulting Call struct. - */ package substrate import ( + "github.com/ChainSafe/log15" "github.com/crustio/chainbridge-utils/blockstore" "github.com/crustio/chainbridge-utils/core" "github.com/crustio/chainbridge-utils/crypto/sr25519" "github.com/crustio/chainbridge-utils/keystore" metrics "github.com/crustio/chainbridge-utils/metrics/types" "github.com/crustio/chainbridge-utils/msg" - "github.com/ChainSafe/log15" ) var _ core.Chain = &Chain{} @@ -82,7 +81,7 @@ func InitializeChain(cfg *core.ChainConfig, logger log15.Logger, sysErr chan<- e stop := make(chan int) // Setup connection conn := NewConnection(cfg.Endpoint, cfg.Name, krp, logger, stop, sysErr) - err = conn.Connect() + err = conn.Connect(startBlock) if err != nil { return nil, err } diff --git a/chains/substrate/connection.go b/chains/substrate/connection.go index 8359d577f..57ba38ac7 100644 --- a/chains/substrate/connection.go +++ b/chains/substrate/connection.go @@ -7,9 +7,9 @@ import ( "fmt" "sync" + "github.com/ChainSafe/log15" utils "github.com/crustio/ChainBridge/shared/substrate" "github.com/crustio/chainbridge-utils/msg" - "github.com/ChainSafe/log15" gsrpc "github.com/crustio/go-substrate-rpc-client/v3" "github.com/crustio/go-substrate-rpc-client/v3/rpc/author" "github.com/crustio/go-substrate-rpc-client/v3/signature" @@ -42,9 +42,9 @@ func (c *Connection) getMetadata() (meta types.Metadata) { return meta } -func (c *Connection) updateMetatdata() error { +func (c *Connection) updateMetatdata(hash types.Hash) error { c.metaLock.Lock() - meta, err := c.api.RPC.State.GetMetadataLatest() + meta, err := c.api.RPC.State.GetMetadata(hash) if err != nil { c.metaLock.Unlock() return err @@ -54,7 +54,7 @@ func (c *Connection) updateMetatdata() error { return nil } -func (c *Connection) Connect() error { +func (c *Connection) Connect(number uint64) error { c.log.Info("Connecting to substrate chain...", "url", c.url) api, err := gsrpc.NewSubstrateAPI(c.url) if err != nil { @@ -66,9 +66,21 @@ func (c *Connection) Connect() error { c.api = api // Fetch metadata - meta, err := api.RPC.State.GetMetadataLatest() - if err != nil { - return err + var meta *types.Metadata + if number == 0 { + meta, err = api.RPC.State.GetMetadataLatest() + if err != nil { + return err + } + } else { + hash, err := api.RPC.Chain.GetBlockHash(number) + if err != nil { + return err + } + meta, err = api.RPC.State.GetMetadata(hash) + if err != nil { + return err + } } c.meta = *meta c.log.Debug("Fetched substrate metadata") diff --git a/chains/substrate/connection_test.go b/chains/substrate/connection_test.go index 6fb27d325..2577cbe37 100644 --- a/chains/substrate/connection_test.go +++ b/chains/substrate/connection_test.go @@ -13,7 +13,7 @@ func TestConnect_QueryStorage(t *testing.T) { // Create connection with Alice key errs := make(chan error) conn := NewConnection(TestEndpoint, "Alice", AliceKey, AliceTestLogger, make(chan int), errs) - err := conn.Connect() + err := conn.Connect(0) if err != nil { t.Fatal(err) } @@ -39,7 +39,7 @@ func TestConnect_CheckChainId(t *testing.T) { // Create connection with Alice key errs := make(chan error) conn := NewConnection(TestEndpoint, "Alice", AliceKey, AliceTestLogger, make(chan int), errs) - err := conn.Connect() + err := conn.Connect(0) if err != nil { t.Fatal(err) } @@ -63,7 +63,7 @@ func TestConnect_SubmitTx(t *testing.T) { // Create connection with Alice key errs := make(chan error) conn := NewConnection(TestEndpoint, "Alice", AliceKey, AliceTestLogger, make(chan int), errs) - err := conn.Connect() + err := conn.Connect(0) if err != nil { t.Fatal(err) } diff --git a/chains/substrate/listener.go b/chains/substrate/listener.go index 864e9e9c4..e05bd1192 100644 --- a/chains/substrate/listener.go +++ b/chains/substrate/listener.go @@ -9,29 +9,29 @@ import ( "math/big" "time" + "github.com/ChainSafe/log15" "github.com/crustio/ChainBridge/chains" utils "github.com/crustio/ChainBridge/shared/substrate" "github.com/crustio/chainbridge-utils/blockstore" metrics "github.com/crustio/chainbridge-utils/metrics/types" "github.com/crustio/chainbridge-utils/msg" - "github.com/ChainSafe/log15" "github.com/crustio/go-substrate-rpc-client/v3/types" ) type listener struct { - name string - chainId msg.ChainId - startBlock uint64 - blockstore blockstore.Blockstorer - conn *Connection - subscriptions map[eventName]eventHandler // Handlers for specific events - router chains.Router - log log15.Logger - stop <-chan int - sysErr chan<- error - latestBlock metrics.LatestBlock - metrics *metrics.ChainMetrics - blockConfirmations uint64 + name string + chainId msg.ChainId + startBlock uint64 + blockstore blockstore.Blockstorer + conn *Connection + subscriptions map[eventName]eventHandler // Handlers for specific events + router chains.Router + log log15.Logger + stop <-chan int + sysErr chan<- error + latestBlock metrics.LatestBlock + metrics *metrics.ChainMetrics + blockConfirmations uint64 } // Frequency of polling for a new block @@ -40,17 +40,17 @@ var BlockRetryLimit = 5 func NewListener(conn *Connection, blockConfirmations uint64, name string, id msg.ChainId, startBlock uint64, log log15.Logger, bs blockstore.Blockstorer, stop <-chan int, sysErr chan<- error, m *metrics.ChainMetrics) *listener { return &listener{ - name: name, - chainId: id, - startBlock: startBlock, - blockstore: bs, - conn: conn, - subscriptions: make(map[eventName]eventHandler), - log: log, - stop: stop, - sysErr: sysErr, - latestBlock: metrics.LatestBlock{LastUpdated: time.Now()}, - metrics: m, + name: name, + chainId: id, + startBlock: startBlock, + blockstore: bs, + conn: conn, + subscriptions: make(map[eventName]eventHandler), + log: log, + stop: stop, + sysErr: sysErr, + latestBlock: metrics.LatestBlock{LastUpdated: time.Now()}, + metrics: m, blockConfirmations: blockConfirmations, } } @@ -145,7 +145,7 @@ func (l *listener) pollBlocks() error { } // Sleep if the difference is less than BlockDelay; (latest - current) < BlockDelay - if uint64(finalizedHeader.Number) - currentBlock < l.blockConfirmations { + if uint64(finalizedHeader.Number)-currentBlock < l.blockConfirmations { l.log.Debug("Block not ready, will retry", "target", currentBlock, "latest", finalizedHeader.Number, "delay", l.blockConfirmations) time.Sleep(BlockRetryInterval) continue @@ -210,14 +210,14 @@ func (l *listener) processEvents(hash types.Hash) error { return err } - l.handleEvents(e) + l.handleEvents(e, hash) l.log.Trace("Finished processing events", "block", hash.Hex()) return nil } // handleEvents calls the associated handler for all registered event types -func (l *listener) handleEvents(evts utils.Events) { +func (l *listener) handleEvents(evts utils.Events, hash types.Hash) { if l.subscriptions[FungibleTransfer] != nil { for _, evt := range evts.ChainBridge_FungibleTransfer { l.log.Trace("Handling FungibleTransfer event") @@ -239,7 +239,7 @@ func (l *listener) handleEvents(evts utils.Events) { if len(evts.System_CodeUpdated) > 0 { l.log.Trace("Received CodeUpdated event") - err := l.conn.updateMetatdata() + err := l.conn.updateMetatdata(hash) if err != nil { l.log.Error("Unable to update Metadata", "error", err) } diff --git a/chains/substrate/test_helper_test.go b/chains/substrate/test_helper_test.go index 52a801808..3eea4dc9d 100644 --- a/chains/substrate/test_helper_test.go +++ b/chains/substrate/test_helper_test.go @@ -7,10 +7,10 @@ import ( "os" "testing" + "github.com/ChainSafe/log15" utils "github.com/crustio/ChainBridge/shared/substrate" "github.com/crustio/chainbridge-utils/keystore" "github.com/crustio/chainbridge-utils/msg" - "github.com/ChainSafe/log15" "github.com/crustio/go-substrate-rpc-client/v3/types" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -120,7 +120,7 @@ func newTestLogger(name string) log15.Logger { func createAliceConnection() (*Connection, chan error, error) { sysErr := make(chan error) alice := NewConnection(TestEndpoint, "Alice", AliceKey, AliceTestLogger, make(chan int), sysErr) - err := alice.Connect() + err := alice.Connect(0) if err != nil { return nil, nil, err } @@ -135,7 +135,7 @@ func createAliceAndBobConnections() (*Connection, *Connection, chan error, error } bob := NewConnection(TestEndpoint, "Bob", BobKey, AliceTestLogger, make(chan int), sysErr) - err = bob.Connect() + err = bob.Connect(0) if err != nil { return nil, nil, nil, err }