diff --git a/.env.bitcoin b/.env.bitcoin deleted file mode 100644 index 62247cd663..0000000000 --- a/.env.bitcoin +++ /dev/null @@ -1,25 +0,0 @@ -BITCOIN_BRIDGE_AA_KERNEL_FACTORY=0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF25 -BITCOIN_BRIDGE_AA_SCA_REGISTRY=0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF24 -BITCOIN_BRIDGE_ABI=aaa.abi -BITCOIN_BRIDGE_CONTRACT_ADDRESS=0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF22 -BITCOIN_BRIDGE_ETH_PRIV_KEY= -BITCOIN_BRIDGE_ETH_RPC_URL=127.0.0.1:8545 -BITCOIN_BRIDGE_GAS_LIMIT=23333 -BITCOIN_DESTINATION=tb1qfhhxljfajcppfhwa09uxwty5dz4xwfptnqmvtv -BITCOIN_ENABLE_COMMITTER=false -BITCOIN_ENABLE_INDEXER=false -BITCOIN_EVM_DEPOSIT=0x01bee1bfa4116bd0440a1108ef6cb6a2f6eb9b611d8f53260aec20d39e84ee89 -BITCOIN_EVM_ENABLE_LISTENER=false -BITCOIN_EVM_WITHDRAW=0xda335c6ae73006d1145bdcf9a98bc76d789b653b13fe6200e6fc4c5dd54add86 -BITCOIN_INDEXER_LISTEN_ADDRESS=tb1qgm39cu009lyvq93afx47pp4h9wxq5x92lxxgnz -BITCOIN_NETWORK_NAME=testnet -BITCOIN_RPC_HOST=127.0.0.1 -BITCOIN_RPC_PASS=123456 -BITCOIN_RPC_PORT=8888 -BITCOIN_RPC_USER=test -BITCOIN_STATE_DB_NAME=db -BITCOIN_STATE_HOST=localhost -BITCOIN_STATE_PASS=password -BITCOIN_STATE_PORT=5432 -BITCOIN_STATE_USER=user -BITCOIN_WALLET_NAME=test diff --git a/app/app.go b/app/app.go index 26a058647b..4f9b6585a6 100644 --- a/app/app.go +++ b/app/app.go @@ -312,7 +312,7 @@ func NewEthermintApp( evmtypes.StoreKey, feemarkettypes.StoreKey, // committer key committertypes.StoreKey, - evmtypes.StoreKey, feemarkettypes.StoreKey, bridgemoduletypes.StoreKey, + bridgemoduletypes.StoreKey, ) // Add the EVM transient store key diff --git a/bitcoin/bridge.go b/bitcoin/bridge.go deleted file mode 100644 index 00492dd690..0000000000 --- a/bitcoin/bridge.go +++ /dev/null @@ -1,214 +0,0 @@ -package bitcoin - -import ( - "bytes" - "context" - "crypto/ecdsa" - "errors" - "fmt" - "math/big" - "net/url" - "os" - "path" - - b2aa "github.com/b2network/b2-go-aa-utils" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/accounts/abi/bind" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/ethclient" -) - -var ErrBrdigeDepositTxIDExist = errors.New("non-repeatable processing") - -// Bridge bridge -// TODO: only L1 -> L2, More calls may be supported later -type Bridge struct { - EthRPCURL string - EthPrivKey *ecdsa.PrivateKey - ContractAddress common.Address - ABI string - GasLimit uint64 - // AA contract address - AASCARegistry common.Address - AAKernelFactory common.Address -} - -// NewBridge new bridge -func NewBridge(bridgeCfg BridgeConfig, abiFileDir string) (*Bridge, error) { - rpcURL, err := url.ParseRequestURI(bridgeCfg.EthRPCURL) - if err != nil { - return nil, err - } - - privateKey, err := crypto.HexToECDSA(bridgeCfg.EthPrivKey) - if err != nil { - return nil, err - } - - abi, err := os.ReadFile(path.Join(abiFileDir, bridgeCfg.ABI)) - if err != nil { - return nil, err - } - - return &Bridge{ - EthRPCURL: rpcURL.String(), - ContractAddress: common.HexToAddress(bridgeCfg.ContractAddress), - EthPrivKey: privateKey, - ABI: string(abi), - GasLimit: bridgeCfg.GasLimit, - AASCARegistry: common.HexToAddress(bridgeCfg.AASCARegistry), - AAKernelFactory: common.HexToAddress(bridgeCfg.AAKernelFactory), - }, nil -} - -// Deposit to ethereum -func (b *Bridge) Deposit(hash string, bitcoinAddress string, amount int64) (string, error) { - if bitcoinAddress == "" { - return "", fmt.Errorf("bitcoin address is empty") - } - - if hash == "" { - return "", fmt.Errorf("tx id is empty") - } - - ctx := context.Background() - - toAddress, err := b.BitcoinAddressToEthAddress(bitcoinAddress) - if err != nil { - return "", fmt.Errorf("btc address to eth address err:%w", err) - } - - // TODO: hash check - // txHash, err := chainhash.NewHashFromStr(hash) - // if err != nil { - // return "", err - // } - - data, err := b.ABIPack(b.ABI, "deposit", common.HexToAddress(toAddress), new(big.Int).SetInt64(amount)) - if err != nil { - return "", fmt.Errorf("abi pack err:%w", err) - } - - receipt, err := b.sendTransaction(ctx, b.EthPrivKey, b.ContractAddress, data, 0) - if err != nil { - return "", fmt.Errorf("eth call err:%w", err) - } - - if receipt.Status != 1 { - receiptStr, err := receipt.MarshalJSON() - if err != nil { - return "", err - } - return "", fmt.Errorf("tx failed, receipt:%s", receiptStr) - } - return receipt.TxHash.String(), nil -} - -// Transfer to ethereum -func (b *Bridge) Transfer(bitcoinAddress string, amount int64) (string, error) { - if bitcoinAddress == "" { - return "", fmt.Errorf("bitcoin address is empty") - } - - ctx := context.Background() - - toAddress, err := b.BitcoinAddressToEthAddress(bitcoinAddress) - if err != nil { - return "", fmt.Errorf("btc address to eth address err:%w", err) - } - - receipt, err := b.sendTransaction(ctx, b.EthPrivKey, common.HexToAddress(toAddress), nil, amount*10000000000) - if err != nil { - return "", fmt.Errorf("eth call err:%w", err) - } - - if receipt.Status != 1 { - receiptStr, err := receipt.MarshalJSON() - if err != nil { - return "", err - } - return "", fmt.Errorf("tx failed, receipt:%s", receiptStr) - } - return receipt.TxHash.String(), nil -} - -func (b *Bridge) sendTransaction(ctx context.Context, fromPriv *ecdsa.PrivateKey, - toAddress common.Address, data []byte, value int64, -) (*types.Receipt, error) { - client, err := ethclient.Dial(b.EthRPCURL) - if err != nil { - return nil, err - } - - publicKey := fromPriv.Public() - publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) - if !ok { - return nil, fmt.Errorf("error casting public key to ECDSA") - } - nonce, err := client.PendingNonceAt(ctx, crypto.PubkeyToAddress(*publicKeyECDSA)) - if err != nil { - return nil, err - } - gasPrice, err := client.SuggestGasPrice(ctx) - if err != nil { - return nil, err - } - - legacyTx := types.LegacyTx{ - Nonce: nonce, - To: &toAddress, - Value: big.NewInt(value), - Gas: b.GasLimit, - GasPrice: gasPrice, - } - - if data != nil { - legacyTx.Data = data - } - - tx := types.NewTx(&legacyTx) - - chainID, err := client.ChainID(ctx) - if err != nil { - return nil, err - } - // sign tx - signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), fromPriv) - if err != nil { - return nil, err - } - - // send tx - err = client.SendTransaction(ctx, signedTx) - if err != nil { - return nil, err - } - - // wait tx confirm - return bind.WaitMined(ctx, client, signedTx) -} - -// ABIPack the given method name to conform the ABI. Method call's data -func (b *Bridge) ABIPack(abiData string, method string, args ...interface{}) ([]byte, error) { - contractAbi, err := abi.JSON(bytes.NewReader([]byte(abiData))) - if err != nil { - return nil, err - } - return contractAbi.Pack(method, args...) -} - -// BitcoinAddressToEthAddress bitcoin address to eth address -func (b *Bridge) BitcoinAddressToEthAddress(bitcoinAddress string) (string, error) { - client, err := ethclient.Dial(b.EthRPCURL) - if err != nil { - return "", err - } - - targetEthAddress, err := b2aa.GetSCAAddress(client, b.AASCARegistry, b.AAKernelFactory, bitcoinAddress) - if err != nil { - return "", err - } - return targetEthAddress.String(), nil -} diff --git a/bitcoin/bridge_test.go b/bitcoin/bridge_test.go deleted file mode 100644 index c65bac1cfa..0000000000 --- a/bitcoin/bridge_test.go +++ /dev/null @@ -1,225 +0,0 @@ -package bitcoin_test - -import ( - "errors" - "math/big" - "os" - "path" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" - "github.com/evmos/ethermint/bitcoin" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestNewBridge(t *testing.T) { - abiPath := path.Join("./testdata") - - abi, err := os.ReadFile(path.Join("./testdata", "abi.json")) - if err != nil { - t.Fatal(err) - } - - privateKey, err := crypto.HexToECDSA("0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") - if err != nil { - t.Fatal(err) - } - - bridgeCfg := bitcoin.BridgeConfig{ - EthRPCURL: "http://localhost:8545", - ContractAddress: "0x123456789abcdef", - EthPrivKey: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", - ABI: "abi.json", - GasLimit: 1000000, - AASCARegistry: "0x123456789abcdefgh", - AAKernelFactory: "0x123456789abcdefg", - } - - bridge, err := bitcoin.NewBridge(bridgeCfg, abiPath) - assert.NoError(t, err) - assert.NotNil(t, bridge) - assert.Equal(t, bridgeCfg.EthRPCURL, bridge.EthRPCURL) - assert.Equal(t, common.HexToAddress("0x123456789abcdef"), bridge.ContractAddress) - assert.Equal(t, privateKey, bridge.EthPrivKey) - assert.Equal(t, string(abi), bridge.ABI) - assert.Equal(t, common.HexToAddress("0x123456789abcdefgh"), bridge.AASCARegistry) - assert.Equal(t, common.HexToAddress("0x123456789abcdefg"), bridge.AAKernelFactory) -} - -// TestLocalDeposit only test in local -func TestLocalDeposit(t *testing.T) { - bridge := bridgeWithConfig(t) - testCase := []struct { - name string - args []interface{} - err error - }{ - { - name: "success", - args: []interface{}{ - "1c7fd15bd884524c8bc4c3b44e6839c013b4ad951972af454f926e0b6bdc570f", - "tb1qjda2l5spwyv4ekwe9keddymzuxynea2m2kj0qy", - int64(1234), - }, - err: nil, - }, - { - name: "fail: address empty", - args: []interface{}{ - "1c7fd15bd884524c8bc4c3b44e6839c013b4ad951972af454f926e0b6bdc570f", - "", - int64(1234), - }, - err: errors.New("bitcoin address is empty"), - }, - { - name: "fail: tx id empty", - args: []interface{}{ - "", - "tb1qjda2l5spwyv4ekwe9keddymzuxynea2m2kj0qy", - int64(1234), - }, - err: errors.New("tx id is empty"), - }, - } - - for _, tc := range testCase { - t.Run(tc.name, func(t *testing.T) { - hex, err := bridge.Deposit(tc.args[0].(string), tc.args[1].(string), tc.args[2].(int64)) - if err != nil { - assert.Equal(t, tc.err, err) - } - t.Log(hex) - }) - } -} - -// TestLocalTransfer only test in local -func TestLocalTransfer(t *testing.T) { - bridge := bridgeWithConfig(t) - testCase := []struct { - name string - args []interface{} - err error - }{ - { - name: "success", - args: []interface{}{ - "tb1qjda2l5spwyv4ekwe9keddymzuxynea2m2kj0qy", - int64(123456), - }, - err: nil, - }, - { - name: "fail: address empty", - args: []interface{}{ - "", - int64(1234), - }, - err: errors.New("bitcoin address is empty"), - }, - } - - for _, tc := range testCase { - t.Run(tc.name, func(t *testing.T) { - hex, err := bridge.Transfer(tc.args[0].(string), tc.args[1].(int64)) - if err != nil { - assert.Equal(t, tc.err, err) - } - t.Log(hex) - }) - } -} - -// TestLocalBitcoinAddressToEthAddress only test in local -func TestLocalBitcoinAddressToEthAddress(t *testing.T) { - bridge := bridgeWithConfig(t) - testCase := []struct { - name string - bitcoinAddress string - ethAddress string - }{ - { - name: "success: Segwit (bech32)", - bitcoinAddress: "tb1qjda2l5spwyv4ekwe9keddymzuxynea2m2kj0qy", - ethAddress: "0x2A9E233eE5d68fD70DE6C4b1d1Ffa29256e3ee9D", - }, - { - name: "success: Segwit (bech32)", - bitcoinAddress: "bc1qf60zw2gec5qg2mk4nyjl0slnytu0s0p28k9her", - ethAddress: "0x1b98017D9d6A9B62a2CFb2764D8012e28606BD49", - }, - { - name: "success: Legacy", - bitcoinAddress: "1KEFsFXrvuzMGd7Sdkwp7iTDcEcEv3GP1y", - ethAddress: "0x30f789e9C889A68180ef63F37cac923D89571394", - }, - { - name: "success: Segwit", - bitcoinAddress: "3Q4g8hgbwZLZ7vA6U1Xp1UsBs7NBnC7zKS", - ethAddress: "0x0aB97EA8eDff3e28867EAe9e13C02e5aA6214f59", - }, - } - - for _, tc := range testCase { - t.Run(tc.name, func(t *testing.T) { - ethAddress, err := bridge.BitcoinAddressToEthAddress(tc.bitcoinAddress) - require.NoError(t, err) - assert.Equal(t, tc.ethAddress, ethAddress) - }) - } -} - -func TestABIPack(t *testing.T) { - t.Run("success", func(t *testing.T) { - abiData, err := os.ReadFile(path.Join("./testdata", "abi.json")) - if err != nil { - t.Fatal(err) - } - expectedMethod := "deposit" - expectedArgs := []interface{}{common.HexToAddress("0x12345678"), new(big.Int).SetInt64(1111)} - expectedResult := []byte{ - 71, 231, 239, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18, 52, 86, 120, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 4, 87, - } - - // Create a mock bridge object - b := &bitcoin.Bridge{} - - // Call the ABIPack method - result, err := b.ABIPack(string(abiData), expectedMethod, expectedArgs...) - // Check for errors - if err != nil { - t.Errorf("Unexpected error: %v", err) - } - - // Compare the result with the expected result - require.Equal(t, result, expectedResult) - }) - - t.Run("Invalid ABI data", func(t *testing.T) { - abiData := `{"inputs": [{"type": "address", "name": "to"}, {"type": "uint256", "name": "value"}` - expectedError := errors.New("unexpected EOF") - - // Create a mock bridge object - b := &bitcoin.Bridge{} - - // Call the ABIPack method - _, err := b.ABIPack(abiData, "method", "arg1", "arg2") - - require.EqualError(t, err, expectedError.Error()) - }) -} - -func bridgeWithConfig(t *testing.T) *bitcoin.Bridge { - config, err := bitcoin.LoadBitcoinConfig("./testdata") - require.NoError(t, err) - - bridge, err := bitcoin.NewBridge(config.Bridge, "./testdata") - require.NoError(t, err) - return bridge -} diff --git a/bitcoin/commiter_service.go b/bitcoin/commiter_service.go deleted file mode 100644 index 437371d331..0000000000 --- a/bitcoin/commiter_service.go +++ /dev/null @@ -1,113 +0,0 @@ -package bitcoin - -import ( - "strconv" - "time" - - dbm "github.com/tendermint/tm-db" - - "github.com/tendermint/tendermint/libs/service" -) - -const ( - BitcoinServiceName = "BitcoinCommitterService" - - WaitTimeout = 10 * time.Minute -) - -// CommitterService is a service that commits bitcoin transactions. -type CommitterService struct { - service.BaseService - committer *Committer - db dbm.DB -} - -// NewIndexerService returns a new service instance. -func NewCommitterService( - committer *Committer, - db dbm.DB, -) *CommitterService { - is := &CommitterService{committer: committer} - is.BaseService = *service.NewBaseService(nil, BitcoinServiceName, is) - is.db = db - return is -} - -// OnStart -func (bis *CommitterService) OnStart() error { - ticker := time.NewTicker(WaitTimeout) - for { - bis.Logger.Info("committer start....") - <-ticker.C - ticker.Reset(WaitTimeout) - - index := int64(0) - blockNumMax, err := bis.db.Get([]byte("blockNumMax")) - if err != nil { - bis.Logger.Error("Failed to get blockNumMax", "err", err) - continue - } - if blockNumMax != nil { - index, err = strconv.ParseInt(string(blockNumMax), 10, 64) - if err != nil { - bis.Logger.Error("Failed to parse blockNumMax", "err", err) - continue - } - } - - roots, err := GetStateRoot(bis.committer.stateConfig, index) - if err != nil { - bis.Logger.Error("Failed to get state root", "err", err) - continue - } - if roots == nil { - continue - } - dataList := make([]InscriptionData, 0) - for _, root := range roots { - dataList = append(dataList, InscriptionData{ - Body: []byte(root.StateRoot), - Destination: bis.committer.destination, - }) - if root.BlockNum > index { - index = root.BlockNum - } - } - - req, err := NewRequest(bis.committer.client, dataList) // update latest block - if err != nil { - bis.Logger.Error("committer init req error", "err", err) - continue - } - tool, err := NewInscriptionTool(bis.committer.chainParams, bis.committer.client, req) - if err != nil { - bis.Logger.Error("Failed to create inscription tool", "err", err) - continue - } - err = tool.BackupRecoveryKeyToRPCNode() - if err != nil { - bis.Logger.Error("Failed to backup recovery key", "err", err) - continue - } - commitTxHash, revealTxHashList, inscriptions, fees, err := tool.Inscribe() - if err != nil { - bis.Logger.Error("Failed to inscribe", "err", err) - continue - } - bis.Logger.Info("commitTxHash," + commitTxHash.String()) - for i := range revealTxHashList { - bis.Logger.Info("revealTxHash," + revealTxHashList[i].String()) - } - for i := range inscriptions { - bis.Logger.Info("inscriptions," + inscriptions[i]) - } - bis.Logger.Info("fees:", "fee", fees) - - indexStr := strconv.FormatInt(index, 10) - err = bis.db.Set([]byte("blockNumMax"), []byte(indexStr)) - if err != nil { - bis.Logger.Error("Failed to set blockNumMax", "err", err) - continue - } - } -} diff --git a/bitcoin/committer.go b/bitcoin/committer.go deleted file mode 100644 index d130348a82..0000000000 --- a/bitcoin/committer.go +++ /dev/null @@ -1,527 +0,0 @@ -package bitcoin - -import ( - "encoding/hex" - "fmt" - "log" - - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/chaincfg/chainhash" - - "github.com/btcsuite/btcd/blockchain" - "github.com/btcsuite/btcd/btcec/v2" - "github.com/btcsuite/btcd/btcec/v2/schnorr" - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/mempool" - "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - "github.com/pkg/errors" -) - -// InscriptionData is the data of an inscription -type InscriptionData struct { - Body []byte // The body of the inscription - Destination string // The destination of the inscription -} - -// InscriptionRequest is the request of an inscription -type InscriptionRequest struct { - CommitTxOutPointList []*wire.OutPoint - // a local signature is required for committing the commit tx. - // Currently, CommitTxPrivateKeyList[i] sign CommitTxOutPointList[i] - CommitFeeRate int64 - FeeRate int64 - DataList []InscriptionData - // SingleRevealTxOnly bool // Currently, the official Ordinal parser can only parse a single NFT per transaction. - // When the official Ordinal parser supports parsing multiple NFTs in the future, we can consider using a single reveal transaction. - RevealOutValue int64 -} - -// inscriptionTxCtxData is the context of an inscription -type inscriptionTxCtxData struct { - privateKey *btcec.PrivateKey - inscriptionScript []byte - commitTxAddressPkScript []byte - controlBlockWitness []byte - recoveryPrivateKeyWIF string - revealTxPrevOutput *wire.TxOut -} - -// InscriptionTool is the tool of an inscription -type InscriptionTool struct { - net *chaincfg.Params - client *rpcclient.Client - commitTxPrevOutputFetcher *txscript.MultiPrevOutFetcher - commitTxPrivateKeyList []*btcec.PrivateKey - txCtxDataList []*inscriptionTxCtxData - revealTxPrevOutputFetcher *txscript.MultiPrevOutFetcher - revealTx []*wire.MsgTx - commitTx *wire.MsgTx -} - -const ( - defaultSequenceNum = wire.MaxTxInSequenceNum - 10 - defaultRevealOutValue = int64(500) // 500 sat, ord default 10000 - - MaxStandardTxWeight = blockchain.MaxBlockWeight / 10 -) - -// Committer is the committer of an inscription -type Committer struct { - client *rpcclient.Client - chainParams *chaincfg.Params - destination string - stateConfig StateConfig -} - -// BlockChainInfo gets the blockchain info -func (b *Committer) BlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) { - return b.client.GetBlockChainInfo() -} - -// NewCommitter creates a new Committer -func NewCommitter(client *rpcclient.Client, network string, destination string, stateConfig StateConfig) (*Committer, error) { - if network == "" { - return nil, errors.New("committer network is empty") - } - params := chaincfg.MainNetParams - switch network { - case chaincfg.MainNetParams.Name: - params = chaincfg.MainNetParams - case chaincfg.SigNetParams.Name: - params = chaincfg.SigNetParams - case chaincfg.TestNet3Params.Name: - params = chaincfg.TestNet3Params - case chaincfg.SimNetParams.Name: - params = chaincfg.SimNetParams - case chaincfg.RegressionNetParams.Name: - params = chaincfg.RegressionNetParams - default: - params = chaincfg.TestNet3Params - } - return &Committer{ - client: client, - chainParams: ¶ms, - destination: destination, - stateConfig: stateConfig, - }, nil -} - -// NewRequest creates a new InscriptionRequest -func NewRequest(rpcclient *rpcclient.Client, dataList []InscriptionData) (*InscriptionRequest, error) { - commitTxOutPointList := make([]*wire.OutPoint, 0) - unspentList, err := rpcclient.ListUnspent() - if err != nil { - return nil, err - } - for i := range unspentList { - inTxid, err := chainhash.NewHashFromStr(unspentList[i].TxID) - if err != nil { - return nil, err - } - commitTxOutPointList = append(commitTxOutPointList, wire.NewOutPoint(inTxid, unspentList[i].Vout)) - } - return &InscriptionRequest{ - CommitTxOutPointList: commitTxOutPointList, - DataList: dataList, - CommitFeeRate: 25, - FeeRate: 26, - }, nil -} - -// NewInscriptionTool creates a new InscriptionTool -func NewInscriptionTool(net *chaincfg.Params, rpcclient *rpcclient.Client, request *InscriptionRequest) (*InscriptionTool, error) { - tool := &InscriptionTool{ - net: net, - client: rpcclient, - commitTxPrevOutputFetcher: txscript.NewMultiPrevOutFetcher(nil), - txCtxDataList: make([]*inscriptionTxCtxData, len(request.DataList)), - revealTxPrevOutputFetcher: txscript.NewMultiPrevOutFetcher(nil), - } - return tool, tool._initTool(net, request) -} - -// _initTool initializes the InscriptionTool -func (tool *InscriptionTool) _initTool(net *chaincfg.Params, request *InscriptionRequest) error { - revealOutValue := defaultRevealOutValue - if request.RevealOutValue > 0 { - revealOutValue = request.RevealOutValue - } - tool.txCtxDataList = make([]*inscriptionTxCtxData, len(request.DataList)) - destinations := make([]string, len(request.DataList)) - for i := 0; i < len(request.DataList); i++ { - txCtxData, err := createInscriptionTxCtxData(net, request.DataList[i]) - if err != nil { - return err - } - tool.txCtxDataList[i] = txCtxData - destinations[i] = request.DataList[i].Destination - } - totalRevealPrevOutput, err := tool.buildEmptyRevealTx(destinations, revealOutValue, request.FeeRate) - if err != nil { - return err - } - err = tool.buildCommitTx(request.CommitTxOutPointList, totalRevealPrevOutput, request.CommitFeeRate) - if err != nil { - return err - } - err = tool.completeRevealTx() - if err != nil { - return err - } - err = tool.signCommitTx() - if err != nil { - return errors.Wrap(err, "sign commit tx error") - } - return err -} - -// createInscriptionTxCtxData creates a new inscriptionTxCtxData -func createInscriptionTxCtxData(net *chaincfg.Params, data InscriptionData) (*inscriptionTxCtxData, error) { - privateKey, err := btcec.NewPrivateKey() - if err != nil { - return nil, err - } - inscriptionBuilder := txscript.NewScriptBuilder(). - AddData(schnorr.SerializePubKey(privateKey.PubKey())). - AddOp(txscript.OP_CHECKSIG). - AddOp(txscript.OP_FALSE). - AddOp(txscript.OP_IF) - maxChunkSize := 520 - bodySize := len(data.Body) - for i := 0; i < bodySize; i += maxChunkSize { - end := i + maxChunkSize - if end > bodySize { - end = bodySize - } - // to skip txscript.MaxScriptSize 10000 - inscriptionBuilder.AddFullData(data.Body[i:end]) - } - inscriptionScript, err := inscriptionBuilder.Script() - if err != nil { - return nil, err - } - // to skip txscript.MaxScriptSize 10000 - inscriptionScript = append(inscriptionScript, txscript.OP_ENDIF) - - leafNode := txscript.NewBaseTapLeaf(inscriptionScript) - proof := &txscript.TapscriptProof{ - TapLeaf: leafNode, - RootNode: leafNode, - } - - controlBlock := proof.ToControlBlock(privateKey.PubKey()) - controlBlockWitness, err := controlBlock.ToBytes() - if err != nil { - return nil, err - } - - tapHash := proof.RootNode.TapHash() - commitTxAddress, err := btcutil.NewAddressTaproot(schnorr.SerializePubKey(txscript.ComputeTaprootOutputKey(privateKey.PubKey(), tapHash[:])), net) - if err != nil { - return nil, err - } - commitTxAddressPkScript, err := txscript.PayToAddrScript(commitTxAddress) - if err != nil { - return nil, err - } - - recoveryPrivateKeyWIF, err := btcutil.NewWIF(txscript.TweakTaprootPrivKey(*privateKey, tapHash[:]), net, true) - if err != nil { - return nil, err - } - - return &inscriptionTxCtxData{ - privateKey: privateKey, - inscriptionScript: inscriptionScript, - commitTxAddressPkScript: commitTxAddressPkScript, - controlBlockWitness: controlBlockWitness, - recoveryPrivateKeyWIF: recoveryPrivateKeyWIF.String(), - }, nil -} - -// buildEmptyRevealTx builds an empty reveal transaction, and calculate the revealTx input value, it means the total value of the reveal transaction -func (tool *InscriptionTool) buildEmptyRevealTx(destination []string, revealOutValue, feeRate int64) (int64, error) { - var revealTx []*wire.MsgTx - totalPrevOutput := int64(0) - total := len(tool.txCtxDataList) - addTxInTxOutIntoRevealTx := func(tx *wire.MsgTx, index int) error { - in := wire.NewTxIn(&wire.OutPoint{Index: uint32(index)}, nil, nil) // #nosec 701 - in.Sequence = defaultSequenceNum - tx.AddTxIn(in) - receiver, err := btcutil.DecodeAddress(destination[index], tool.net) - if err != nil { - return err - } - scriptPubKey, err := txscript.PayToAddrScript(receiver) - if err != nil { - return err - } - out := wire.NewTxOut(revealOutValue, scriptPubKey) - tx.AddTxOut(out) - return nil - } - - revealTx = make([]*wire.MsgTx, total) - for i := 0; i < total; i++ { - tx := wire.NewMsgTx(wire.TxVersion) - err := addTxInTxOutIntoRevealTx(tx, i) - if err != nil { - return 0, err - } - prevOutput := revealOutValue + int64(tx.SerializeSize())*feeRate - { - emptySignature := make([]byte, 64) - emptyControlBlockWitness := make([]byte, 33) - fee := (int64(wire.TxWitness{emptySignature, tool.txCtxDataList[i].inscriptionScript, emptyControlBlockWitness}.SerializeSize()+2+3) / 4) * feeRate - prevOutput += fee - tool.txCtxDataList[i].revealTxPrevOutput = &wire.TxOut{ - PkScript: tool.txCtxDataList[i].commitTxAddressPkScript, - Value: prevOutput, - } - } - totalPrevOutput += prevOutput - revealTx[i] = tx - } - - tool.revealTx = revealTx - return totalPrevOutput, nil -} - -// buildCommitTx builds a commit transaction -func (tool *InscriptionTool) buildCommitTx(commitTxOutPointList []*wire.OutPoint, totalRevealPrevOutput, commitFeeRate int64) error { - totalSenderAmount := btcutil.Amount(0) - tx := wire.NewMsgTx(wire.TxVersion) - var changePkScript *[]byte - for i := range commitTxOutPointList { - log.Println("point:" + commitTxOutPointList[i].String()) - txOut, err := tool.getTxOutByOutPoint(commitTxOutPointList[i]) - if err != nil { - return err - } - if changePkScript == nil { // first sender as change address - changePkScript = &txOut.PkScript - } - in := wire.NewTxIn(commitTxOutPointList[i], nil, nil) - in.Sequence = defaultSequenceNum - tx.AddTxIn(in) - - totalSenderAmount += btcutil.Amount(txOut.Value) - } - for i := range tool.txCtxDataList { - tx.AddTxOut(tool.txCtxDataList[i].revealTxPrevOutput) - } - - tx.AddTxOut(wire.NewTxOut(0, *changePkScript)) - fee := btcutil.Amount(mempool.GetTxVirtualSize(btcutil.NewTx(tx))) * btcutil.Amount(commitFeeRate) - changeAmount := totalSenderAmount - btcutil.Amount(totalRevealPrevOutput) - fee - if changeAmount > 0 { - tx.TxOut[len(tx.TxOut)-1].Value = int64(changeAmount) - } else { - tx.TxOut = tx.TxOut[:len(tx.TxOut)-1] - if changeAmount < 0 { - feeWithoutChange := btcutil.Amount(mempool.GetTxVirtualSize(btcutil.NewTx(tx))) * btcutil.Amount(commitFeeRate) - if totalSenderAmount-btcutil.Amount(totalRevealPrevOutput)-feeWithoutChange < 0 { - return errors.New("insufficient balance") - } - } - } - tool.commitTx = tx - return nil -} - -// getTxOutByOutPoint gets the txOut by outPoint -func (tool *InscriptionTool) getTxOutByOutPoint(outPoint *wire.OutPoint) (*wire.TxOut, error) { - var txOut *wire.TxOut - tx, err := tool.client.GetRawTransactionVerbose(&outPoint.Hash) - if err != nil { - return nil, err - } - if int(outPoint.Index) >= len(tx.Vout) { // #nosec G701 - return nil, errors.New("err out point") - } - vout := tx.Vout[outPoint.Index] - pkScript, err := hex.DecodeString(vout.ScriptPubKey.Hex) - if err != nil { - return nil, err - } - amount, err := btcutil.NewAmount(vout.Value) - if err != nil { - return nil, err - } - txOut = wire.NewTxOut(int64(amount), pkScript) - - tool.commitTxPrevOutputFetcher.AddPrevOut(*outPoint, txOut) - return txOut, nil -} - -// completeRevealTx completes the reveal transaction -func (tool *InscriptionTool) completeRevealTx() error { - for i := range tool.txCtxDataList { - tool.revealTxPrevOutputFetcher.AddPrevOut(wire.OutPoint{ - Hash: tool.commitTx.TxHash(), - Index: uint32(i), // #nosec 701 - }, tool.txCtxDataList[i].revealTxPrevOutput) - if len(tool.revealTx) == 1 { - tool.revealTx[0].TxIn[i].PreviousOutPoint.Hash = tool.commitTx.TxHash() - } else { - tool.revealTx[i].TxIn[0].PreviousOutPoint.Hash = tool.commitTx.TxHash() - } - } - witnessList := make([]wire.TxWitness, len(tool.txCtxDataList)) - for i := range tool.txCtxDataList { - revealTx := tool.revealTx[0] - idx := i - if len(tool.revealTx) != 1 { - revealTx = tool.revealTx[i] - idx = 0 - } - witnessArray, err := txscript.CalcTapscriptSignaturehash(txscript.NewTxSigHashes(revealTx, tool.revealTxPrevOutputFetcher), - txscript.SigHashDefault, revealTx, idx, tool.revealTxPrevOutputFetcher, txscript.NewBaseTapLeaf(tool.txCtxDataList[i].inscriptionScript)) - if err != nil { - return err - } - signature, err := schnorr.Sign(tool.txCtxDataList[i].privateKey, witnessArray) - if err != nil { - return err - } - witnessList[i] = wire.TxWitness{signature.Serialize(), tool.txCtxDataList[i].inscriptionScript, tool.txCtxDataList[i].controlBlockWitness} - } - for i := range witnessList { - if len(tool.revealTx) == 1 { - tool.revealTx[0].TxIn[i].Witness = witnessList[i] - } else { - tool.revealTx[i].TxIn[0].Witness = witnessList[i] - } - } - // check tx max tx wight - for i, tx := range tool.revealTx { - revealWeight := blockchain.GetTransactionWeight(btcutil.NewTx(tx)) - if revealWeight > MaxStandardTxWeight { - return fmt.Errorf("reveal(index %d) transaction weight greater "+ - "than %d (MAX_STANDARD_TX_WEIGHT): %d", i, MaxStandardTxWeight, revealWeight) - } - } - return nil -} - -// signCommitTx signs the commit transaction -func (tool *InscriptionTool) signCommitTx() error { - if len(tool.commitTxPrivateKeyList) == 0 { - commitSignTransaction, isSignComplete, err := tool.client.SignRawTransactionWithWallet(tool.commitTx) - if err != nil { - log.Printf("sign commit tx error, %v", err) - return err - } - if !isSignComplete { - return errors.New("sign commit tx error") - } - tool.commitTx = commitSignTransaction - } else { - witnessList := make([]wire.TxWitness, len(tool.commitTx.TxIn)) - for i := range tool.commitTx.TxIn { - txOut := tool.commitTxPrevOutputFetcher.FetchPrevOutput(tool.commitTx.TxIn[i].PreviousOutPoint) - witness, err := txscript.TaprootWitnessSignature(tool.commitTx, txscript.NewTxSigHashes(tool.commitTx, tool.commitTxPrevOutputFetcher), - i, txOut.Value, txOut.PkScript, txscript.SigHashDefault, tool.commitTxPrivateKeyList[i]) - if err != nil { - return err - } - witnessList[i] = witness - } - for i := range witnessList { - tool.commitTx.TxIn[i].Witness = witnessList[i] - } - } - return nil -} - -// BackupRecoveryKeyToRpcNode backup the recovery key to rpc node -func (tool *InscriptionTool) BackupRecoveryKeyToRPCNode() error { - if tool.client == nil { - return errors.New("rpc client is nil") - } - descriptors := make([]Descriptor, len(tool.txCtxDataList)) - for i := range tool.txCtxDataList { - descriptorInfo, err := tool.client.GetDescriptorInfo(fmt.Sprintf("rawtr(%s)", tool.txCtxDataList[i].recoveryPrivateKeyWIF)) - if err != nil { - return err - } - descriptors[i] = Descriptor{ - Desc: *btcjson.String(fmt.Sprintf("rawtr(%s)#%s", tool.txCtxDataList[i].recoveryPrivateKeyWIF, descriptorInfo.Checksum)), - Timestamp: btcjson.TimestampOrNow{ - Value: "now", - }, - Active: btcjson.Bool(false), - Range: nil, - NextIndex: nil, - Internal: btcjson.Bool(false), - Label: btcjson.String("commit tx recovery key"), - } - } - results, err := ImportDescriptors(tool.client, descriptors) - if err != nil { - return err - } - if results == nil { - return errors.New("commit tx recovery key import failed, nil result") - } - for _, result := range *results { - if !result.Success { - return errors.New("commit tx recovery key import failed") - } - } - return nil -} - -// Inscribe inscribes the data -func (tool *InscriptionTool) Inscribe() (commitTxHash *chainhash.Hash, revealTxHashList []*chainhash.Hash, - inscriptions []string, fees int64, err error, -) { - fees = tool.calculateFee() - commitTxHash, err = tool.client.SendRawTransaction(tool.commitTx, false) - if err != nil { - return nil, nil, nil, fees, errors.Wrap(err, "send commit tx error") - } - revealTxHashList = make([]*chainhash.Hash, len(tool.revealTx)) - inscriptions = make([]string, len(tool.txCtxDataList)) - for i := range tool.revealTx { - _revealTxHash, err := tool.client.SendRawTransaction(tool.revealTx[i], false) - if err != nil { - return commitTxHash, revealTxHashList, nil, fees, errors.Wrap(err, fmt.Sprintf("send reveal tx error, %d。", i)) - } - revealTxHashList[i] = _revealTxHash - if len(tool.revealTx) == len(tool.txCtxDataList) { - inscriptions[i] = fmt.Sprintf("%si0", _revealTxHash) - } else { - inscriptions[i] = fmt.Sprintf("%si", _revealTxHash) - } - } - if len(tool.revealTx) != len(tool.txCtxDataList) { - for i := len(inscriptions) - 1; i > 0; i-- { - inscriptions[i] = fmt.Sprintf("%s%d", inscriptions[0], i) - } - } - return commitTxHash, revealTxHashList, inscriptions, fees, nil -} - -// calculateFee calculates the fee -func (tool *InscriptionTool) calculateFee() int64 { - fees := int64(0) - for _, in := range tool.commitTx.TxIn { - fees += tool.commitTxPrevOutputFetcher.FetchPrevOutput(in.PreviousOutPoint).Value - } - for _, out := range tool.commitTx.TxOut { - fees -= out.Value - } - for _, tx := range tool.revealTx { - for _, in := range tx.TxIn { - fees += tool.revealTxPrevOutputFetcher.FetchPrevOutput(in.PreviousOutPoint).Value - } - for _, out := range tx.TxOut { - fees -= out.Value - } - } - return fees -} diff --git a/bitcoin/committer_test.go b/bitcoin/committer_test.go deleted file mode 100644 index fc775c5646..0000000000 --- a/bitcoin/committer_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package bitcoin_test - -import ( - "log" - "testing" - - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcd/wire" - "github.com/evmos/ethermint/bitcoin" -) - -func TestNewInscriptionTool(t *testing.T) { - config, err := bitcoin.LoadBitcoinConfig("./testdata") - connCfg := &rpcclient.ConnConfig{ - Host: config.RPCHost + ":" + config.RPCPort + "/wallet/" + config.WalletName, - User: config.RPCUser, - Pass: config.RPCPass, - HTTPPostMode: true, - DisableTLS: true, - } - client, _ := rpcclient.New(connCfg, nil) - commitTxOutPointList := make([]*wire.OutPoint, 0) - unspentList, _ := client.ListUnspent() - for i := range unspentList { - inTxid, _ := chainhash.NewHashFromStr(unspentList[i].TxID) - commitTxOutPointList = append(commitTxOutPointList, wire.NewOutPoint(inTxid, unspentList[i].Vout)) - } - req := bitcoin.InscriptionRequest{ - CommitTxOutPointList: commitTxOutPointList, - CommitFeeRate: 25, - FeeRate: 26, - DataList: []bitcoin.InscriptionData{ - { - Destination: config.Destination, - Body: []byte("hello world"), - }, - }, - RevealOutValue: 500, - } - tool, err := bitcoin.NewInscriptionTool(&chaincfg.TestNet3Params, client, &req) - if err != nil { - log.Fatalf("Failed to create inscription tool: %v", err) - } - err = tool.BackupRecoveryKeyToRPCNode() - if err != nil { - log.Fatalf("Failed to backup recovery key: %v", err) - } - commitTxHash, revealTxHashList, inscriptions, fees, err := tool.Inscribe() - if err != nil { - log.Fatalf("send tx errr, %v", err) - } - log.Println("commitTxHash, " + commitTxHash.String()) - for i := range revealTxHashList { - log.Println("revealTxHash, " + revealTxHashList[i].String()) - } - for i := range inscriptions { - log.Println("inscription, " + inscriptions[i]) - } - log.Println("fees: ", fees) -} diff --git a/bitcoin/config.go b/bitcoin/config.go deleted file mode 100644 index a54bd6f54c..0000000000 --- a/bitcoin/config.go +++ /dev/null @@ -1,247 +0,0 @@ -package bitcoin - -import ( - "os" - "path" - "strings" - - "github.com/btcsuite/btcd/chaincfg" - "github.com/spf13/viper" -) - -// BitconConfig defines the bitcoin config -// TODO: defined different config group eg: bitcoin, bridge, indexer, commiter -type BitconConfig struct { - // NetworkName defines the bitcoin network name - NetworkName string `mapstructure:"network-name"` - // RPCHost defines the bitcoin rpc host - RPCHost string `mapstructure:"rpc-host"` - // RPCPort defines the bitcoin rpc port - RPCPort string `mapstructure:"rpc-port"` - // RPCUser defines the bitcoin rpc user - RPCUser string `mapstructure:"rpc-user"` - // RPCPass defines the bitcoin rpc password - RPCPass string `mapstructure:"rpc-pass"` - // WalletName defines the bitcoin wallet name - WalletName string `mapstructure:"wallet-name"` - // Destination defines the taproot transaction destination address - Destination string `mapstructure:"destination"` - // EnableIndexer defines whether to enable the indexer - EnableIndexer bool `mapstructure:"enable-indexer"` - // EnableCommitter defines whether to enable the committer - EnableCommitter bool `mapstructure:"enable-committer"` - // IndexerListenAddress defines the address to listen on - IndexerListenAddress string `mapstructure:"indexer-listen-address"` - // Bridge defines the bridge config - Bridge BridgeConfig `mapstructure:"bridge"` - // Dsn defines the state db dsn - StateConfig StateConfig `mapstructure:"state"` - // Fee defines the bitcoin tx fee - Fee int64 `mapstructure:"fee"` - // Evm defines the evm config - Evm EvmConfig `mapstructure:"evm"` -} - -type BridgeConfig struct { - // EthRPCURL defines the ethereum rpc url - EthRPCURL string `mapstructure:"eth-rpc-url"` - // EthPrivKey defines the invoke ethereum private key - EthPrivKey string `mapstructure:"eth-priv-key"` - // ContractAddress defines the l1 -> l2 bridge contract address - ContractAddress string `mapstructure:"contract-address"` - // ABI defines the l1 -> l2 bridge contract abi - ABI string `mapstructure:"abi"` - // GasLimit defines the contract gas limit - GasLimit uint64 `mapstructure:"gas-limit"` - // AASCARegistry defines the contract AASCARegistry address - AASCARegistry string `mapstructure:"aa-sca-registry"` - // AAKernelFactory defines the contract AAKernelFactory address - AAKernelFactory string `mapstructure:"aa-kernel-factory"` -} - -type StateConfig struct { - Host string `mapstructure:"host"` - Port int `mapstructure:"port"` - User string `mapstructure:"user"` - Pass string `mapstructure:"pass"` - DBName string `mapstructure:"db-name"` -} - -type EvmConfig struct { - // EnableListener defines whether to enable the listener - EnableListener bool `mapstructure:"enable-listener"` - // Deposit defines the deposit event hash - Deposit string `mapstructure:"deposit"` - // Withdraw defines the withdraw event hash - Withdraw string `mapstructure:"withdraw"` -} - -const ( - BitcoinRPCConfigFileName = "bitcoin.toml" -) - -func LoadBitcoinConfig(homePath string) (*BitconConfig, error) { - config := BitconConfig{} - configFile := path.Join(homePath, BitcoinRPCConfigFileName) - _, err := os.Stat(configFile) - if err != nil { - // if file not exist use default config - // TODO: add gen config command after, The default configuration may not be required - if !os.IsNotExist(err) { - return nil, err - } - // config.NetworkName = "signet" - // config.RPCHost = "localhost" - // config.RPCPort = "8332" - // config.RPCUser = "user" - // config.RPCPass = "password" - // config.WalletName = "walletname" - // config.Destination = "tb1qgm39cu009lyvq93afx47pp4h9wxq5x92lxxgnz" - // config.IndexerListenAddress = "tb1qsja4hvx66jr9grgmt8452letmz37gmludcrnup" - // config.EnableIndexer = false - // config.EnableCommitter = false - // return &config, nil - } - - v := viper.New() - v.SetConfigFile(configFile) - v.SetEnvPrefix("BITCOIN") - v.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_")) - v.AutomaticEnv() - - if err := v.ReadInConfig(); err != nil { - if !os.IsNotExist(err) { - return nil, err - } - // Load from environment variables if not found in the config file - err = v.BindEnv("network-name", "BITCOIN_NETWORK_NAME") - if err != nil { - return nil, err - } - err = v.BindEnv("rpc-host", "BITCOIN_RPC_HOST") - if err != nil { - return nil, err - } - err = v.BindEnv("rpc-port", "BITCOIN_RPC_PORT") - if err != nil { - return nil, err - } - err = v.BindEnv("rpc-user", "BITCOIN_RPC_USER") - if err != nil { - return nil, err - } - err = v.BindEnv("rpc-pass", "BITCOIN_RPC_PASS") - if err != nil { - return nil, err - } - err = v.BindEnv("wallet-name", "BITCOIN_WALLET_NAME") - if err != nil { - return nil, err - } - err = v.BindEnv("destination", "BITCOIN_DESTINATION") - if err != nil { - return nil, err - } - err = v.BindEnv("enable-indexer", "BITCOIN_ENABLE_INDEXER") - if err != nil { - return nil, err - } - err = v.BindEnv("enable-committer", "BITCOIN_ENABLE_COMMITTER") - if err != nil { - return nil, err - } - err = v.BindEnv("indexer-listen-address", "BITCOIN_INDEXER_LISTEN_ADDRESS") - if err != nil { - return nil, err - } - err = v.BindEnv("bridge.eth-rpc-url", "BITCOIN_BRIDGE_ETH_RPC_URL") - if err != nil { - return nil, err - } - err = v.BindEnv("bridge.eth-priv-key", "BITCOIN_BRIDGE_ETH_PRIV_KEY") - if err != nil { - return nil, err - } - err = v.BindEnv("bridge.contract-address", "BITCOIN_BRIDGE_CONTRACT_ADDRESS") - if err != nil { - return nil, err - } - err = v.BindEnv("bridge.abi", "BITCOIN_BRIDGE_ABI") - if err != nil { - return nil, err - } - err = v.BindEnv("bridge.gas-limit", "BITCOIN_BRIDGE_GAS_LIMIT") - if err != nil { - return nil, err - } - err = v.BindEnv("bridge.aa-sca-registry", "BITCOIN_BRIDGE_AA_SCA_REGISTRY") - if err != nil { - return nil, err - } - err = v.BindEnv("bridge.aa-kernel-factory", "BITCOIN_BRIDGE_AA_KERNEL_FACTORY") - if err != nil { - return nil, err - } - err = v.BindEnv("state.host", "BITCOIN_STATE_HOST") - if err != nil { - return nil, err - } - err = v.BindEnv("state.port", "BITCOIN_STATE_PORT") - if err != nil { - return nil, err - } - err = v.BindEnv("state.user", "BITCOIN_STATE_USER") - if err != nil { - return nil, err - } - err = v.BindEnv("state.pass", "BITCOIN_STATE_PASS") - if err != nil { - return nil, err - } - err = v.BindEnv("state.db-name", "BITCOIN_STATE_DB_NAME") - if err != nil { - return nil, err - } - err = v.BindEnv("fee", "BITCOIN_FEE") - if err != nil { - return nil, err - } - err = v.BindEnv("evm.enable-listener", "BITCOIN_EVM_ENABLE_LISTENER") - if err != nil { - return nil, err - } - err = v.BindEnv("evm.deposit", "BITCOIN_EVM_DEPOSIT") - if err != nil { - return nil, err - } - err = v.BindEnv("evm.withdraw", "BITCOIN_EVM_WITHDRAW") - if err != nil { - return nil, err - } - } - - err = v.Unmarshal(&config) - if err != nil { - return nil, err - } - - return &config, nil -} - -// ChainParams get chain params by network name -func ChainParams(network string) *chaincfg.Params { - switch network { - case chaincfg.MainNetParams.Name: - return &chaincfg.MainNetParams - case chaincfg.TestNet3Params.Name: - return &chaincfg.TestNet3Params - case chaincfg.SigNetParams.Name: - return &chaincfg.SigNetParams - case chaincfg.SimNetParams.Name: - return &chaincfg.SimNetParams - case chaincfg.RegressionNetParams.Name: - return &chaincfg.RegressionNetParams - default: - return &chaincfg.TestNet3Params - } -} diff --git a/bitcoin/config_test.go b/bitcoin/config_test.go deleted file mode 100644 index 84eb601c13..0000000000 --- a/bitcoin/config_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package bitcoin_test - -import ( - "os" - "testing" - - "github.com/btcsuite/btcd/chaincfg" - "github.com/evmos/ethermint/bitcoin" - "github.com/stretchr/testify/require" -) - -func TestConfig(t *testing.T) { - // clean BITCOIN env set - // This is because the value set by the environment variable affects viper reading file - os.Unsetenv("BITCOIN_NETWORK_NAME") - os.Unsetenv("BITCOIN_RPC_HOST") - os.Unsetenv("BITCOIN_RPC_PORT") - os.Unsetenv("BITCOIN_RPC_USER") - os.Unsetenv("BITCOIN_RPC_PASS") - os.Unsetenv("BITCOIN_WALLET_NAME") - os.Unsetenv("BITCOIN_DESTINATION") - os.Unsetenv("BITCOIN_ENABLE_INDEXER") - os.Unsetenv("BITCOIN_INDEXER_LISTEN_ADDRESS") - os.Unsetenv("BITCOIN_BRIDGE_ETH_RPC_URL") - os.Unsetenv("BITCOIN_BRIDGE_CONTRACT_ADDRESS") - os.Unsetenv("BITCOIN_BRIDGE_ETH_PRIV_KEY") - os.Unsetenv("BITCOIN_BRIDGE_ABI") - os.Unsetenv("BITCOIN_BRIDGE_GAS_LIMIT") - os.Unsetenv("BITCOIN_BRIDGE_AA_SCA_REGISTRY") - os.Unsetenv("BITCOIN_BRIDGE_AA_KERNEL_FACTORY") - config, err := bitcoin.LoadBitcoinConfig("./testdata") - require.NoError(t, err) - require.Equal(t, "signet", config.NetworkName) - require.Equal(t, "localhost", config.RPCHost) - require.Equal(t, "8332", config.RPCPort) - require.Equal(t, "b2node", config.RPCUser) - require.Equal(t, "b2node", config.RPCPass) - require.Equal(t, "b2node", config.WalletName) - require.Equal(t, "tb1qgm39cu009lyvq93afx47pp4h9wxq5x92lxxgnz", config.Destination) - require.Equal(t, true, config.EnableIndexer) - require.Equal(t, "tb1qfhhxljfajcppfhwa09uxwty5dz4xwfptnqmvtv", config.IndexerListenAddress) - require.Equal(t, "localhost:8545", config.Bridge.EthRPCURL) - require.Equal(t, "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DFF2", config.Bridge.ContractAddress) - require.Equal(t, "", config.Bridge.EthPrivKey) - require.Equal(t, "abi.json", config.Bridge.ABI) - require.Equal(t, uint64(3000), config.Bridge.GasLimit) - require.Equal(t, "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DFF3", config.Bridge.AASCARegistry) - require.Equal(t, "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DFF4", config.Bridge.AAKernelFactory) -} - -func TestConfigEnv(t *testing.T) { - os.Setenv("BITCOIN_NETWORK_NAME", "testnet") - os.Setenv("BITCOIN_RPC_HOST", "127.0.0.1") - os.Setenv("BITCOIN_RPC_PORT", "8888") - os.Setenv("BITCOIN_RPC_USER", "abc") - os.Setenv("BITCOIN_RPC_PASS", "abcd") - os.Setenv("BITCOIN_WALLET_NAME", "b2node") - os.Setenv("BITCOIN_DESTINATION", "tb1qfhhxljfajcppfhwa09uxwty5dz4xwfptnqmvtv") - os.Setenv("BITCOIN_ENABLE_INDEXER", "false") - os.Setenv("BITCOIN_INDEXER_LISTEN_ADDRESS", "tb1qgm39cu009lyvq93afx47pp4h9wxq5x92lxxgnz") - os.Setenv("BITCOIN_BRIDGE_ETH_RPC_URL", "127.0.0.1:8545") - os.Setenv("BITCOIN_BRIDGE_CONTRACT_ADDRESS", "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF22") - os.Setenv("BITCOIN_BRIDGE_ETH_PRIV_KEY", "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") - os.Setenv("BITCOIN_BRIDGE_ABI", "aaa.abi") - os.Setenv("BITCOIN_BRIDGE_GAS_LIMIT", "23333") - os.Setenv("BITCOIN_STATE_HOST", "localhost") - os.Setenv("BITCOIN_STATE_PORT", "5432") - os.Setenv("BITCOIN_STATE_USER", "user") - os.Setenv("BITCOIN_STATE_PASS", "password") - os.Setenv("BITCOIN_STATE_DB_NAME", "db") - os.Setenv("BITCOIN_ENABLE_COMMITTER", "false") - os.Setenv("BITCOIN_BRIDGE_AA_SCA_REGISTRY", "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF23") - os.Setenv("BITCOIN_BRIDGE_AA_KERNEL_FACTORY", "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF24") - os.Setenv("BITCOIN_EVM_ENABLE_LISTENER", "false") - os.Setenv("BITCOIN_EVM_DEPOSIT", "0x01bee1bfa4116bd0440a1108ef6cb6a2f6eb9b611d8f53260aec20d39e84ee88") - os.Setenv("BITCOIN_EVM_WITHDRAW", "0xda335c6ae73006d1145bdcf9a98bc76d789b653b13fe6200e6fc4c5dd54add85") - - config, err := bitcoin.LoadBitcoinConfig("./") - require.NoError(t, err) - require.Equal(t, "testnet", config.NetworkName) - require.Equal(t, "127.0.0.1", config.RPCHost) - require.Equal(t, "8888", config.RPCPort) - require.Equal(t, "abc", config.RPCUser) - require.Equal(t, "abcd", config.RPCPass) - require.Equal(t, "b2node", config.WalletName) - require.Equal(t, "tb1qfhhxljfajcppfhwa09uxwty5dz4xwfptnqmvtv", config.Destination) - require.Equal(t, false, config.EnableIndexer) - require.Equal(t, "tb1qgm39cu009lyvq93afx47pp4h9wxq5x92lxxgnz", config.IndexerListenAddress) - require.Equal(t, "127.0.0.1:8545", config.Bridge.EthRPCURL) - require.Equal(t, "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF22", config.Bridge.ContractAddress) - require.Equal(t, "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", config.Bridge.EthPrivKey) - require.Equal(t, "aaa.abi", config.Bridge.ABI) - require.Equal(t, uint64(23333), config.Bridge.GasLimit) - require.Equal(t, "localhost", config.StateConfig.Host) - require.Equal(t, 5432, config.StateConfig.Port) - require.Equal(t, "user", config.StateConfig.User) - require.Equal(t, "password", config.StateConfig.Pass) - require.Equal(t, "db", config.StateConfig.DBName) - require.Equal(t, "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF23", config.Bridge.AASCARegistry) - require.Equal(t, "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DF24", config.Bridge.AAKernelFactory) -} - -func TestChainParams(t *testing.T) { - testCases := []struct { - network string - params *chaincfg.Params - }{ - { - network: "mainnet", - params: &chaincfg.MainNetParams, - }, - { - network: "testnet", - params: &chaincfg.TestNet3Params, - }, - { - network: "signet", - params: &chaincfg.SigNetParams, - }, - { - network: "simnet", - params: &chaincfg.SimNetParams, - }, - { - network: "regtest", - params: &chaincfg.RegressionNetParams, - }, - { - network: "invalid", - params: &chaincfg.TestNet3Params, - }, - } - - for _, tc := range testCases { - t.Run(tc.network, func(t *testing.T) { - result := bitcoin.ChainParams(tc.network) - if result == nil || result != tc.params { - t.Errorf("ChainParams(%s) = %v, expected %v", tc.network, result, tc.params) - } - }) - } -} diff --git a/bitcoin/evm_listener_service.go b/bitcoin/evm_listener_service.go deleted file mode 100644 index 1b481a8516..0000000000 --- a/bitcoin/evm_listener_service.go +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2021 Evmos Foundation -// This file is part of Evmos' Ethermint library. -// -// The Ethermint library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The Ethermint library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the Ethermint library. If not, see https://github.com/evmos/ethermint/blob/main/LICENSE -package bitcoin - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "math/big" - "strconv" - "time" - - dbm "github.com/tendermint/tm-db" - - "github.com/btcsuite/btcd/chaincfg/chainhash" - - "github.com/btcsuite/btcd/txscript" - - "github.com/btcsuite/btcd/wire" - - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" - btcrpcclient "github.com/btcsuite/btcd/rpcclient" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/ethclient" - - "github.com/tendermint/tendermint/libs/service" -) - -const ( - ListenerServiceName = "EVMListenerService" - EVMListenerBlockKey = "EVMListenerBlock" // key: currentBlock -) - -// EVMListenerService indexes transactions for json-rpc service. -type EVMListenerService struct { - service.BaseService - - btcCli *btcrpcclient.Client - ethCli *ethclient.Client - config *BitconConfig - db dbm.DB -} - -// NewEVMListenerService returns a new service instance. -func NewEVMListenerService( - btcCli *btcrpcclient.Client, - ethCli *ethclient.Client, - config *BitconConfig, - db dbm.DB, -) *EVMListenerService { - is := &EVMListenerService{btcCli: btcCli, ethCli: ethCli, config: config, db: db} - is.BaseService = *service.NewBaseService(nil, ListenerServiceName, is) - return is -} - -// OnStart implements service.Service by subscribing for new blocks -// and indexing them by events. -func (eis *EVMListenerService) OnStart() error { - var lastBlock int64 - lastBlockByte, err := eis.db.Get([]byte(EVMListenerBlockKey)) - if err != nil { - eis.Logger.Error("EVMListenerService get block from db failed", "error", err) - return err - } - if string(lastBlockByte) == "" { - lastBlock = 0 - } else { - lastBlock, err = strconv.ParseInt(string(lastBlockByte), 10, 64) - if err != nil { - eis.Logger.Error("EVMListenerService get lastBlock failed", "error", err) - return err - } - } - addresses := []common.Address{ - common.HexToAddress(eis.config.Bridge.ContractAddress), - } - topics := [][]common.Hash{ - { - common.HexToHash(eis.config.Evm.Deposit), - common.HexToHash(eis.config.Evm.Withdraw), - }, - } - destAddresses := make([]string, 0, 10) - amounts := make([]int64, 0, 10) - for { - height, err := eis.ethCli.BlockNumber(context.Background()) - if err != nil { - eis.Logger.Error("EVMListenerService HeaderByNumber is failed:", "err", err) - time.Sleep(time.Second * 10) - continue - } - - latestBlock, err := strconv.ParseInt(fmt.Sprint(height), 10, 64) - if err != nil { - eis.Logger.Error("EVMListenerService ParseInt latestBlock", "err", err) - return err - } - eis.Logger.Info("EVMListenerService ethClient height", "height", latestBlock, "lastBlock", lastBlock, "dest", destAddresses, "amout", amounts) - if latestBlock <= lastBlock { - time.Sleep(time.Second * 10) - continue - } - - for i := lastBlock + 1; i <= latestBlock; i++ { - query := ethereum.FilterQuery{ - FromBlock: big.NewInt(i), - ToBlock: big.NewInt(i), - Topics: topics, - Addresses: addresses, - } - logs, err := eis.ethCli.FilterLogs(context.Background(), query) - if err != nil { - eis.Logger.Error("EVMListenerService failed to fetch block", "height", i, "err", err) - break - } - - for _, vlog := range logs { - eventHash := common.BytesToHash(vlog.Topics[0].Bytes()) - if eventHash == common.HexToHash(eis.config.Evm.Deposit) { - // todo - data := DepositEvent{ - Sender: TopicToAddress(vlog, 1), - ToAddress: TopicToAddress(vlog, 2), - Amount: DataToBigInt(vlog, 0), - } - value, err := json.Marshal(&data) - if err != nil { - eis.Logger.Error("EVMListenerService listener deposit Marshal failed: ", "err", err) - return err - } - eis.Logger.Info("EVMListenerService listener deposit event: ", "num", i, "deposit", string(value)) - } else if eventHash == common.HexToHash(eis.config.Evm.Withdraw) { - data := WithdrawEvent{ - FromAddress: TopicToAddress(vlog, 1), - ToAddress: DataToString(vlog, 0), - Amount: DataToBigInt(vlog, 1), - } - value, err := json.Marshal(&data) - if err != nil { - eis.Logger.Error("EVMListenerService listener withdraw Marshal failed: ", "err", err) - return err - } - eis.Logger.Info("EVMListenerService listener withdraw event: ", "num", i, "withdraw", string(value)) - - amount := DataToBigInt(vlog, 1) - destAddrStr := DataToString(vlog, 0) - destAddresses = append(destAddresses, destAddrStr) - amounts = append(amounts, amount.Int64()) - } - } - lastBlock = i - currentBlockStr := strconv.FormatInt(lastBlock, 10) - err = eis.db.Set([]byte(EVMListenerBlockKey), []byte(currentBlockStr)) - if err != nil { - eis.Logger.Error("EVMListenerService db set EVMListenerBlockKey failed: ", "err", err) - } - if len(destAddresses) > 0 { - isOK, err := eis.IsUnspentTX() - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc IsUnspentTX failed: ", "err", err) - continue - } - if !isOK { - continue - } - eis.Logger.Info("EVMListenerService btc transfer", "destAddr", destAddresses, "amount", amounts) - err = eis.TransferToBtc(destAddresses, amounts) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc failed: ", "err", err) - } else { - destAddresses = make([]string, 0, 10) - amounts = make([]int64, 0, 10) - } - } - } - } -} - -func (eis *EVMListenerService) TransferToBtc(destAddresses []string, amounts []int64) error { - sourceAddrStr := eis.config.IndexerListenAddress - - var defaultNet *chaincfg.Params - networkName := eis.config.NetworkName - defaultNet = ChainParams(networkName) - - // get sourceAddress UTXO - sourceAddr, err := btcutil.DecodeAddress(sourceAddrStr, defaultNet) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc DecodeAddress failed: ", "err", err) - return err - } - - unspentTxs, err := eis.btcCli.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{sourceAddr}) - if err != nil { - eis.Logger.Error("EVMListenerService ListUnspentMinMaxAddresses transferToBtc DecodeAddress failed: ", "err", err) - return err - } - - totalTransferAmount := btcutil.Amount(0) - tx := wire.NewMsgTx(wire.TxVersion) - - for index, destAddress := range destAddresses { - destAddr, err := btcutil.DecodeAddress(destAddress, defaultNet) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc DecodeAddress destAddress failed: ", "err", err) - return err - } - destinationScript, err := txscript.PayToAddrScript(destAddr) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc PayToAddrScript destAddress failed: ", "err", err) - return err - } - tx.AddTxOut(wire.NewTxOut(amounts[index], destinationScript)) - totalTransferAmount += btcutil.Amount(amounts[index]) - } - - totalInputAmount := btcutil.Amount(0) - for _, unspentTx := range unspentTxs { - inTxid, err := chainhash.NewHashFromStr(unspentTx.TxID) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc NewHashFromStr failed: ", "err", err) - return err - } - outpoint := wire.NewOutPoint(inTxid, unspentTx.Vout) - txIn := wire.NewTxIn(outpoint, nil, nil) - tx.AddTxIn(txIn) - totalInputAmount += btcutil.Amount(unspentTx.Amount * 1e8) - if int64(totalInputAmount) > (int64(totalTransferAmount) + eis.config.Fee) { - break - } - } - - changeAmount := int64(totalInputAmount) - eis.config.Fee - int64(totalTransferAmount) - if changeAmount < 0 { - return errors.New("insufficient balance") - } - changeScript, err := txscript.PayToAddrScript(sourceAddr) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc PayToAddrScript sourceAddr failed: ", "err", err) - return err - } - tx.AddTxOut(wire.NewTxOut(changeAmount, changeScript)) - - // sign - signedTx, complete, err := eis.btcCli.SignRawTransactionWithWallet(tx) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc SignRawTransactionWithWallet failed: ", "err", err) - return err - } - if !complete { - eis.Logger.Error("EVMListenerService transferToBtc SignRawTransactionWithWallet failed: ", "err", errors.New("SignRawTransaction not complete")) - return errors.New("SignRawTransaction not complete") - } - // send - txHash, err := eis.btcCli.SendRawTransaction(signedTx, true) - if err != nil { - eis.Logger.Error("EVMListenerService transferToBtc SendRawTransaction failed: ", "err", err) - return err - } - eis.Logger.Info("EVMListenerService tx success: ", "from", sourceAddrStr, "to", destAddresses, "amount", amounts, "hash", txHash.String()) - return nil -} - -func (eis *EVMListenerService) IsUnspentTX() (bool, error) { - sourceAddrStr := eis.config.IndexerListenAddress - var defaultNet *chaincfg.Params - networkName := eis.config.NetworkName - defaultNet = ChainParams(networkName) - - // get sourceAddress UTXO - sourceAddr, err := btcutil.DecodeAddress(sourceAddrStr, defaultNet) - if err != nil { - eis.Logger.Error("EVMListenerService IsUnspentTX DecodeAddress failed: ", "err", err) - return false, err - } - unspentTxs, err := eis.btcCli.ListUnspentMinMaxAddresses(1, 9999999, []btcutil.Address{sourceAddr}) - if err != nil { - eis.Logger.Error("EVMListenerService ListUnspentMinMaxAddresses transferToBtc DecodeAddress failed: ", "err", err) - return false, err - } - if len(unspentTxs) == 0 { - return false, nil - } - return true, nil -} diff --git a/bitcoin/evm_listener_service_test.go b/bitcoin/evm_listener_service_test.go deleted file mode 100644 index 13cedcb1e2..0000000000 --- a/bitcoin/evm_listener_service_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package bitcoin_test - -import ( - "errors" - "log" - "testing" - - dbm "github.com/tendermint/tm-db" - - "github.com/btcsuite/btcd/rpcclient" - "github.com/evmos/ethermint/bitcoin" - "github.com/stretchr/testify/require" -) - -func TestNewEVMListenerService(t *testing.T) { - listenerService := evmListenerWithConfig(t) - require.NotNil(t, listenerService) -} - -func TestIsUnspentTX(t *testing.T) { - listenerService := evmListenerWithConfig(t) - - testCase := []struct { - name string - value bool - }{ - { - name: "NoUnspentTX", - value: false, - }, - } - - for _, tc := range testCase { - t.Run(tc.name, func(t *testing.T) { - isOK, _ := listenerService.IsUnspentTX() - require.Equal(t, tc.value, isOK) - }) - } -} - -func TestTransferToBtc(t *testing.T) { - listenerService := evmListenerWithConfig(t) - - testCase := []struct { - name string - addresses []string - amounts []int64 - err error - }{ - { - name: "fail", - addresses: []string{"tb1qgm39cu009lyvq93afx47pp4h9wxq5x92lxxgnz"}, - amounts: []int64{10000}, - err: errors.New("the client has been shutdown"), - }, - } - - for _, tc := range testCase { - t.Run(tc.name, func(t *testing.T) { - err := listenerService.TransferToBtc(tc.addresses, tc.amounts) - if err != nil { - require.Error(t, tc.err, err) - } - }) - } -} - -func evmListenerWithConfig(t *testing.T) *bitcoin.EVMListenerService { - bitcoinCfg, err := bitcoin.LoadBitcoinConfig("./testdata") - require.NoError(t, err) - - // start btc rpc client - btclient, err := rpcclient.New(&rpcclient.ConnConfig{ - Host: bitcoinCfg.RPCHost + ":" + bitcoinCfg.RPCPort, - User: bitcoinCfg.RPCUser, - Pass: bitcoinCfg.RPCPass, - HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode - DisableTLS: true, // Bitcoin core does not provide TLS by default - }, nil) - if err != nil { - log.Fatalf("EVMListenerService failed to create bitcoin client: %v", err) - } - - var db dbm.DB - listenerService := bitcoin.NewEVMListenerService(btclient, nil, bitcoinCfg, db) - return listenerService -} diff --git a/bitcoin/import_descriptors_cmds.go b/bitcoin/import_descriptors_cmds.go deleted file mode 100644 index f2c6006f9b..0000000000 --- a/bitcoin/import_descriptors_cmds.go +++ /dev/null @@ -1,77 +0,0 @@ -package bitcoin - -import ( - "encoding/json" - - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/rpcclient" -) - -// Descriptor @see https://developer.bitcoin.org/reference/rpc/importdescriptors.html -type Descriptor struct { - Desc string `json:"desc"` - Active *bool `json:"active,omitempty"` - Range interface{} `json:"range,omitempty"` - NextIndex *int `json:"next_index,omitempty"` - Timestamp interface{} `json:"timestamp"` - Internal *bool `json:"internal,omitempty"` - Label *string `json:"label,omitempty"` -} - -// ImportDescriptorsCmd @see https://developer.bitcoin.org/reference/rpc/importdescriptors.html -type ImportDescriptorsCmd struct { - Descriptors []Descriptor `json:""` -} - -// NewImportDescriptorsCmd creates a new instance of the importdescriptors command. -func NewImportDescriptorsCmd(descriptors []Descriptor) *ImportDescriptorsCmd { - return &ImportDescriptorsCmd{ - Descriptors: descriptors, - } -} - -// ImportDescriptorsResult @see ImportDescriptorsResult -type ImportDescriptorsResultElement struct { - Success bool `json:"success"` - Warnings []string `json:"warnings,omitempty"` - Error *btcjson.RPCError `json:"error,omitempty"` -} - -type ImportDescriptorsResult []ImportDescriptorsResultElement - -type FutureImportDescriptorsResult chan *rpcclient.Response - -// Receive waits for the response promised by the future and returns the result of the importdescriptors command. -func (r FutureImportDescriptorsResult) Receive() (*ImportDescriptorsResult, error) { - res, err := rpcclient.ReceiveFuture(r) - if err != nil { - return nil, err - } - - var importDescriptors ImportDescriptorsResult - err = json.Unmarshal(res, &importDescriptors) - if err != nil { - return nil, err - } - - return &importDescriptors, nil -} - -// ImportDescriptorsAsync @see ImportDescriptorsAsync -func ImportDescriptorsAsync(c *rpcclient.Client, descriptors []Descriptor) FutureImportDescriptorsResult { - cmd := &ImportDescriptorsCmd{ - Descriptors: descriptors, - } - return c.SendCmd(cmd) -} - -// ImportDescriptors @see https://developer.bitcoin.org/reference/rpc/importdescriptors.html -func ImportDescriptors(c *rpcclient.Client, descriptors []Descriptor) (*ImportDescriptorsResult, error) { - return ImportDescriptorsAsync(c, descriptors).Receive() -} - -// register -func init() { - flags := btcjson.UsageFlag(0) - btcjson.MustRegisterCmd("importdescriptors", (*ImportDescriptorsCmd)(nil), flags) -} diff --git a/bitcoin/indexer.go b/bitcoin/indexer.go deleted file mode 100644 index b0c44aae08..0000000000 --- a/bitcoin/indexer.go +++ /dev/null @@ -1,181 +0,0 @@ -package bitcoin - -import ( - "errors" - "fmt" - - "github.com/btcsuite/btcd/btcjson" - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - "github.com/evmos/ethermint/types" - "github.com/tendermint/tendermint/libs/log" -) - -var ( - ErrParsePkScript = errors.New("parse pkscript err") - ErrDecodeListenAddress = errors.New("decode listen address err") -) - -const ( - // tx type - TxTypeTransfer = "transfer" // btc transfer -) - -// Indexer bitcoin indexer, parse and forward data -type Indexer struct { - client *rpcclient.Client // call bitcoin rpc client - chainParams *chaincfg.Params // bitcoin network params, e.g. mainnet, testnet, etc. - listenAddress btcutil.Address // need listened bitcoin address - - logger log.Logger -} - -// NewBitcoinIndexer new bitcoin indexer -func NewBitcoinIndexer( - log log.Logger, - client *rpcclient.Client, - chainParams *chaincfg.Params, - listenAddress string, -) (*Indexer, error) { - // check listenAddress - address, err := btcutil.DecodeAddress(listenAddress, chainParams) - if err != nil { - return nil, fmt.Errorf("%w:%s", ErrDecodeListenAddress, err.Error()) - } - return &Indexer{ - logger: log, - client: client, - chainParams: chainParams, - listenAddress: address, - }, nil -} - -// ParseBlock parse block data by block height -// NOTE: Currently, only transfer transactions are supported. -func (b *Indexer) ParseBlock(height int64, txIndex int64) ([]*types.BitcoinTxParseResult, error) { - blockResult, err := b.getBlockByHeight(height) - if err != nil { - return nil, err - } - - blockParsedResult := make([]*types.BitcoinTxParseResult, 0) - for k, v := range blockResult.Transactions { - if int64(k) < txIndex { - continue - } - - b.logger.Debug("parse block", "k", k, "height", height, "txIndex", txIndex, "tx", v.TxHash().String()) - - parseTxs, err := b.parseTx(v, k) - if err != nil { - return nil, err - } - - blockParsedResult = append(blockParsedResult, parseTxs...) - } - - return blockParsedResult, nil -} - -// getBlockByHeight returns a raw block from the server given its height -func (b *Indexer) getBlockByHeight(height int64) (*wire.MsgBlock, error) { - blockhash, err := b.client.GetBlockHash(height) - if err != nil { - return nil, err - } - return b.client.GetBlock(blockhash) -} - -// parseTx parse transaction data -func (b *Indexer) parseTx(txResult *wire.MsgTx, index int) (parsedResult []*types.BitcoinTxParseResult, err error) { - for _, v := range txResult.TxOut { - pkAddress, err := b.parseAddress(v.PkScript) - if err != nil { - if errors.Is(err, ErrParsePkScript) { - continue - } - return nil, err - } - - // if pk address eq dest listened address, after parse from address by vin prev tx - if pkAddress == b.listenAddress.EncodeAddress() { - fromAddress, err := b.parseFromAddress(txResult) - if err != nil { - return nil, fmt.Errorf("vin parse err:%w", err) - } - parsedResult = append(parsedResult, &types.BitcoinTxParseResult{ - TxId: txResult.TxHash().String(), - TxType: TxTypeTransfer, - Index: int64(index), - Value: v.Value, - From: fromAddress, - To: pkAddress, - }) - } - } - - return -} - -// parseFromAddress from vin parse from address -// return all possible values parsed from address -// TODO: at present, it is assumed that it is a single from, and multiple from needs to be tested later -func (b *Indexer) parseFromAddress(txResult *wire.MsgTx) (fromAddress []string, err error) { - for _, vin := range txResult.TxIn { - // get prev tx hash - prevTxID := vin.PreviousOutPoint.Hash - vinResult, err := b.client.GetRawTransaction(&prevTxID) - if err != nil { - return nil, fmt.Errorf("vin get raw transaction err:%w", err) - } - if len(vinResult.MsgTx().TxOut) == 0 { - return nil, fmt.Errorf("vin txOut is null") - } - vinPKScript := vinResult.MsgTx().TxOut[vin.PreviousOutPoint.Index].PkScript - // script to address - vinPkAddress, err := b.parseAddress(vinPKScript) - if err != nil { - b.logger.Error("vin parse address", "error", err) - if errors.Is(err, ErrParsePkScript) { - continue - } - return nil, err - } - - fromAddress = append(fromAddress, vinPkAddress) - } - return -} - -// parseAddress from pkscript parse address -func (b *Indexer) ParseAddress(pkScript []byte) (string, error) { - return b.parseAddress(pkScript) -} - -// parseAddress from pkscript parse address -func (b *Indexer) parseAddress(pkScript []byte) (string, error) { - pk, err := txscript.ParsePkScript(pkScript) - if err != nil { - return "", fmt.Errorf("%w:%s", ErrParsePkScript, err.Error()) - } - - // encodes the script into an address for the given chain. - pkAddress, err := pk.Address(b.chainParams) - if err != nil { - return "", fmt.Errorf("PKScript to address err:%w", err) - } - return pkAddress.EncodeAddress(), nil -} - -// LatestBlock get latest block height in the longest block chain. -func (b *Indexer) LatestBlock() (int64, error) { - return b.client.GetBlockCount() -} - -// BlockChainInfo get block chain info -func (b *Indexer) BlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) { - return b.client.GetBlockChainInfo() -} diff --git a/bitcoin/indexer_service.go b/bitcoin/indexer_service.go deleted file mode 100644 index f93c251531..0000000000 --- a/bitcoin/indexer_service.go +++ /dev/null @@ -1,160 +0,0 @@ -package bitcoin - -import ( - "strconv" - "strings" - "time" - - "github.com/evmos/ethermint/types" - "github.com/tendermint/tendermint/libs/service" - dbm "github.com/tendermint/tm-db" -) - -const ( - ServiceName = "BitcoinIndexerService" - - BitcoinIndexBlockKey = "bitcoinIndexBlock" // key: currentBlock + "."+ currentTxIndex - - NewBlockWaitTimeout = 60 * time.Second -) - -// IndexerService indexes transactions for json-rpc service. -type IndexerService struct { - service.BaseService - - txIdxr types.BITCOINTxIndexer - bridge types.BITCOINBridge - - db dbm.DB -} - -// NewIndexerService returns a new service instance. -func NewIndexerService( - txIdxr types.BITCOINTxIndexer, - bridge types.BITCOINBridge, - db dbm.DB, -) *IndexerService { - is := &IndexerService{txIdxr: txIdxr, bridge: bridge, db: db} - is.BaseService = *service.NewBaseService(nil, ServiceName, is) - return is -} - -// OnStart -func (bis *IndexerService) OnStart() error { - latestBlock, err := bis.txIdxr.LatestBlock() - if err != nil { - bis.Logger.Error("bitcoin indexer latestBlock", "error", err.Error()) - return err - } - - var ( - currentBlock int64 // index current block number - currentTxIndex int64 // index current block tx index - ) - // btcIndexBlock - btcIndexBlockMax, err := bis.db.Get([]byte(BitcoinIndexBlockKey)) - if err != nil { - bis.Logger.Error("failed to get bitcoin index block from db", "error", err) - return err - } - - bis.Logger.Info("bitcoin indexer load db", "data", string(btcIndexBlockMax)) - - // set default value - currentBlock = latestBlock - currentTxIndex = 0 - - if btcIndexBlockMax != nil { - indexBlock := strings.Split(string(btcIndexBlockMax), ".") - bis.Logger.Info("bitcoin indexer db data split", "indexBlock", indexBlock) - if len(indexBlock) > 1 { - currentBlock, err = strconv.ParseInt(indexBlock[0], 10, 64) - if err != nil { - bis.Logger.Error("failed to parse block", "error", err) - return err - } - currentTxIndex, err = strconv.ParseInt(indexBlock[1], 10, 64) - if err != nil { - bis.Logger.Error("failed to parse tx index", "error", err) - return err - } - } - } - bis.Logger.Info("bitcoin indexer init data", "latestBlock", latestBlock, - "currentBlock", currentBlock, "db data", string(btcIndexBlockMax), "currentTxIndex", currentTxIndex) - - ticker := time.NewTicker(NewBlockWaitTimeout) - for { - bis.Logger.Info("bitcoin indexer", "latestBlock", - latestBlock, "currentBlock", currentBlock, "currentTxIndex", currentTxIndex) - - if latestBlock <= currentBlock { - <-ticker.C - ticker.Reset(NewBlockWaitTimeout) - - // update latest block - latestBlock, err = bis.txIdxr.LatestBlock() - if err != nil { - bis.Logger.Error("bitcoin indexer latestBlock", "error", err.Error()) - } - continue - } - - // index > 0, start index from currentBlock currentTxIndex + 1 - // index == 0, start index from currentBlock + 1 - if currentTxIndex == 0 { - currentBlock++ - } else { - currentTxIndex++ - } - - for i := currentBlock; i <= latestBlock; i++ { - txResults, err := bis.txIdxr.ParseBlock(i, currentTxIndex) - if err != nil { - bis.Logger.Error("bitcoin indexer parseblock", "error", err.Error(), "currentBlock", i, "currentTxIndex", currentTxIndex) - continue - } - - if len(txResults) > 0 { - for _, v := range txResults { - // if from is listen address, skip - if v.From[0] == v.To { - bis.Logger.Info("bitcoin indexer current transaction from is listen address", "currentBlock", i, "currentTxIndex", v.Index, "data", v) - continue - } - var transferResult string - depositResult, err := bis.bridge.Deposit(v.TxId, v.From[0], v.Value) - if err != nil { - bis.Logger.Error("bitcoin indexer invoke deposit unknown err try again by transfer", "error", err.Error(), - "currentBlock", i, "currentTxIndex", v.Index, "data", v) - // try transfer - transferResult, err = bis.bridge.Transfer(v.From[0], v.Value) - if err != nil { - bis.Logger.Error("bitcoin indexer invoke transfer unknown err", "error", err.Error(), - "currentBlock", i, "currentTxIndex", v.Index, "data", v) - } - } - currentBlockStr := strconv.FormatInt(i, 10) - currentTxIndexStr := strconv.FormatInt(v.Index, 10) - err = bis.db.Set([]byte(BitcoinIndexBlockKey), []byte(currentBlockStr+"."+currentTxIndexStr)) - if err != nil { - bis.Logger.Error("failed to set bitcoin index block", "error", err) - } - bis.Logger.Info("bitcoin indexer invoke deposit bridge", "deposit data", v, "depositResult", depositResult, "transferResult", transferResult) - } - } - - currentBlock = i - currentTxIndex = 0 - - currentBlockStr := strconv.FormatInt(currentBlock, 10) - currentTxIndexStr := strconv.FormatInt(currentTxIndex, 10) - err = bis.db.Set([]byte(BitcoinIndexBlockKey), []byte(currentBlockStr+"."+currentTxIndexStr)) - if err != nil { - bis.Logger.Error("failed to set bitcoin index block", "error", err) - } - bis.Logger.Info("bitcoin indexer parsed", "txResult", txResults, "currentBlock", i, - "currentTxIndex", currentTxIndex, "latestBlock", latestBlock) - } - } -} diff --git a/bitcoin/indexer_test.go b/bitcoin/indexer_test.go deleted file mode 100644 index 6a94ada33e..0000000000 --- a/bitcoin/indexer_test.go +++ /dev/null @@ -1,229 +0,0 @@ -package bitcoin_test - -import ( - "testing" - - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/rpcclient" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/evmos/ethermint/bitcoin" - "github.com/evmos/ethermint/types" - "github.com/stretchr/testify/require" - tmlog "github.com/tendermint/tendermint/libs/log" -) - -func TestNewBitcoinIndexer(t *testing.T) { - testCases := []struct { - name string - listendAddress string - errMsg string - }{ - { - "success", - "tb1qukxc3sy3s3k5n5z9cxt3xyywgcjmp2tzudlz2n", - "", - }, - { - "success: segwit", - "3HctoF43JZCjAQrad1MqGtn5EsF57f5CCN", - "", - }, - { - "success: legacy", - "1CpnsCEQ3Q4d15rLkrANnfd9GtYNHJRsYb", - "", - }, - { - "success: segwit(bech32)", - "bc1qj2hkaplmmka9lqjj4p23t2z2lrd4vv8fjqa36g", - "", - }, - { - "fail: format fail", - "tb1qukxc3sy3s3k5n5z9cxt3xyywgcjmp2tzudlz2n1", - "decode listen address err:decoded address is of unknown format", - }, - { - "fail: address null", - "", - "decode listen address err:decoded address is of unknown format", - }, - { - "fail: check sum", - "1CpnsCEQ3Q4d15rLkrANnfd9GtYNHJRsYy", - "decode listen address err:checksum mismatch", - }, - } - - for _, tc := range testCases { - _, err := bitcoin.NewBitcoinIndexer( - tmlog.NewNopLogger(), - mockRpcClient(t), - &chaincfg.MainNetParams, // chainParams Do not affect the address - tc.listendAddress) - if err != nil { - require.EqualError(t, err, tc.errMsg) - } - } -} - -func TestParseAddress(t *testing.T) { - testCases := []struct { - name string - pkScriptHex string - parsedAddress string - pkAddress string - chainParams *chaincfg.Params - errMsg string - }{ - { - "success", - "0x51207099e4b23427fc40ba4777bbf52cfd0b7444d69a3e21ef281270723f54c0c14b", - "tb1pwzv7fv35yl7ypwj8w7al2t8apd6yf4568cs772qjwper74xqc99sk8x7tk", - "tb1pwzv7fv35yl7ypwj8w7al2t8apd6yf4568cs772qjwper74xqc99sk8x7tk", - &chaincfg.SigNetParams, - "", - }, - { - "success: main net", - "0x5120916e7f2636a8754793a5257198d9bef0d6afbea8d09cc2a36b5901869d6b0ad5", - "bc1pj9h87f3k4p650ya9y4ce3kd77rt2l04g6zwv9gmttyqcd8ttpt2sva77pe", - "bc1pj9h87f3k4p650ya9y4ce3kd77rt2l04g6zwv9gmttyqcd8ttpt2sva77pe", - &chaincfg.MainNetParams, - "", - }, - { - "success: sim net", - "0x5120916e7f2636a8754793a5257198d9bef0d6afbea8d09cc2a36b5901869d6b0ad5", - "sb1pj9h87f3k4p650ya9y4ce3kd77rt2l04g6zwv9gmttyqcd8ttpt2suyzkzn", - "sb1pj9h87f3k4p650ya9y4ce3kd77rt2l04g6zwv9gmttyqcd8ttpt2suyzkzn", - &chaincfg.SimNetParams, - "", - }, - { - "fail: unsupported script type", - "0x51207099e4b23427fc40ba4777bbf52cfd0b7444d69a3e21ef281270723f54c0c1", - "1CpnsCEQ3Q4d15rLkrANnfd9GtYNHJRsYb", - "tb1pwzv7fv35yl7ypwj8w7al2t8apd6yf4568cs772qjwper74xqc99sk8x7tk", - &chaincfg.SigNetParams, - "parse pkscript err:unsupported script type", - }, - { - "fail: empty pk", - "0x", - "1CpnsCEQ3Q4d15rLkrANnfd9GtYNHJRsYb", - "tb1pwzv7fv35yl7ypwj8w7al2t8apd6yf4568cs772qjwper74xqc99sk8x7tk", - &chaincfg.SigNetParams, - "parse pkscript err:unsupported script type", - }, - } - - for _, tc := range testCases { - pkScript, err := hexutil.Decode(tc.pkScriptHex) - require.NoError(t, err) - tmpAddress, err := mockBitcoinIndexer(t, tc.chainParams).ParseAddress(pkScript) - if err != nil { - require.EqualError(t, err, tc.errMsg) - continue - } - if tmpAddress != tc.parsedAddress && tmpAddress != tc.pkAddress { - t.Errorf("test:%s expected %s, got %s", tc.name, tc.parsedAddress, tmpAddress) - } - } -} - -// TestLocalParseTx only test in local -// data source: testnet network -func TestLocalParseTx(t *testing.T) { - indexer := bitcoinIndexerWithConfig(t) - testCases := []struct { - name string - height int64 - dest []*types.BitcoinTxParseResult - }{ - { - name: "success", - height: 2540186, - dest: []*types.BitcoinTxParseResult{ - { - TxId: "317ce1cc2f987c95d19ba13044c6298953d91c82274a2c34d7ac92a8df3dab0f", - TxType: bitcoin.TxTypeTransfer, - Index: 350, - From: []string{"tb1qravmtnqvtpnmugeg7q90ck69lzznflu4w9amnw"}, - To: "tb1qjda2l5spwyv4ekwe9keddymzuxynea2m2kj0qy", - Value: 2306, - }, - }, - }, - { - name: "success empty", - height: 2540180, - dest: []*types.BitcoinTxParseResult{}, - }, - } - - for _, tc := range testCases { - results, err := indexer.ParseBlock(tc.height, 0) - require.NoError(t, err) - require.Equal(t, results, tc.dest) - } -} - -// TestLocalLatestBlock only test in local -func TestLocalLatestBlock(t *testing.T) { - indexer := bitcoinIndexerWithConfig(t) - _, err := indexer.LatestBlock() - require.NoError(t, err) -} - -// TestLocalBlockChainInfo only test in local -func TestLocalBlockChainInfo(t *testing.T) { - indexer := bitcoinIndexerWithConfig(t) - _, err := indexer.BlockChainInfo() - require.NoError(t, err) -} - -func mockRpcClient(t *testing.T) *rpcclient.Client { - connCfg := &rpcclient.ConnConfig{ - Host: "127.0.0.1:38332", - User: "user", - Pass: "password", - HTTPPostMode: true, - DisableTLS: true, - } - client, err := rpcclient.New(connCfg, nil) - require.NoError(t, err) - return client -} - -func mockBitcoinIndexer(t *testing.T, chainParams *chaincfg.Params) *bitcoin.Indexer { - indexer, err := bitcoin.NewBitcoinIndexer( - tmlog.NewNopLogger(), - mockRpcClient(t), - chainParams, - "tb1qukxc3sy3s3k5n5z9cxt3xyywgcjmp2tzudlz2n") - require.NoError(t, err) - return indexer -} - -func bitcoinIndexerWithConfig(t *testing.T) *bitcoin.Indexer { - config, err := bitcoin.LoadBitcoinConfig("./testdata") - require.NoError(t, err) - connCfg := &rpcclient.ConnConfig{ - Host: config.RPCHost + ":" + config.RPCPort, - User: config.RPCUser, - Pass: config.RPCPass, - HTTPPostMode: true, - DisableTLS: true, - } - client, err := rpcclient.New(connCfg, nil) - require.NoError(t, err) - bitcoinParam := bitcoin.ChainParams(config.NetworkName) - indexer, err := bitcoin.NewBitcoinIndexer( - tmlog.NewNopLogger(), - client, - bitcoinParam, - config.IndexerListenAddress) - require.NoError(t, err) - return indexer -} diff --git a/bitcoin/state.go b/bitcoin/state.go deleted file mode 100644 index 2b196bba18..0000000000 --- a/bitcoin/state.go +++ /dev/null @@ -1,63 +0,0 @@ -package bitcoin - -import ( - "context" - "database/sql" - "fmt" - "time" -) - -func openDB(cfg StateConfig) (*sql.DB, error) { - dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", - cfg.Host, cfg.Port, cfg.User, cfg.Pass, cfg.DBName) - db, err := sql.Open("postgres", dsn) - if err != nil { - return nil, err - } - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - err = db.PingContext(ctx) - if err != nil { - return nil, err - } - return db, nil -} - -type VerifiedBatch struct { - BatchNum int64 - TxHash string - Aggregator string - StateRoot string - BlockNum int64 - IsTrusted bool -} - -func GetStateRoot(cfg StateConfig, index int64) ([]*VerifiedBatch, error) { - db, err := openDB(cfg) - if err != nil { - return nil, fmt.Errorf("openDB err:%w", err) - } - userSQL := "select state_root, max(block_num) block_num from state.verified_batch where block_num > $1 and " + - " is_trusted=true group by state_root order by block_num desc" - rows, err := db.Query(userSQL, index) - if err != nil { - return nil, fmt.Errorf("vin parse err:%w", err) - } - var batchs []*VerifiedBatch - - for rows.Next() { - var stateRoot string - var blockNum int64 - err = rows.Scan(&stateRoot, &blockNum) - if err != nil { - return nil, fmt.Errorf("vin parse err:%w", err) - } - batch := &VerifiedBatch{ - StateRoot: stateRoot, - BlockNum: blockNum, - } - batchs = append(batchs, batch) - } - return batchs, nil -} diff --git a/bitcoin/state_test.go b/bitcoin/state_test.go deleted file mode 100644 index 718bf92ee3..0000000000 --- a/bitcoin/state_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package bitcoin_test - -import ( - "testing" - - "github.com/evmos/ethermint/bitcoin" - _ "github.com/lib/pq" - "github.com/stretchr/testify/require" -) - -func TestLocalGetStateRoot(t *testing.T) { - cfg := bitcoin.StateConfig{ - Host: "localhost", - Port: 5432, - User: "state_user", - Pass: "state_password", - DBName: "state_db", - } - items, err := bitcoin.GetStateRoot(cfg, 1) - require.NoError(t, err) - for _, item := range items { - require.Equal(t, int64(1299), item.BlockNum) - require.Equal(t, "0x1cc9e812fdad14a03f6e3c8563393d0e0c155dbd1d54361f41b33da46b087294", item.StateRoot) - } -} diff --git a/bitcoin/testdata/abi.json b/bitcoin/testdata/abi.json deleted file mode 100644 index dcda47bba9..0000000000 --- a/bitcoin/testdata/abi.json +++ /dev/null @@ -1,378 +0,0 @@ -[ - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "caller", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to_address", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "DepositEvent", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } - ], - "name": "Initialized", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from_address", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "btc_address", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrawEvent", - "type": "event" - }, - { - "inputs": [], - "name": "ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "b2_to_address", - "type": "address" - }, - { - "internalType": "uint256", - "name": "btc_amount", - "type": "uint256" - } - ], - "name": "deposit", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "deposit_uuid", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "b2_to_address", - "type": "address" - }, - { - "internalType": "uint256", - "name": "btc_amount", - "type": "uint256" - } - ], - "name": "depositV2", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "btc_address", - "type": "string" - } - ], - "name": "withdraw", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "withdraw_uuid", - "type": "bytes32" - }, - { - "internalType": "string", - "name": "btc_address", - "type": "string" - } - ], - "name": "withdrawV2", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - } -] \ No newline at end of file diff --git a/bitcoin/testdata/bitcoin.toml b/bitcoin/testdata/bitcoin.toml deleted file mode 100644 index 5646460b2a..0000000000 --- a/bitcoin/testdata/bitcoin.toml +++ /dev/null @@ -1,31 +0,0 @@ -network-name = "signet" -rpc-host = "localhost" -rpc-port = 8332 -rpc-user = "b2node" -rpc-pass = "b2node" -wallet-name = "b2node" -destination = "tb1qgm39cu009lyvq93afx47pp4h9wxq5x92lxxgnz" -enable-indexer = true -indexer-listen-address = "tb1qfhhxljfajcppfhwa09uxwty5dz4xwfptnqmvtv" -fee = 200000 - -[bridge] -eth-rpc-url = "localhost:8545" -eth-priv-key = "" -contract-address = "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DFF2" -abi = "abi.json" -gas-limit = 3000 -aa-sca-registry = "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DFF3" -aa-kernel-factory = "0xB457BF68D71a17Fa5030269Fb895e29e6cD2DFF4" - -[evm] -enable-listener = true -deposit = "0x01bee1bfa4116bd0440a1108ef6cb6a2f6eb9b611d8f53260aec20d39e84ee88" -withdraw = "0xda335c6ae73006d1145bdcf9a98bc76d789b653b13fe6200e6fc4c5dd54add85" - -[state] -host = "localhost" -port = 5432 -user = "state_user" -pass = "state_password" -db-name = "state_db" diff --git a/bitcoin/utils.go b/bitcoin/utils.go deleted file mode 100644 index bbf9d89d6c..0000000000 --- a/bitcoin/utils.go +++ /dev/null @@ -1,40 +0,0 @@ -package bitcoin - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - ethtypes "github.com/ethereum/go-ethereum/core/types" -) - -type WithdrawEvent struct { - FromAddress common.Address - ToAddress string - Amount *big.Int -} - -type DepositEvent struct { - Sender common.Address - ToAddress common.Address - Amount *big.Int -} - -func TopicToHash(vLog ethtypes.Log, index int64) common.Hash { - return common.BytesToHash(vLog.Topics[index].Bytes()) -} - -func TopicToAddress(vLog ethtypes.Log, index int64) common.Address { - return common.BytesToAddress(vLog.Topics[index].Bytes()) -} - -func DataToBigInt(vLog ethtypes.Log, index int64) *big.Int { - start := 32 * index - return big.NewInt(0).SetBytes(vLog.Data[start : start+32]) -} - -func DataToString(vLog ethtypes.Log, index int64) string { - start := 32 * index - offset := big.NewInt(0).SetBytes(vLog.Data[start : start+32]).Int64() - length := big.NewInt(0).SetBytes(vLog.Data[offset : offset+32]).Int64() - return string(vLog.Data[offset+32 : offset+32+length]) -} diff --git a/go.mod b/go.mod index aaac1a2afe..e4369119fe 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,7 @@ require ( cosmossdk.io/errors v1.0.0-beta.7 cosmossdk.io/math v1.0.0-rc.0 github.com/armon/go-metrics v0.4.1 - github.com/b2network/b2-go-aa-utils v1.0.2 github.com/btcsuite/btcd v0.23.4 - github.com/btcsuite/btcd/btcec/v2 v2.3.2 github.com/btcsuite/btcd/btcutil v1.1.2 github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 github.com/cosmos/cosmos-proto v1.0.0-beta.3 @@ -61,11 +59,11 @@ require ( github.com/StackExchange/wmi v1.2.1 // indirect github.com/VictoriaMetrics/fastcache v1.6.0 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect - github.com/aead/siphash v1.0.1 // indirect github.com/aws/aws-sdk-go v1.44.122 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect @@ -96,9 +94,7 @@ require ( github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect github.com/felixge/httpsnoop v1.0.1 // indirect - github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect github.com/go-kit/kit v0.12.0 // indirect github.com/go-kit/log v0.2.1 // indirect @@ -141,9 +137,7 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect - github.com/kevinburke/go-bindata/v4 v4.0.2 // indirect github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect - github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 // indirect github.com/klauspost/compress v1.15.11 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -196,7 +190,6 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 // indirect golang.org/x/crypto v0.18.0 // indirect golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 // indirect - golang.org/x/mod v0.14.0 // indirect golang.org/x/oauth2 v0.15.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.16.0 // indirect diff --git a/go.sum b/go.sum index 460a7c12a9..3b43ea799b 100644 --- a/go.sum +++ b/go.sum @@ -229,7 +229,6 @@ github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSa github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= -github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= @@ -266,8 +265,6 @@ github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7 github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= -github.com/b2network/b2-go-aa-utils v1.0.2 h1:y4wJAAiFvfbsn+fS6dRV1YBHpDB4KxX4dYf4VjYP2Vc= -github.com/b2network/b2-go-aa-utils v1.0.2/go.mod h1:OL1kBzuRXu9yBocRszQc+xkNyIUM8b1UIilm+R3nVwY= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -482,8 +479,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e h1:bBLctRc7kr01YGvaDfgLbTwjFNW5jdp5y5rj8XXBHfY= -github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= @@ -495,8 +490,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 h1:IZqZOB2fydHte3kUgxrzK5E1fW7RQGeDwE8F/ZZnUYc= -github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= @@ -826,13 +819,10 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= -github.com/kevinburke/go-bindata/v4 v4.0.2 h1:6qQI0nNTL27wM1En8zQHGBEPp3ETzgFU6hVdSjlkrfE= -github.com/kevinburke/go-bindata/v4 v4.0.2/go.mod h1:M/CkBqw2qCZ1Ztv5JyKgocGYWyUkYlDqkqXS1ktLe5c= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= @@ -1279,8 +1269,6 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1326,9 +1314,7 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1395,8 +1381,6 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1440,8 +1424,6 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= -golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1555,16 +1537,12 @@ golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1651,8 +1629,6 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= -golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/proto/ethermint/types/v1/bitcoin_indexer.proto b/proto/ethermint/types/v1/bitcoin_indexer.proto deleted file mode 100644 index 257514b94b..0000000000 --- a/proto/ethermint/types/v1/bitcoin_indexer.proto +++ /dev/null @@ -1,30 +0,0 @@ -syntax = "proto3"; -package ethermint.types.v1; - -import "gogoproto/gogo.proto"; - -option go_package = "github.com/evmos/ethermint/types"; - -// BitcoinTxParseResult is the value parsed bitcoin transaction -// NOTE: This struct may be extended in the future -message BitcoinTxParseResult { - option (gogoproto.goproto_getters) = false; - - // from is l2 user address, by parse bitcoin get the address - repeated string from = 1; - - // to is listening address - string to = 2; - - // value is from transfer amount - int64 value = 3; - - // tx_id is the btc transaction id - string tx_id = 4; - - // tx_type is the type of the transaction, eg. "brc20_transfer","transfer" - string tx_type = 5; - - // index is the index of the transaction in the block - int64 index = 6; -} diff --git a/server/config/toml.go b/server/config/toml.go index 36ee6b40c2..a61f110dc7 100644 --- a/server/config/toml.go +++ b/server/config/toml.go @@ -106,6 +106,4 @@ certificate-path = "{{ .TLS.CertificatePath }}" # Key path defines the key.pem file path for the TLS configuration. key-path = "{{ .TLS.KeyPath }}" - - ` diff --git a/server/start.go b/server/start.go index 8d01ca6e00..74a81d4815 100644 --- a/server/start.go +++ b/server/start.go @@ -22,14 +22,10 @@ import ( "net" "net/http" "os" - "path" "path/filepath" "runtime/pprof" "time" - "github.com/ethereum/go-ethereum/ethclient" - - "github.com/btcsuite/btcd/rpcclient" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/telemetry" @@ -65,7 +61,6 @@ import ( "github.com/cosmos/cosmos-sdk/server/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/evmos/ethermint/bitcoin" "github.com/evmos/ethermint/indexer" ethdebug "github.com/evmos/ethermint/rpc/namespaces/ethereum/debug" "github.com/evmos/ethermint/server/config" @@ -645,176 +640,6 @@ func startInProcess(ctx *server.Context, clientCtx client.Context, opts StartOpt case <-time.After(types.ServerStartTime): // assume server started successfully } } - - // TODO: bitcoin services logic - // bitcoin indexer run go routine handle bitcoin transaction - // or bitcoin commiter logic - bitcoinCfg, err := bitcoin.LoadBitcoinConfig(path.Join(home, "config")) - if err != nil { - logger.Error("failed to load bitcoin config", "error", err.Error()) - return err - } - - if bitcoinCfg.EnableIndexer { - bclient, err := rpcclient.New(&rpcclient.ConnConfig{ - Host: bitcoinCfg.RPCHost + ":" + bitcoinCfg.RPCPort, - User: bitcoinCfg.RPCUser, - Pass: bitcoinCfg.RPCPass, - HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode - DisableTLS: true, // Bitcoin core does not provide TLS by default - }, nil) - if err != nil { - logger.Error("failed to create bitcoin client", "error", err.Error()) - return err - } - defer func() { - bclient.Shutdown() - }() - bitcoinParam := bitcoin.ChainParams(bitcoinCfg.NetworkName) - - bidxLogger := ctx.Logger.With("indexer", "bitcoin") - bidxer, err := bitcoin.NewBitcoinIndexer(bidxLogger, bclient, bitcoinParam, bitcoinCfg.IndexerListenAddress) - if err != nil { - logger.Error("failed to new bitcoin indexer indexer", "error", err.Error()) - return err - } - // check bitcoin core status, whether the request succeed - _, err = bidxer.BlockChainInfo() - if err != nil { - logger.Error("failed to get bitcoin core status", "error", err.Error()) - return err - } - - bridge, err := bitcoin.NewBridge(bitcoinCfg.Bridge, path.Join(home, "config")) - if err != nil { - logger.Error("failed to create bitcoin bridge", "error", err.Error()) - return err - } - - bitcoinidxDB, err := OpenBitcoinIndexerDB(home, server.GetAppDBBackend(ctx.Viper)) - if err != nil { - logger.Error("failed to open bitcoin indexer DB", "error", err.Error()) - return err - } - - bindexerService := bitcoin.NewIndexerService(bidxer, bridge, bitcoinidxDB) - bindexerService.SetLogger(bidxLogger) - - errCh := make(chan error) - go func() { - if err := bindexerService.Start(); err != nil { - errCh <- err - } - }() - - select { - case err := <-errCh: - return err - case <-time.After(types.ServerStartTime): // assume server started successfully - } - } - - if bitcoinCfg.EnableCommitter { - bclient, err := rpcclient.New(&rpcclient.ConnConfig{ - Host: bitcoinCfg.RPCHost + ":" + bitcoinCfg.RPCPort + "/wallet/" + bitcoinCfg.WalletName, - User: bitcoinCfg.RPCUser, - Pass: bitcoinCfg.RPCPass, - HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode - DisableTLS: true, // Bitcoin core does not provide TLS by default - }, nil) - if err != nil { - logger.Error("failed to create bitcoin client", "error", err.Error()) - return err - } - defer func() { - bclient.Shutdown() - }() - bidxLogger := ctx.Logger.With("committer", "bitcoin") - committer, err := bitcoin.NewCommitter(bclient, bitcoinCfg.NetworkName, bitcoinCfg.Destination, bitcoinCfg.StateConfig) - if err != nil { - logger.Error("failed to new bitcoin committer", "error", err.Error()) - return err - } - // check bitcoin core status, whether the request succeed - _, err = committer.BlockChainInfo() - if err != nil { - logger.Error("failed to get bitcoin core status", "error", err.Error()) - return err - } - - citDB, err := OpenCommitterDB(home, server.GetAppDBBackend(ctx.Viper)) - if err != nil { - logger.Error("failed to open evm indexer DB", "error", err.Error()) - return err - } - - committerService := bitcoin.NewCommitterService(committer, citDB) - committerService.SetLogger(bidxLogger) - - errCh := make(chan error) - go func() { - if err := committerService.Start(); err != nil { - errCh <- err - } - }() - - select { - case err := <-errCh: - return err - case <-time.After(types.ServerStartTime): // assume server started successfully - } - } - - if bitcoinCfg.Evm.EnableListener { - // start btc rpc client - btclient, err := rpcclient.New(&rpcclient.ConnConfig{ - Host: bitcoinCfg.RPCHost + ":" + bitcoinCfg.RPCPort + "/wallet/" + bitcoinCfg.WalletName, - User: bitcoinCfg.RPCUser, - Pass: bitcoinCfg.RPCPass, - HTTPPostMode: true, // Bitcoin core only supports HTTP POST mode - DisableTLS: true, // Bitcoin core does not provide TLS by default - }, nil) - if err != nil { - logger.Error("EVMListenerService failed to create bitcoin client", "error", err.Error()) - return err - } - defer func() { - btclient.Shutdown() - }() - - // start eth rpc client - ethlient, err := ethclient.Dial(bitcoinCfg.Bridge.EthRPCURL) - if err != nil { - logger.Error("EVMListenerService failed to create eth client", "error", err.Error()) - return err - } - defer func() { - ethlient.Close() - }() - - evmListenerDB, err := OpenEVMListenerServiceDB(home, server.GetAppDBBackend(ctx.Viper)) - if err != nil { - logger.Error("EVMListenerService failed to open DB", "error", err.Error()) - return err - } - listenerService := bitcoin.NewEVMListenerService(btclient, ethlient, bitcoinCfg, evmListenerDB) - listenerLogger := ctx.Logger.With("EVMListener", "evm") - listenerService.SetLogger(listenerLogger) - - errCh := make(chan error) - go func() { - if err := listenerService.Start(); err != nil { - errCh <- err - } - }() - - select { - case err := <-errCh: - return err - case <-time.After(types.ServerStartTime): // assume server started successfully - } - } - // Wait for SIGINT or SIGTERM signal return server.WaitForQuitSignals() } @@ -830,16 +655,6 @@ func OpenIndexerDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) return dbm.NewDB("evmindexer", backendType, dataDir) } -func OpenCommitterDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) { - dataDir := filepath.Join(rootDir, "data") - return dbm.NewDB("committer", backendType, dataDir) -} - -func OpenBitcoinIndexerDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) { - dataDir := filepath.Join(rootDir, "data") - return dbm.NewDB("bitoinindexer", backendType, dataDir) -} - func openTraceWriter(traceWriterFile string) (w io.Writer, err error) { if traceWriterFile == "" { return @@ -859,8 +674,3 @@ func startTelemetry(cfg config.Config) (*telemetry.Metrics, error) { } return telemetry.New(cfg.Telemetry) } - -func OpenEVMListenerServiceDB(rootDir string, backendType dbm.BackendType) (dbm.DB, error) { - dataDir := filepath.Join(rootDir, "data") - return dbm.NewDB("evmlistenerservice", backendType, dataDir) -} diff --git a/types/bitcoin_bridge.go b/types/bitcoin_bridge.go deleted file mode 100644 index 197a35bb9f..0000000000 --- a/types/bitcoin_bridge.go +++ /dev/null @@ -1,9 +0,0 @@ -package types - -// BITCOINBridge defines the interface of custom bitcoin bridge. -type BITCOINBridge interface { - // Deposit transfers amout to address - Deposit(string, string, int64) (string, error) - // Transfer amount to address - Transfer(string, int64) (string, error) -} diff --git a/types/bitcoin_indexer.go b/types/bitcoin_indexer.go deleted file mode 100644 index 2d08504bc1..0000000000 --- a/types/bitcoin_indexer.go +++ /dev/null @@ -1,9 +0,0 @@ -package types - -// BITCOINTxIndexer defines the interface of custom bitcoin tx indexer. -type BITCOINTxIndexer interface { - // ParseBlock parse bitcoin block tx - ParseBlock(int64, int64) ([]*BitcoinTxParseResult, error) - // LatestBlock get latest block height in the longest block chain. - LatestBlock() (int64, error) -} diff --git a/types/bitcoin_indexer.pb.go b/types/bitcoin_indexer.pb.go deleted file mode 100644 index 4e16568fbf..0000000000 --- a/types/bitcoin_indexer.pb.go +++ /dev/null @@ -1,517 +0,0 @@ -// Code generated by protoc-gen-gogo. DO NOT EDIT. -// source: ethermint/types/v1/bitcoin_indexer.proto - -package types - -import ( - fmt "fmt" - _ "github.com/cosmos/gogoproto/gogoproto" - proto "github.com/gogo/protobuf/proto" - io "io" - math "math" - math_bits "math/bits" -) - -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package - -// BitcoinTxParseResult is the value parsed bitcoin transaction -// NOTE: This struct may be extended in the future -type BitcoinTxParseResult struct { - // from is l2 user address, by parse bitcoin get the address - From []string `protobuf:"bytes,1,rep,name=from,proto3" json:"from,omitempty"` - // to is listening address - To string `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"` - // value is from transfer amount - Value int64 `protobuf:"varint,3,opt,name=value,proto3" json:"value,omitempty"` - // tx_id is the btc transaction id - TxId string `protobuf:"bytes,4,opt,name=tx_id,json=txId,proto3" json:"tx_id,omitempty"` - // tx_type is the type of the transaction, eg. "brc20_transfer","transfer" - TxType string `protobuf:"bytes,5,opt,name=tx_type,json=txType,proto3" json:"tx_type,omitempty"` - // index is the index of the transaction in the block - Index int64 `protobuf:"varint,6,opt,name=index,proto3" json:"index,omitempty"` -} - -func (m *BitcoinTxParseResult) Reset() { *m = BitcoinTxParseResult{} } -func (m *BitcoinTxParseResult) String() string { return proto.CompactTextString(m) } -func (*BitcoinTxParseResult) ProtoMessage() {} -func (*BitcoinTxParseResult) Descriptor() ([]byte, []int) { - return fileDescriptor_a28da31cd1817aa6, []int{0} -} -func (m *BitcoinTxParseResult) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *BitcoinTxParseResult) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_BitcoinTxParseResult.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *BitcoinTxParseResult) XXX_Merge(src proto.Message) { - xxx_messageInfo_BitcoinTxParseResult.Merge(m, src) -} -func (m *BitcoinTxParseResult) XXX_Size() int { - return m.Size() -} -func (m *BitcoinTxParseResult) XXX_DiscardUnknown() { - xxx_messageInfo_BitcoinTxParseResult.DiscardUnknown(m) -} - -var xxx_messageInfo_BitcoinTxParseResult proto.InternalMessageInfo - -func init() { - proto.RegisterType((*BitcoinTxParseResult)(nil), "ethermint.types.v1.BitcoinTxParseResult") -} - -func init() { - proto.RegisterFile("ethermint/types/v1/bitcoin_indexer.proto", fileDescriptor_a28da31cd1817aa6) -} - -var fileDescriptor_a28da31cd1817aa6 = []byte{ - // 266 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x90, 0x3f, 0x4f, 0xc3, 0x30, - 0x10, 0xc5, 0xe3, 0xfc, 0x43, 0xf5, 0xc0, 0x60, 0x22, 0x61, 0x31, 0x98, 0x88, 0x29, 0x53, 0xac, - 0x8a, 0xad, 0x63, 0x37, 0x36, 0x14, 0x75, 0x62, 0x89, 0x9a, 0xc6, 0xa4, 0x96, 0x9a, 0x38, 0x72, - 0x2e, 0x91, 0xfb, 0x0d, 0x18, 0x99, 0x99, 0xf8, 0x38, 0x8c, 0x1d, 0x19, 0x51, 0xf2, 0x45, 0x50, - 0x1c, 0x89, 0x81, 0xed, 0xbd, 0xbb, 0x9f, 0x9e, 0xde, 0x1d, 0x4e, 0x04, 0x1c, 0x85, 0xae, 0x65, - 0x03, 0x1c, 0xce, 0xad, 0xe8, 0xf8, 0xb0, 0xe6, 0x85, 0x84, 0x83, 0x92, 0x4d, 0x2e, 0x9b, 0x52, - 0x18, 0xa1, 0xd3, 0x56, 0x2b, 0x50, 0x84, 0xfc, 0x91, 0xa9, 0x25, 0xd3, 0x61, 0x7d, 0x17, 0x55, - 0xaa, 0x52, 0x76, 0xcd, 0x67, 0xb5, 0x90, 0x0f, 0x1f, 0x08, 0x47, 0xdb, 0x25, 0x63, 0x67, 0x9e, - 0xf7, 0xba, 0x13, 0x99, 0xe8, 0xfa, 0x13, 0x10, 0x82, 0xfd, 0x57, 0xad, 0x6a, 0x8a, 0x62, 0x2f, - 0x59, 0x65, 0x56, 0x93, 0x6b, 0xec, 0x82, 0xa2, 0x6e, 0x8c, 0x92, 0x55, 0xe6, 0x82, 0x22, 0x11, - 0x0e, 0x86, 0xfd, 0xa9, 0x17, 0xd4, 0x8b, 0x51, 0xe2, 0x65, 0x8b, 0x21, 0x37, 0x38, 0x00, 0x93, - 0xcb, 0x92, 0xfa, 0x16, 0xf4, 0xc1, 0x3c, 0x95, 0xe4, 0x16, 0x5f, 0x81, 0xc9, 0xe7, 0x32, 0x34, - 0xb0, 0xe3, 0x10, 0xcc, 0xee, 0xdc, 0x8a, 0x39, 0xc3, 0x76, 0xa7, 0xe1, 0x92, 0x61, 0xcd, 0xc6, - 0x7f, 0xfb, 0xbc, 0x77, 0xb6, 0x9b, 0xaf, 0x91, 0xa1, 0xcb, 0xc8, 0xd0, 0xcf, 0xc8, 0xd0, 0xfb, - 0xc4, 0x9c, 0xcb, 0xc4, 0x9c, 0xef, 0x89, 0x39, 0x2f, 0x71, 0x25, 0xe1, 0xd8, 0x17, 0xe9, 0x41, - 0xd5, 0x5c, 0x0c, 0xb5, 0xea, 0xf8, 0xbf, 0xdf, 0x14, 0xa1, 0xbd, 0xef, 0xf1, 0x37, 0x00, 0x00, - 0xff, 0xff, 0x74, 0x78, 0x7e, 0x0c, 0x35, 0x01, 0x00, 0x00, -} - -func (m *BitcoinTxParseResult) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *BitcoinTxParseResult) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *BitcoinTxParseResult) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if m.Index != 0 { - i = encodeVarintBitcoinIndexer(dAtA, i, uint64(m.Index)) - i-- - dAtA[i] = 0x30 - } - if len(m.TxType) > 0 { - i -= len(m.TxType) - copy(dAtA[i:], m.TxType) - i = encodeVarintBitcoinIndexer(dAtA, i, uint64(len(m.TxType))) - i-- - dAtA[i] = 0x2a - } - if len(m.TxId) > 0 { - i -= len(m.TxId) - copy(dAtA[i:], m.TxId) - i = encodeVarintBitcoinIndexer(dAtA, i, uint64(len(m.TxId))) - i-- - dAtA[i] = 0x22 - } - if m.Value != 0 { - i = encodeVarintBitcoinIndexer(dAtA, i, uint64(m.Value)) - i-- - dAtA[i] = 0x18 - } - if len(m.To) > 0 { - i -= len(m.To) - copy(dAtA[i:], m.To) - i = encodeVarintBitcoinIndexer(dAtA, i, uint64(len(m.To))) - i-- - dAtA[i] = 0x12 - } - if len(m.From) > 0 { - for iNdEx := len(m.From) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.From[iNdEx]) - copy(dAtA[i:], m.From[iNdEx]) - i = encodeVarintBitcoinIndexer(dAtA, i, uint64(len(m.From[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func encodeVarintBitcoinIndexer(dAtA []byte, offset int, v uint64) int { - offset -= sovBitcoinIndexer(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *BitcoinTxParseResult) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.From) > 0 { - for _, s := range m.From { - l = len(s) - n += 1 + l + sovBitcoinIndexer(uint64(l)) - } - } - l = len(m.To) - if l > 0 { - n += 1 + l + sovBitcoinIndexer(uint64(l)) - } - if m.Value != 0 { - n += 1 + sovBitcoinIndexer(uint64(m.Value)) - } - l = len(m.TxId) - if l > 0 { - n += 1 + l + sovBitcoinIndexer(uint64(l)) - } - l = len(m.TxType) - if l > 0 { - n += 1 + l + sovBitcoinIndexer(uint64(l)) - } - if m.Index != 0 { - n += 1 + sovBitcoinIndexer(uint64(m.Index)) - } - return n -} - -func sovBitcoinIndexer(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 -} -func sozBitcoinIndexer(x uint64) (n int) { - return sovBitcoinIndexer(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *BitcoinTxParseResult) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: BitcoinTxParseResult: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: BitcoinTxParseResult: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field From", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthBitcoinIndexer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthBitcoinIndexer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.From = append(m.From, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field To", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthBitcoinIndexer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthBitcoinIndexer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.To = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 3: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType) - } - m.Value = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Value |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 4: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TxId", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthBitcoinIndexer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthBitcoinIndexer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.TxId = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field TxType", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthBitcoinIndexer - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthBitcoinIndexer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.TxType = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 6: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Index", wireType) - } - m.Index = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Index |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } - default: - iNdEx = preIndex - skippy, err := skipBitcoinIndexer(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthBitcoinIndexer - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipBitcoinIndexer(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowBitcoinIndexer - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthBitcoinIndexer - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupBitcoinIndexer - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthBitcoinIndexer - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthBitcoinIndexer = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowBitcoinIndexer = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupBitcoinIndexer = fmt.Errorf("proto: unexpected end of group") -)