diff --git a/chains/substrate/client/check_metadata_hash_enabled_client.go b/chains/substrate/client/check_metadata_hash_enabled_client.go deleted file mode 100644 index 8adef584..00000000 --- a/chains/substrate/client/check_metadata_hash_enabled_client.go +++ /dev/null @@ -1,214 +0,0 @@ -// The Licensed Work is (c) 2022 Sygma -// SPDX-License-Identifier: LGPL-3.0-only - -package client - -import ( - "bytes" - "context" - "fmt" - "math/big" - "sync" - "time" - - "github.com/rs/zerolog/log" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/rpc/author" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/scale" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/signature" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/types" - "github.com/sygmaprotocol/sygma-core/chains/substrate/connection" - "github.com/sygmaprotocol/sygma-core/chains/substrate/events" -) - -type SubstrateCheckMetadataModeEnabledClient struct { - key *signature.KeyringPair // Keyring used for signing - nonceLock sync.Mutex // Locks nonce for updates - nonce types.U32 // Latest account nonce - tip uint64 - Conn *connection.CheckMetadataModeEnabledConnection - ChainID *big.Int -} - -func NewSubstrateCheckMetadataModeEnabledClient(conn *connection.CheckMetadataModeEnabledConnection, key *signature.KeyringPair, chainID *big.Int, tip uint64) *SubstrateCheckMetadataModeEnabledClient { - return &SubstrateCheckMetadataModeEnabledClient{ - key: key, - Conn: conn, - ChainID: chainID, - tip: tip, - } -} - -// Transact constructs and submits an extrinsic to call the method with the given arguments. -// All args are passed directly into GSRPC. GSRPC types are recommended to avoid serialization inconsistencies. -func (c *SubstrateCheckMetadataModeEnabledClient) Transact(method string, args ...interface{}) (types.Hash, *author.ExtrinsicStatusSubscription, error) { - log.Debug().Msgf("Submitting substrate call... method %s, sender %s", method, c.key.Address) - - // Create call and extrinsic - meta := c.Conn.GetMetadata() - call, err := types.NewCall( - &meta, - method, - args..., - ) - if err != nil { - return types.Hash{}, nil, fmt.Errorf("failed to construct call: %w", err) - } - - ext := types.NewExtrinsic(call) - // Get latest runtime version - rv, err := c.Conn.RPC.State.GetRuntimeVersionLatest() - if err != nil { - return types.Hash{}, nil, err - } - - c.nonceLock.Lock() - defer c.nonceLock.Unlock() - - nonce, err := c.nextNonce(&meta) - if err != nil { - return types.Hash{}, nil, err - } - - // Sign the extrinsic - o := types.SignatureOptions{ - BlockHash: types.Hash(c.Conn.GenesisHash), - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: types.Hash(c.Conn.GenesisHash), - Nonce: types.NewUCompactFromUInt(uint64(nonce)), - SpecVersion: types.U32(rv.SpecVersion), - Tip: types.NewUCompactFromUInt(c.tip), - TransactionVersion: types.U32(rv.TransactionVersion), - } - - sub, err := c.submitAndWatchExtrinsic(o, &ext) - if err != nil { - return types.Hash{}, nil, fmt.Errorf("submission of extrinsic failed: %w", err) - } - - hash, err := ExtrinsicHashCheckMetadataModeEnabled(ext) - if err != nil { - return types.Hash{}, nil, err - } - - log.Info().Str("extrinsic", hash.Hex()).Msgf("Extrinsic call submitted... method %s, sender %s, nonce %d", method, c.key.Address, nonce) - c.nonce = nonce + 1 - - return hash, sub, nil -} - -func (c *SubstrateCheckMetadataModeEnabledClient) TrackExtrinsic(extHash types.Hash, sub *author.ExtrinsicStatusSubscription) error { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(time.Minute*10)) - defer sub.Unsubscribe() - defer cancel() - subChan := sub.Chan() - for { - select { - case status := <-subChan: - { - if status.IsInBlock { - log.Debug().Str("extrinsic", extHash.Hex()).Msgf("Extrinsic in block with hash: %#x", status.AsInBlock) - } - if status.IsFinalized { - log.Info().Str("extrinsic", extHash.Hex()).Msgf("Extrinsic is finalized in block with hash: %#x", status.AsFinalized) - return c.checkExtrinsicSuccess(extHash, types.Hash(status.AsFinalized)) - } - } - case <-ctx.Done(): - return fmt.Errorf("extrinsic has timed out") - } - } -} - -func (c *SubstrateCheckMetadataModeEnabledClient) nextNonce(meta *types.Metadata) (types.U32, error) { - key, err := types.CreateStorageKey(meta, "System", "Account", c.key.PublicKey, nil) - if err != nil { - return 0, err - } - - var latestNonce types.U32 - var acct types.AccountInfo - exists, err := c.Conn.RPC.State.GetStorageLatest(key, &acct) - if err != nil { - return 0, err - } - - if !exists { - latestNonce = 0 - } else { - latestNonce = acct.Nonce - } - - if latestNonce < c.nonce { - return c.nonce, nil - } - - return latestNonce, nil -} - -func (c *SubstrateCheckMetadataModeEnabledClient) submitAndWatchExtrinsic(opts types.SignatureOptions, ext *types.Extrinsic) (*author.ExtrinsicStatusSubscription, error) { - err := ext.Sign(*c.key, opts) - if err != nil { - return nil, err - } - - sub, err := c.Conn.RPC.Author.SubmitAndWatchExtrinsic(*ext) - if err != nil { - return nil, err - } - - return sub, nil -} - -func (c *SubstrateCheckMetadataModeEnabledClient) checkExtrinsicSuccess(extHash types.Hash, blockHash types.Hash) error { - block, err := c.Conn.Chain.GetBlock(blockHash) - if err != nil { - return err - } - - evts, err := c.Conn.GetBlockEvents(blockHash) - if err != nil { - return err - } - - for _, event := range evts { - index := event.Phase.AsApplyExtrinsic - hash, err := ExtrinsicHashCheckMetadataModeEnabled(block.Block.Extrinsics[index]) - if err != nil { - return err - } - - if extHash != hash { - continue - } - - if event.Name == events.ExtrinsicFailedEvent { - return fmt.Errorf("extrinsic failed") - } - if event.Name == events.FailedHandlerExecutionEvent { - return fmt.Errorf("extrinsic failed with failed handler execution") - } - if event.Name == events.ExtrinsicSuccessEvent { - return nil - } - } - - return fmt.Errorf("no event found") -} - -func (c *SubstrateCheckMetadataModeEnabledClient) LatestBlock() (*big.Int, error) { - block, err := c.Conn.Chain.GetBlockLatest() - if err != nil { - return nil, err - } - return big.NewInt(int64(block.Block.Header.Number)), nil -} - -func ExtrinsicHashCheckMetadataModeEnabled(ext types.Extrinsic) (types.Hash, error) { - extHash := bytes.NewBuffer([]byte{}) - encoder := scale.NewEncoder(extHash) - err := ext.Encode(*encoder) - if err != nil { - return types.Hash{}, err - } - return types.NewHash(extHash.Bytes()), nil -} diff --git a/chains/substrate/client/client.go b/chains/substrate/client/client.go index 44e65f06..4bcdc260 100644 --- a/chains/substrate/client/client.go +++ b/chains/substrate/client/client.go @@ -7,6 +7,8 @@ import ( "bytes" "context" "fmt" + "github.com/centrifuge/go-substrate-rpc-client/v4/types/extrinsic" + "github.com/centrifuge/go-substrate-rpc-client/v4/types/extrinsic/extensions" "math/big" "sync" "time" @@ -54,7 +56,8 @@ func (c *SubstrateClient) Transact(method string, args ...interface{}) (types.Ha return types.Hash{}, nil, fmt.Errorf("failed to construct call: %w", err) } - ext := types.NewExtrinsic(call) + ext := extrinsic.NewDynamicExtrinsic(&call) + // Get latest runtime version rv, err := c.Conn.RPC.State.GetRuntimeVersionLatest() if err != nil { @@ -70,21 +73,22 @@ func (c *SubstrateClient) Transact(method string, args ...interface{}) (types.Ha } // Sign the extrinsic - o := types.SignatureOptions{ - BlockHash: c.Conn.GenesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.Conn.GenesisHash, - Nonce: types.NewUCompactFromUInt(uint64(nonce)), - SpecVersion: rv.SpecVersion, - Tip: types.NewUCompactFromUInt(c.tip), - TransactionVersion: rv.TransactionVersion, - } - sub, err := c.submitAndWatchExtrinsic(o, &ext) + sub, err := c.submitAndWatchExtrinsic( + &meta, + ext, + extrinsic.WithEra(types.ExtrinsicEra{IsImmortalEra: true}, c.Conn.GenesisHash), + extrinsic.WithNonce(types.NewUCompactFromUInt(uint64(nonce))), + extrinsic.WithTip(types.NewUCompactFromUInt(c.tip)), + extrinsic.WithSpecVersion(rv.SpecVersion), + extrinsic.WithTransactionVersion(rv.TransactionVersion), + extrinsic.WithGenesisHash(c.Conn.GenesisHash), + extrinsic.WithMetadataMode(extensions.CheckMetadataModeDisabled, extensions.CheckMetadataHash{Hash: types.NewEmptyOption[types.H256]()}), + ) if err != nil { return types.Hash{}, nil, fmt.Errorf("submission of extrinsic failed: %w", err) } - hash, err := ExtrinsicHash(ext) + hash, err := DynamicExtrinsicHash(ext) if err != nil { return types.Hash{}, nil, err } @@ -144,13 +148,13 @@ func (c *SubstrateClient) nextNonce(meta *types.Metadata) (types.U32, error) { return latestNonce, nil } -func (c *SubstrateClient) submitAndWatchExtrinsic(opts types.SignatureOptions, ext *types.Extrinsic) (*author.ExtrinsicStatusSubscription, error) { - err := ext.Sign(*c.key, opts) +func (c *SubstrateClient) submitAndWatchExtrinsic(meta *types.Metadata, ext extrinsic.DynamicExtrinsic, opts ...extrinsic.SigningOption) (*author.ExtrinsicStatusSubscription, error) { + err := ext.Sign(*c.key, meta, opts...) if err != nil { return nil, err } - sub, err := c.Conn.RPC.Author.SubmitAndWatchExtrinsic(*ext) + sub, err := c.Conn.RPC.Author.SubmitAndWatchDynamicExtrinsic(ext) if err != nil { return nil, err } @@ -211,3 +215,13 @@ func ExtrinsicHash(ext types.Extrinsic) (types.Hash, error) { } return types.NewHash(extHash.Bytes()), nil } + +func DynamicExtrinsicHash(ext extrinsic.DynamicExtrinsic) (types.Hash, error) { + extHash := bytes.NewBuffer([]byte{}) + encoder := scale.NewEncoder(extHash) + err := ext.Encode(*encoder) + if err != nil { + return types.Hash{}, err + } + return types.NewHash(extHash.Bytes()), nil +} diff --git a/chains/substrate/connection/check_metadata_hash_enabled_connection.go b/chains/substrate/connection/check_metadata_hash_enabled_connection.go deleted file mode 100644 index 0b5e4a32..00000000 --- a/chains/substrate/connection/check_metadata_hash_enabled_connection.go +++ /dev/null @@ -1,106 +0,0 @@ -// The Licensed Work is (c) 2022 Sygma -// SPDX-License-Identifier: LGPL-3.0-only - -package connection - -import ( - "math/big" - "sync" - - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/client" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/registry/parser" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/registry/retriever" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/registry/state" - - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/rpc" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/rpc/chain" - "github.com/sygmaprotocol/go-substrate-rpc-client/v4/types" -) - -type CheckMetadataModeEnabledConnection struct { - chain.Chain - client.Client - *rpc.RPC - meta types.Metadata // Latest chain metadata - metaLock sync.RWMutex // Lock metadata for updates, allows concurrent reads - GenesisHash types.Hash // Chain genesis hash -} - -func NewCheckMetadataModeEnabledConnection(url string) (*CheckMetadataModeEnabledConnection, error) { - client, err := client.Connect(url) - if err != nil { - return nil, err - } - rpc, err := rpc.NewRPC(client) - if err != nil { - return nil, err - } - - meta, err := rpc.State.GetMetadataLatest() - if err != nil { - return nil, err - } - genesisHash, err := rpc.Chain.GetBlockHash(0) - if err != nil { - return nil, err - } - - return &CheckMetadataModeEnabledConnection{ - meta: *meta, - - RPC: rpc, - Chain: rpc.Chain, - Client: client, - GenesisHash: types.Hash(genesisHash), - }, nil -} - -func (c *CheckMetadataModeEnabledConnection) GetMetadata() (meta types.Metadata) { - c.metaLock.RLock() - meta = c.meta - c.metaLock.RUnlock() - return meta -} - -func (c *CheckMetadataModeEnabledConnection) UpdateMetatdata() error { - c.metaLock.Lock() - meta, err := c.RPC.State.GetMetadataLatest() - if err != nil { - c.metaLock.Unlock() - return err - } - c.meta = *meta - c.metaLock.Unlock() - return nil -} - -func (c *CheckMetadataModeEnabledConnection) GetBlockEvents(hash types.Hash) ([]*parser.Event, error) { - provider := state.NewEventProvider(c.State) - eventRetriever, err := retriever.NewDefaultEventRetriever(provider, c.State) - if err != nil { - return nil, err - } - - evts, err := eventRetriever.GetEvents(hash) - if err != nil { - return nil, err - } - return evts, nil -} - -func (c *CheckMetadataModeEnabledConnection) FetchEvents(startBlock, endBlock *big.Int) ([]*parser.Event, error) { - evts := make([]*parser.Event, 0) - for i := new(big.Int).Set(startBlock); i.Cmp(endBlock) <= 0; i.Add(i, big.NewInt(1)) { - hash, err := c.GetBlockHash(i.Uint64()) - if err != nil { - return nil, err - } - - evt, err := c.GetBlockEvents(hash) - if err != nil { - return nil, err - } - evts = append(evts, evt...) - } - return evts, nil -} diff --git a/go.mod b/go.mod index fe9dce43..ab36e116 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,12 @@ go 1.21 toolchain go1.22.2 require ( - github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1 + github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.2-0.20240724202640-8bafff8c25ea github.com/ethereum/go-ethereum v1.13.2 github.com/imdario/mergo v0.3.12 github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.25.0 github.com/stretchr/testify v1.8.3 - github.com/sygmaprotocol/go-substrate-rpc-client/v4 v4.2.2-0.20240813185906-0395c914c6f8 github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a go.opentelemetry.io/otel v1.16.0 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.39.0 diff --git a/go.sum b/go.sum index 2745b3ac..7008b650 100644 --- a/go.sum +++ b/go.sum @@ -58,8 +58,8 @@ github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlH github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1 h1:io49TJ8IOIlzipioJc9pJlrjgdJvqktpUWYxVY5AUjE= -github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1/go.mod h1:k61SBXqYmnZO4frAJyH3iuqjolYrYsq79r8EstmklDY= +github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.2-0.20240724202640-8bafff8c25ea h1:O2DsP9UvPHFXQVt5W/+i7H+KegncyVKEyO6tkZ9klUs= +github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.2-0.20240724202640-8bafff8c25ea/go.mod h1:k61SBXqYmnZO4frAJyH3iuqjolYrYsq79r8EstmklDY= github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -346,8 +346,6 @@ github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gt github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/sygmaprotocol/go-substrate-rpc-client/v4 v4.2.2-0.20240813185906-0395c914c6f8 h1:I1yWp/SlL96ZirqU6qhwvW1Mpmw7SnaAu+RfwBXYX/g= -github.com/sygmaprotocol/go-substrate-rpc-client/v4 v4.2.2-0.20240813185906-0395c914c6f8/go.mod h1:UMezfYq6Blh0C7RPTfNwtbVmNOSfu6mwoiu2F8kWUTI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a h1:1ur3QoCqvE5fl+nylMaIr9PVV1w343YRDtsy+Rwu7XI= github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=