From ecf2c8d5bf21063df92fd729f2c28ec3bd7074c8 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 25 Jun 2024 16:34:32 +0700 Subject: [PATCH 001/113] BB-104 Update base multisig code and test creating wallet --- utils/multisig/constants.go | 10 ++ utils/multisig/multisig_test.go | 166 +++++++++++++++++++++++ utils/multisig/structure.go | 33 +++++ utils/multisig/tx.go | 226 ++++++++++++++++++++++++++++++++ utils/multisig/utils.go | 66 ++++++++++ utils/multisig/wallet.go | 171 ++++++++++++++++++++++++ 6 files changed, 672 insertions(+) create mode 100644 utils/multisig/constants.go create mode 100644 utils/multisig/multisig_test.go create mode 100644 utils/multisig/structure.go create mode 100644 utils/multisig/tx.go create mode 100644 utils/multisig/utils.go create mode 100644 utils/multisig/wallet.go diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go new file mode 100644 index 00000000..35384f0e --- /dev/null +++ b/utils/multisig/constants.go @@ -0,0 +1,10 @@ +package multisig + +const MIN_SAT = 546 + +const TEST_ACCOUNT_0_PRIVATE_KEY = "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy" +const TEST_ACCOUNT_0_PUBLIC_KEY = "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2" +const TEST_ACCOUNT_1_PRIVATE_KEY = "cRfK7N7cPZ1BZi6MpsNBuz7k3LiMMA7jreHMx3KUBjRV4KAQT9ou" +const TEST_ACCOUNT_1_PUBLIC_KEY = "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052" +const TEST_ACCOUNT_2_PRIVATE_KEY = "cU8TYnj3fp9t6hVcAz1rNm2GNLoLL2PFHpiCbkXmBCN6F1GZccxf" +const TEST_ACCOUNT_2_PUBLIC_KEY = "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833" diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go new file mode 100644 index 00000000..7392d198 --- /dev/null +++ b/utils/multisig/multisig_test.go @@ -0,0 +1,166 @@ +package multisig + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "fmt" + "math/big" + "testing" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" +) + +func TestGenerateKeys(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + + for i := 0; i < 3; i++ { + privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) + wif, _ := btcutil.NewWIF(privKey, chainParam, true) + pubKey := wif.SerializePubKey(); + witnessProg := btcutil.Hash160(pubKey) + p2wpkh, _ := btcutil.NewAddressWitnessPubKeyHash(witnessProg, chainParam) + + fmt.Printf("Account %v:\n Private Key: %v\n Public Key: %v\n Address: %v\n", i, wif.String(), hex.EncodeToString(pubKey), p2wpkh) + } +} + +func TestLoadWalletFromPrivateKey(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + + wif, _ := btcutil.DecodeWIF("cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy") + pubKey := wif.SerializePubKey(); + witnessProg := btcutil.Hash160(pubKey) + p2wpkh, _ := btcutil.NewAddressWitnessPubKeyHash(witnessProg, chainParam) + + fmt.Printf("Account:\n Private Key: %v\n Public Key: %v\n Address: %v\n", string(wif.String()), hex.EncodeToString(pubKey), p2wpkh) +} + +func TestRandomKeys(t *testing.T) { + randomKeys(3, &chaincfg.RegressionNetParams) +} + +func TestBuildMultisigTapScript(t *testing.T) { + // 2/3: bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz + // 3/3: bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h + totalSigs := 3 + numSigsRequired := 2 + chainParam := &chaincfg.RegressionNetParams + // 3 for multisig vault, 1 for recovery key + _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam) + + fmt.Printf("Len pub key: %v\n", len(pubKeys[0])) + + multisigInfo := &MultisigInfo{ + PubKeys: pubKeys, + EcPubKeys: ECPubKeys, + NumberRequiredSigs: numSigsRequired, + } + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + multisigAddress, err := AddressOnChain(chainParam, multisigWallet) + fmt.Println("address, err : ", multisigAddress, err) +} + +func TestCreateTx(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + + inputs := []*UTXO{ + // 2/3 - empty data + // { + // WalletAddress: "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz", + // TxHash: "1a532a1bd32b6be1140a3e1de414aa4d0d7a215066d62e8a27b96810a80de9ea", + // OutputIdx: 0, + // OutputAmount: 100000, + // }, + // 2/3 - empty data + { + WalletAddress: "bcrt1ptkwstjj0fm24qfm4whkamzxlnp902fpqk2w0ust0usfu9fcmsccs9zvh5n", + TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + OutputIdx: 0, + OutputAmount: 10000, + }, + // 3/3 + // { + // WalletAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", + // TxHash: "18166fe8fe7ca9a9ea5632021d1173860af5ad2c332424a6d1f7d835c37ff347", + // OutputIdx: 0, + // OutputAmount: 100000, + // }, + + // // 2/3 + // { + // WalletAddress: "bcrt1pmq64qc50jnn89s9e2cqn03y83rvqx75r2c2nx0fqqfp8w9jrfktsfkdyjs", + // TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", + // OutputIdx: 0, + // OutputAmount: 10000, + // }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", + Amount: 8000, + }, + } + + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" + msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + fmt.Println("msgTx: ", msgTx) + fmt.Println("prevOuts: ", prevOuts) + fmt.Println("err: ", err) + + // validators sign tx + totalSigs := [][][]byte{} // index private key -> index input -> sig + for _, privKey := range privKeys { + sigs, _, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, prevOuts, multisigWallet, chainParam) + if err != nil { + fmt.Println("err sign: ", err) + } + + totalSigs = append(totalSigs, sigs) + } + + signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} + +func TestGenSharedInternalPubKey(t *testing.T) { + + b := make([]byte, 32) + rand.Read(b) + bHex := hex.EncodeToString(b) + fmt.Printf("bHex: %v\n", bHex) + sharedRandom := new(big.Int).SetBytes(b) + genSharedInternalPubKey(sharedRandom) +} + +func TestParseTx(t *testing.T) { + // hexSignedTx := "02000000000104f6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0000000000ffffffffd9a54f6610fbc9b56cea421230b79edf5c48d92052c13c166656591f2d9ed1fd0000000000ffffffff7b02c2d6a2c8d14d3a1c717f4093306a2c485b4a0cff672ed26715555dff1fde0000000000fffffffff6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0100000000ffffffff05f82a000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd3c3d0900000000002251203cb3f6132189f271733e94476de372e022ea84dc2cb914c7ff691c453ddce563bcb1000000000000160014a355d136171b816b2b2f08d531cf94555d796751e803000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cda22d020000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd01401bdbfd310cbd31807024070825fc5a3fec6e7b37eb1d359dd3027727e5719c52e68b178f438d18c9218b13e3d95b8e3bd8efe1b422778fb88a59a8e5d4a7ba1601418f67cd9c4799e32ac9aed36c14a60e0a2442c4497cddb176ae118a9aeec099f0eaa68901681b0d6df6cdf45c062b70b73171d002d2c50345ea3c53bc51b6e8198301410315713b00ab6f47392e947e90aa4c67c37b77f9c76d1c5cb80a0df5f725dde2b883177dda0abe8dcbc7e06453c2720fa0eefea78e4b905a333929ee03e065bf830140430cc6f8e554c98930c7e67e9512bdc3c73a6944a60a58033607a9b195c857d0426ef570fb6640b07234ef33402a2ce22c66199ec57cbda27ce6028d3258f53100000000" + + hexSignedTx := "01000000000101bcbbb24bd5953d424debb9a24c8009298771eecd3ac0d3c4b219d906a319dfa80000000000e803000002e803000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d53401f000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d530540f4085e4f85eb81b8bd6afd77f728ea75716108cb29cd02aa031def6be65e97e98db40430554669d7b64476d76fd9ae6646529b7abfeee1ac4ad67de0bce9608040f3fc057a9ad0e4a0132040826e2c8e3ca0678ebd515146b8825f527f31195e1966d8424cdf9e963b7335178cab820534e1bd4ede4e8addf47c1bc449a764cec400962c7b22626173655661756c7441646472657373223a22222c22726563656976657241646472657373223a22227d7520fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2ac2030edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052ba201e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833ba529c21c0636e6671d0135074f83177c5e456191043de9bd54744423b88d6b1ab4751650f00000000" + msgTx, err := ParseTx(hexSignedTx) + if err != nil { + fmt.Printf("Err parse tx: %v", err) + return + } + + for _, txIn := range msgTx.TxIn { + fmt.Printf("txIn: %+v\n ", txIn) + } + + for _, txOut := range msgTx.TxOut { + fmt.Printf("txOut: %+v\n ", txOut) + } +} diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go new file mode 100644 index 00000000..b3a90407 --- /dev/null +++ b/utils/multisig/structure.go @@ -0,0 +1,33 @@ +package multisig + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/txscript" +) + +type MultisigInfo struct { + PubKeys [][]byte + EcPubKeys []*btcutil.AddressPubKey + NumberRequiredSigs int +} + +type MultisigWallet struct { + TapScriptTree *txscript.IndexedTapScriptTree + TapLeaves []txscript.TapLeaf + + PKScript []byte + SharedPublicKey *btcec.PublicKey +} + +type OutputTx struct { + ReceiverAddress string + Amount uint64 +} + +type UTXO struct { + WalletAddress string `bson:"wallet_address" json:"walletAddress"` + TxHash string `bson:"tx_hash" json:"txHash"` + OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` + OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` +} diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go new file mode 100644 index 00000000..c9029b56 --- /dev/null +++ b/utils/multisig/tx.go @@ -0,0 +1,226 @@ +package multisig + +import ( + "bytes" + "encoding/hex" + "errors" + "fmt" + "strings" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +// create unsigned multisig transaction +// input: UTXO, output, tx fee, chain config, change receiver +// output: unsigned tx message, previous output fetcher +func CreateMultisigTx( + inputs []*UTXO, + outputs []*OutputTx, + feePerOutput uint64, + chainParam *chaincfg.Params, + changeReceiverAddress string, + sourcePKScript []byte, +) (*wire.MsgTx, *txscript.MultiPrevOutFetcher, error) { + msgTx := wire.NewMsgTx(wire.TxVersion) + + // add TxIns into raw tx + // totalInputAmount in external unit + totalInputAmount := uint64(0) + prevOuts := txscript.NewMultiPrevOutFetcher(nil) + for _, in := range inputs { + utxoHash, err := chainhash.NewHashFromStr(in.TxHash) + if err != nil { + return nil, nil, err + } + outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + txIn := wire.NewTxIn(outPoint, nil, nil) + txIn.Sequence = uint32(feePerOutput) + msgTx.AddTxIn(txIn) + totalInputAmount += in.OutputAmount + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: sourcePKScript, + }) + } + + // add TxOuts into raw tx + // totalOutputAmount in external unit + totalOutputAmount := uint64(0) + for _, out := range outputs { + // adding the output to tx + decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) + if err != nil { + return nil, nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + } + destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) + if err != nil { + return nil, nil, err + } + + // adding the destination address and the amount to the transaction + if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { + return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + } + redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) + + msgTx.AddTxOut(redeemTxOut) + totalOutputAmount += out.Amount + } + + // check amount of input coins and output coins + if totalInputAmount < totalOutputAmount { + return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + } + + // calculate the change output + changeAmt := uint64(0) + if totalInputAmount > totalOutputAmount { + // adding the output to tx + decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) + if err != nil { + return nil, nil, err + } + destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) + if err != nil { + return nil, nil, err + } + + // adding the destination address and the amount to the transaction + changeAmt = totalInputAmount - totalOutputAmount + if changeAmt >= MIN_SAT { + redeemTxOut := wire.NewTxOut(int64(changeAmt), destinationAddrByte) + msgTx.AddTxOut(redeemTxOut) + } else { + changeAmt = 0 + } + } + + var rawTxBytes bytes.Buffer + err := msgTx.Serialize(&rawTxBytes) + if err != nil { + return nil, nil, err + } + + return msgTx, prevOuts, nil +} + +func PartSignOnRawExternalTx( + privKey string, + msgTx *wire.MsgTx, + inputs []*UTXO, + prevOuts *txscript.MultiPrevOutFetcher, + multisigWallet *MultisigWallet, + chainParam *chaincfg.Params, +) ([][]byte, string, error) { + wif, err := btcutil.DecodeWIF(privKey) + if err != nil { + return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) + } + + // sign on each TxIn + if len(inputs) != len(msgTx.TxIn) { + return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) + } + sigs := [][]byte{} + + txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + + for i := range msgTx.TxIn { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[0], txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } + fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) + + sigs = append(sigs, sig) + } + + return sigs, msgTx.TxHash().String(), nil +} + +// combine all the signatures to create the signed tx +// input: unsigned tx message, signatures, multisig struct +// output: signed tx message, tx hash +func CombineMultisigSigs( + multisigInfo *MultisigInfo, + multisigWallet *MultisigWallet, + msgTx *wire.MsgTx, + totalSigs [][][]byte, +) (*wire.MsgTx, error) { + // combine multisigs and finalize tx + numSig := uint(0) + sigs := make([][][]byte, len(msgTx.TxIn)) + for i := range sigs { + sigs[i] = [][]byte{} + } + + for _, sigsFromOneSigner := range totalSigs { + if numSig == uint(multisigInfo.NumberRequiredSigs) { + for indexInput := range sigsFromOneSigner { + if indexInput >= len(sigs) { + return nil, errors.New("invalid length of sigs") + } + sigs[indexInput] = append(sigs[indexInput], []byte{}) + } + } else { + for indexInput, sig := range sigsFromOneSigner { + if indexInput >= len(sigs) { + return nil, errors.New("invalid length of sigs") + } + + sigs[indexInput] = append(sigs[indexInput], sig) + } + numSig++ + } + } + + for idxInput, v := range sigs { + ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) + ctrlBlockBytes, err := ctrlBlock.ToBytes() + if err != nil { + return nil, fmt.Errorf("error including control block: %v", err) + } + + reverseV := [][]byte{} + for i := len(v) - 1; i >= 0; i-- { + reverseV = append(reverseV, v[i]) + } + witness := append([][]byte{}, reverseV...) + witness = append(witness, multisigWallet.TapLeaves[0].Script) + witness = append(witness, ctrlBlockBytes) + + witnessHexStr := []string{} + for _, w := range witness { + witnessHexStr = append(witnessHexStr, hex.EncodeToString(w)) + fmt.Printf("w idxInput %v - %v\n", idxInput, witnessHexStr) + + } + + fmt.Printf("Len witness %v: %v \n", idxInput, len(v)+len(multisigWallet.TapLeaves[0].Script)+len(ctrlBlockBytes)) + + msgTx.TxIn[idxInput].Witness = witness + } + + return msgTx, nil +} + +func ParseTx(data string) (*wire.MsgTx, error) { + fmt.Printf("ParseTx data: %v\n", string(data)) + dataBytes, err := hex.DecodeString(data) + if err != nil { + return nil, err + } + fmt.Printf("ParseTx dataBytes: %v\n", string(dataBytes)) + tx := &wire.MsgTx{} + err = tx.Deserialize(strings.NewReader(string(dataBytes))) + if err != nil { + return nil, err + } + return tx, nil +} diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go new file mode 100644 index 00000000..d550968f --- /dev/null +++ b/utils/multisig/utils.go @@ -0,0 +1,66 @@ +package multisig + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/hdkeychain" + "github.com/btcsuite/btcd/chaincfg" +) + +func GeneratePrivateKeyFromSeed(seed []byte, chainParam *chaincfg.Params) *btcec.PrivateKey { + seedDigest := sha256.Sum256([]byte(seed)) + masterKey, _ := hdkeychain.NewMaster(seedDigest[:], chainParam) + for _, childNum := range []uint32{1, 1, 1} { + var err error + masterKey, err = masterKey.Derive(hdkeychain.HardenedKeyStart + childNum) + if err != nil { + panic(err) + } + } + privateKey, _ := masterKey.ECPrivKey() + return privateKey +} + +func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcutil.AddressPubKey) { + + privKeys := []string{} + pubKeys := [][]byte{} + ECPubKeys := []*btcutil.AddressPubKey{} + + for i := 0; i < n; i++ { + privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) + wif, _ := btcutil.NewWIF(privKey, chainParam, true) + + ECPubKey, _ := btcutil.NewAddressPubKey(wif.SerializePubKey(), chainParam) + + pubKey := privKey.PubKey().SerializeCompressed() + pubKey2 := wif.SerializePubKey() + + fmt.Printf("Account %v:\n%v\n%v\n%v\n", i, wif.String(), hex.EncodeToString(wif.SerializePubKey()), wif.PrivKey.Serialize()) + privKeys = append(privKeys, wif.String()) + pubKeys = append(pubKeys, wif.SerializePubKey()) + ECPubKeys = append(ECPubKeys, ECPubKey) + + fmt.Printf("randomKeys pubKey %v - pubKey 2 %v\n ", pubKey, pubKey2) + } + fmt.Printf("len privateKey: %v\n", len(privKeys)) + fmt.Printf("len publicKey: %v\n", len(pubKeys)) + + return privKeys, pubKeys, ECPubKeys +} + + +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params) ([]string, *MultisigInfo) { + privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam) + vaultInfo := MultisigInfo{ + PubKeys: pubKeys, + EcPubKeys: EcPubKeys, + NumberRequiredSigs: k, + } + + return privKeys, &vaultInfo + +} \ No newline at end of file diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go new file mode 100644 index 00000000..66e6b445 --- /dev/null +++ b/utils/multisig/wallet.go @@ -0,0 +1,171 @@ +package multisig + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "math/big" + + "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/txscript" +) + +// hardcode temporarily +const SharedRandomHex = "304575862a092eb80b87dcbafdaac720687694f451ef063b4fb109071f9252ee" + +func toXOnly(pubKey []byte) []byte { + if len(pubKey) == 33 { + return pubKey[1:33] + } + + return pubKey +} + +// use OP_CHECKSIGADD instead of OP_CHECKMULTISIG legacy +func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, string, error) { + builder := txscript.NewScriptBuilder() + + // the first pubkey + builder.AddData(toXOnly(pubKeys[0])) + builder.AddOp(txscript.OP_CHECKSIG) + + // the remaining pubkeys + for i := 1; i < len(pubKeys); i++ { + builder.AddData(toXOnly(pubKeys[i])) + builder.AddOp(txscript.OP_CHECKSIGADD) + } + + // add number of required sigs + builder.AddInt64(int64(numSigsRequired)) + builder.AddOp(txscript.OP_NUMEQUAL) + + redeemScript, err := builder.Script() + if err != nil { + return []byte{}, "", fmt.Errorf("could not build script - Error %v", err) + } + + scriptStr, err := txscript.DisasmString(redeemScript) + fmt.Printf("Script str: %v\n", scriptStr) + fmt.Printf("Script str err: %v\n", err) + + + return redeemScript, "", nil +} + +func computeYCoordinate(x *big.Int) *big.Int { + // secp256k1 curve parameters + params := btcec.S256() + + // Compute y^2 = x^3 + 7 (mod p) + xCubed := new(big.Int).Exp(x, big.NewInt(3), params.P) + ySquared := new(big.Int).Add(xCubed, big.NewInt(7)) + ySquared.Mod(ySquared, params.P) + + // Compute y-coordinate using square root modulo p + y := new(big.Int).ModSqrt(ySquared, params.P) + return y +} + +func genSharedInternalPubKey(sharedRandom *big.Int) (*btcec.PublicKey, []byte, error) { + + // P = H + rG + uncompressGBytes := []byte{4} + uncompressGBytes = append(uncompressGBytes, btcec.S256().CurveParams.Params().Gx.Bytes()...) + uncompressGBytes = append(uncompressGBytes, btcec.S256().CurveParams.Params().Gy.Bytes()...) + hashGBytes := sha256.Sum256(uncompressGBytes) + + xH := new(big.Int).SetBytes(hashGBytes[:]) + yH := computeYCoordinate(xH) + isValidPoint := btcec.S256().IsOnCurve(xH, yH) + if !isValidPoint { + return nil, nil, fmt.Errorf("can not generate H point from hash of G") + } + + xrG, yrG := btcec.S256().ScalarBaseMult(sharedRandom.Bytes()) + xP, yP := btcec.S256().Add(xH, yH, xrG, yrG) + isValidPoint = btcec.S256().IsOnCurve(xP, yP) + if !isValidPoint { + return nil, nil, fmt.Errorf("can not generate P point") + } + xField := &btcec.FieldVal{} + xField.SetBytes((*[32]byte)(xP.Bytes())) + + yField := &btcec.FieldVal{} + yField.SetBytes((*[32]byte)(yP.Bytes())) + + publicKey := btcec.NewPublicKey(xField, yField) + + return publicKey, toXOnly(publicKey.SerializeCompressed()), nil + +} + +// create multisig struct contain multisig wallet detail +// input: multisig info (public keys, number of sigs required) +// output: multisig struct +func GenerateMultisigWallet( + multisigInfo *MultisigInfo, +) (*MultisigWallet, error) { + + // Taptree structure: + // TapLeaf 1: + + script1, _, err := buildMultisigTapScript(multisigInfo.NumberRequiredSigs, multisigInfo.PubKeys) + if err != nil { + return nil, fmt.Errorf("build script 1 err %v", err) + } + + tapLeaf1 := txscript.NewBaseTapLeaf(script1) + tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf1) + + fmt.Printf("TapTree: %+v\n", tapScriptTree) + + tapScriptRootHash := tapScriptTree.RootNode.TapHash() + + sharedRandomBytes, _ := hex.DecodeString(SharedRandomHex) + sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) + + sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) + if err != nil { + return nil, err + } + + outputKey := txscript.ComputeTaprootOutputKey( + sharedPublicKey, tapScriptRootHash[:], + ) + + pkScript, err := txscript.PayToTaprootScript(outputKey) + if err != nil { + return nil, fmt.Errorf("build taproot pk script err %v", err) + } + + return &MultisigWallet{ + PKScript: pkScript, + SharedPublicKey: sharedPublicKey, + + TapScriptTree: tapScriptTree, + TapLeaves: []txscript.TapLeaf{tapLeaf1}, + }, nil + +} + +func AddressOnChain( + chainParam *chaincfg.Params, + multisigWallet *MultisigWallet, +) (*btcutil.AddressTaproot, error) { + tapScriptRootHash := multisigWallet.TapScriptTree.RootNode.TapHash() + + outputKey := txscript.ComputeTaprootOutputKey( + multisigWallet.SharedPublicKey, tapScriptRootHash[:], + ) + + address, err := btcutil.NewAddressTaproot( + schnorr.SerializePubKey(outputKey), chainParam) + if err != nil { + return nil, fmt.Errorf("build address from script err %v", err) + } + + return address, nil +} \ No newline at end of file From d16c83027cfd31ba1c587552843d0d2abd9a9be4 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Thu, 27 Jun 2024 17:22:26 +0700 Subject: [PATCH 002/113] BB-105 update multisig code to allow signing tx through API --- utils/multisig/constants.go | 7 --- utils/multisig/multisig_test.go | 99 +++++++++++++++++++++++++-------- utils/multisig/test_utils.go | 79 ++++++++++++++++++++++++++ utils/multisig/tx.go | 29 +++++++--- utils/multisig/utils.go | 10 ---- utils/multisig/wallet.go | 7 --- 6 files changed, 175 insertions(+), 56 deletions(-) create mode 100644 utils/multisig/test_utils.go diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 35384f0e..40949478 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,10 +1,3 @@ package multisig const MIN_SAT = 546 - -const TEST_ACCOUNT_0_PRIVATE_KEY = "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy" -const TEST_ACCOUNT_0_PUBLIC_KEY = "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2" -const TEST_ACCOUNT_1_PRIVATE_KEY = "cRfK7N7cPZ1BZi6MpsNBuz7k3LiMMA7jreHMx3KUBjRV4KAQT9ou" -const TEST_ACCOUNT_1_PUBLIC_KEY = "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052" -const TEST_ACCOUNT_2_PRIVATE_KEY = "cU8TYnj3fp9t6hVcAz1rNm2GNLoLL2PFHpiCbkXmBCN6F1GZccxf" -const TEST_ACCOUNT_2_PUBLIC_KEY = "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833" diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 7392d198..2e058798 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/rand" "encoding/hex" + "encoding/json" "fmt" "math/big" "testing" @@ -67,35 +68,17 @@ func TestCreateTx(t *testing.T) { privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) inputs := []*UTXO{ - // 2/3 - empty data - // { - // WalletAddress: "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz", - // TxHash: "1a532a1bd32b6be1140a3e1de414aa4d0d7a215066d62e8a27b96810a80de9ea", - // OutputIdx: 0, - // OutputAmount: 100000, - // }, // 2/3 - empty data { - WalletAddress: "bcrt1ptkwstjj0fm24qfm4whkamzxlnp902fpqk2w0ust0usfu9fcmsccs9zvh5n", TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", OutputIdx: 0, OutputAmount: 10000, }, - // 3/3 - // { - // WalletAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", - // TxHash: "18166fe8fe7ca9a9ea5632021d1173860af5ad2c332424a6d1f7d835c37ff347", - // OutputIdx: 0, - // OutputAmount: 100000, - // }, - - // // 2/3 - // { - // WalletAddress: "bcrt1pmq64qc50jnn89s9e2cqn03y83rvqx75r2c2nx0fqqfp8w9jrfktsfkdyjs", - // TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", - // OutputIdx: 0, - // OutputAmount: 10000, - // }, + { + TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", + OutputIdx: 0, + OutputAmount: 20000, + }, } outputs := []*OutputTx{ @@ -116,7 +99,7 @@ func TestCreateTx(t *testing.T) { // validators sign tx totalSigs := [][][]byte{} // index private key -> index input -> sig for _, privKey := range privKeys { - sigs, _, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, prevOuts, multisigWallet, chainParam) + sigs, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, multisigWallet, 0, chainParam) if err != nil { fmt.Println("err sign: ", err) } @@ -136,6 +119,74 @@ func TestCreateTx(t *testing.T) { fmt.Println("err sign: ", err) } +func TestMultiRelayers(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + + inputs := []*UTXO{ + { + TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + OutputIdx: 0, + OutputAmount: 10000, + }, + { + TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", + OutputIdx: 0, + OutputAmount: 20000, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", + Amount: 8000, + }, + } + + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" + msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + + totalSigs := [][][]byte{} + // MATSTER RELAYER SIGN TX + sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet, 0, chainParam) + if err != nil { + fmt.Println("err sign: ", err) + } + totalSigs = append(totalSigs, sigs) + + router := SetUpRouter() + // create post body using an instance of the requestSignInput struct + rsi := requestSignInput{ + MsgTx: msgTx, + Inputs: inputs, + } + requestJson, _ := json.Marshal(rsi) + + // SLAVE RELAYER 1 SIGN TX + sigs1 := requestSign("/requestSign1", requestJson, router) + fmt.Println("resp: ", sigs1) + totalSigs = append(totalSigs, sigs1) + + // SLAVE RELAYER 2 SIGN TX + sigs2 := requestSign("/requestSign2", requestJson, router) + fmt.Println("resp: ", sigs2) + totalSigs = append(totalSigs, sigs2) + + // MATSTER RELAYER COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} + func TestGenSharedInternalPubKey(t *testing.T) { b := make([]byte, 32) diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go new file mode 100644 index 00000000..ef84aecb --- /dev/null +++ b/utils/multisig/test_utils.go @@ -0,0 +1,79 @@ +package multisig + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/wire" + "github.com/gin-gonic/gin" +) + +func SetUpRouter() *gin.Engine{ + router := gin.Default() + router.POST("/requestSign1", postRequestSignSlaveRelayer1) + router.POST("/requestSign2", postRequestSignSlaveRelayer2) + + return router +} + +func requestSign(url string, requestJson []byte, router *gin.Engine) [][]byte{ + req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestJson)) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + responseData, _ := io.ReadAll(w.Body) + + sigs := [][]byte{} + err := json.Unmarshal(responseData, &sigs) + if err != nil { + fmt.Println("err Unmarshal: ", err) + } + + return sigs +} + +type requestSignInput struct { + MsgTx *wire.MsgTx `json:"msgTx"` + Inputs []*UTXO `json:"inputs"` +} + +func postRequestSignSlaveRelayer1(c *gin.Context) { + var input requestSignInput + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + c.IndentedJSON(http.StatusOK, sigs) +} + +func postRequestSignSlaveRelayer2(c *gin.Context) { + var input requestSignInput + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + c.IndentedJSON(http.StatusOK, sigs) +} \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index c9029b56..8a282a58 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -113,35 +113,48 @@ func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, inputs []*UTXO, - prevOuts *txscript.MultiPrevOutFetcher, multisigWallet *MultisigWallet, + indexTapLeaf int, chainParam *chaincfg.Params, -) ([][]byte, string, error) { +) ([][]byte, error) { wif, err := btcutil.DecodeWIF(privKey) if err != nil { - return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) } // sign on each TxIn if len(inputs) != len(msgTx.TxIn) { - return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) } - sigs := [][]byte{} + prevOuts := txscript.NewMultiPrevOutFetcher(nil) + for _, in := range inputs { + utxoHash, err := chainhash.NewHashFromStr(in.TxHash) + if err != nil { + return nil, err + } + outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: multisigWallet.PKScript, + }) + } txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + sigs := [][]byte{} for i := range msgTx.TxIn { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[0], txscript.SigHashAll, wif.PrivKey) + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) if err != nil { - return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) } fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) sigs = append(sigs, sig) } - return sigs, msgTx.TxHash().String(), nil + return sigs, nil } // combine all the signatures to create the signed tx diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index d550968f..51e233c6 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -2,8 +2,6 @@ package multisig import ( "crypto/sha256" - "encoding/hex" - "fmt" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/hdkeychain" @@ -36,18 +34,10 @@ func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcu ECPubKey, _ := btcutil.NewAddressPubKey(wif.SerializePubKey(), chainParam) - pubKey := privKey.PubKey().SerializeCompressed() - pubKey2 := wif.SerializePubKey() - - fmt.Printf("Account %v:\n%v\n%v\n%v\n", i, wif.String(), hex.EncodeToString(wif.SerializePubKey()), wif.PrivKey.Serialize()) privKeys = append(privKeys, wif.String()) pubKeys = append(pubKeys, wif.SerializePubKey()) ECPubKeys = append(ECPubKeys, ECPubKey) - - fmt.Printf("randomKeys pubKey %v - pubKey 2 %v\n ", pubKey, pubKey2) } - fmt.Printf("len privateKey: %v\n", len(privKeys)) - fmt.Printf("len publicKey: %v\n", len(pubKeys)) return privKeys, pubKeys, ECPubKeys } diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index 66e6b445..1d2dd9d9 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -47,11 +47,6 @@ func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, stri return []byte{}, "", fmt.Errorf("could not build script - Error %v", err) } - scriptStr, err := txscript.DisasmString(redeemScript) - fmt.Printf("Script str: %v\n", scriptStr) - fmt.Printf("Script str err: %v\n", err) - - return redeemScript, "", nil } @@ -120,8 +115,6 @@ func GenerateMultisigWallet( tapLeaf1 := txscript.NewBaseTapLeaf(script1) tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf1) - fmt.Printf("TapTree: %+v\n", tapScriptTree) - tapScriptRootHash := tapScriptTree.RootNode.TapHash() sharedRandomBytes, _ := hex.DecodeString(SharedRandomHex) From 33e93a290243f84845fad19c7944a268e5d4a58c Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 2 Jul 2024 21:25:11 +0700 Subject: [PATCH 003/113] update to allow using the UTXO of user multisig --- utils/multisig/multisig_test.go | 118 +++++++++++++++++++++++----- utils/multisig/structure.go | 8 +- utils/multisig/test_utils.go | 63 ++++++++++++++- utils/multisig/tx.go | 132 +++++++++++++++++--------------- utils/multisig/utils.go | 10 +-- 5 files changed, 236 insertions(+), 95 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 2e058798..6277af0c 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/txscript" ) func TestGenerateKeys(t *testing.T) { @@ -39,7 +40,7 @@ func TestLoadWalletFromPrivateKey(t *testing.T) { } func TestRandomKeys(t *testing.T) { - randomKeys(3, &chaincfg.RegressionNetParams) + randomKeys(3, &chaincfg.RegressionNetParams, []int{0, 1, 2}) } func TestBuildMultisigTapScript(t *testing.T) { @@ -49,7 +50,7 @@ func TestBuildMultisigTapScript(t *testing.T) { numSigsRequired := 2 chainParam := &chaincfg.RegressionNetParams // 3 for multisig vault, 1 for recovery key - _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam) + _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam, []int{0, 1, 2}) fmt.Printf("Len pub key: %v\n", len(pubKeys[0])) @@ -65,16 +66,17 @@ func TestBuildMultisigTapScript(t *testing.T) { func TestCreateTx(t *testing.T) { chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) inputs := []*UTXO{ // 2/3 - empty data { + IsRelayersMultisig: true, TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", OutputIdx: 0, OutputAmount: 10000, }, { + IsRelayersMultisig: true, TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", OutputIdx: 0, OutputAmount: 20000, @@ -88,26 +90,74 @@ func TestCreateTx(t *testing.T) { }, } + _, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) fmt.Println("msgTx: ", msgTx) fmt.Println("prevOuts: ", prevOuts) fmt.Println("err: ", err) +} - // validators sign tx - totalSigs := [][][]byte{} // index private key -> index input -> sig - for _, privKey := range privKeys { - sigs, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, multisigWallet, 0, chainParam) - if err != nil { - fmt.Println("err sign: ", err) - } +func TestMultisigUserClaimLiquidity(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams - totalSigs = append(totalSigs, sigs) + inputs := []*UTXO{ + { + IsRelayersMultisig: true, + TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + OutputIdx: 0, + OutputAmount: 10000, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", + Amount: 8000, + }, } - signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" + msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + + totalSigs := [][][]byte{} + // MATSTER RELAYER SIGN TX + sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, true) + if err != nil { + fmt.Println("err sign: ", err) + } + totalSigs = append(totalSigs, sigs) + + router := SetUpRouter() + // create post body using an instance of the requestSignInput struct + rsi := requestSignInput{ + MsgTx: msgTx, + Inputs: inputs, + } + requestJson, _ := json.Marshal(rsi) + + // SLAVE RELAYER 1 SIGN TX + sigs1 := requestSign("/requestSign1", requestJson, router) + fmt.Println("resp: ", sigs1) + totalSigs = append(totalSigs, sigs1) + + // SLAVE RELAYER 2 SIGN TX + sigs2 := requestSign("/requestSign2", requestJson, router) + fmt.Println("resp: ", sigs2) + totalSigs = append(totalSigs, sigs2) + + // MATSTER RELAYER COMBINE SIGNS + transposedSigs := TransposeSigs(totalSigs) + relayersMultisigTapLeafScript := multisigWallet.TapLeaves[0].Script + ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) + relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() + + signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, nil, nil, msgTx, inputs, transposedSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -119,17 +169,18 @@ func TestCreateTx(t *testing.T) { fmt.Println("err sign: ", err) } -func TestMultiRelayers(t *testing.T) { +func TestMultisigUserSwap(t *testing.T) { chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) inputs := []*UTXO{ { + IsRelayersMultisig: true, TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", OutputIdx: 0, OutputAmount: 10000, }, { + IsRelayersMultisig: false, TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", OutputIdx: 0, OutputAmount: 20000, @@ -141,16 +192,23 @@ func TestMultiRelayers(t *testing.T) { ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", Amount: 8000, }, + { + ReceiverAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", + Amount: 8000, + }, } - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) + userPrivKeys, _ := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) + userMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet, 0, chainParam) + sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) if err != nil { fmt.Println("err sign: ", err) } @@ -174,8 +232,28 @@ func TestMultiRelayers(t *testing.T) { fmt.Println("resp: ", sigs2) totalSigs = append(totalSigs, sigs2) + // USER SIGN TX + userSigs, _ := UserSignTx(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0, chainParam) + // add user sign to total sigs + for i := range msgTx.TxIn { + if (!inputs[i].IsRelayersMultisig) { + totalSigs[1][i] = userSigs[i] + } + } + fmt.Println("--------totalSig: ", totalSigs) + // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + transposedSigs := TransposeSigs(totalSigs) + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script + ctrlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) + relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() + + userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script + userCtrlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) + userMultisigControlBlock, _ := userCtrlBlock.ToBytes() + + signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, userMultisigTapLeafScript, userMultisigControlBlock, msgTx, inputs, transposedSigs) + var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -188,7 +266,6 @@ func TestMultiRelayers(t *testing.T) { } func TestGenSharedInternalPubKey(t *testing.T) { - b := make([]byte, 32) rand.Read(b) bHex := hex.EncodeToString(b) @@ -199,7 +276,6 @@ func TestGenSharedInternalPubKey(t *testing.T) { func TestParseTx(t *testing.T) { // hexSignedTx := "02000000000104f6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0000000000ffffffffd9a54f6610fbc9b56cea421230b79edf5c48d92052c13c166656591f2d9ed1fd0000000000ffffffff7b02c2d6a2c8d14d3a1c717f4093306a2c485b4a0cff672ed26715555dff1fde0000000000fffffffff6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0100000000ffffffff05f82a000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd3c3d0900000000002251203cb3f6132189f271733e94476de372e022ea84dc2cb914c7ff691c453ddce563bcb1000000000000160014a355d136171b816b2b2f08d531cf94555d796751e803000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cda22d020000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd01401bdbfd310cbd31807024070825fc5a3fec6e7b37eb1d359dd3027727e5719c52e68b178f438d18c9218b13e3d95b8e3bd8efe1b422778fb88a59a8e5d4a7ba1601418f67cd9c4799e32ac9aed36c14a60e0a2442c4497cddb176ae118a9aeec099f0eaa68901681b0d6df6cdf45c062b70b73171d002d2c50345ea3c53bc51b6e8198301410315713b00ab6f47392e947e90aa4c67c37b77f9c76d1c5cb80a0df5f725dde2b883177dda0abe8dcbc7e06453c2720fa0eefea78e4b905a333929ee03e065bf830140430cc6f8e554c98930c7e67e9512bdc3c73a6944a60a58033607a9b195c857d0426ef570fb6640b07234ef33402a2ce22c66199ec57cbda27ce6028d3258f53100000000" - hexSignedTx := "01000000000101bcbbb24bd5953d424debb9a24c8009298771eecd3ac0d3c4b219d906a319dfa80000000000e803000002e803000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d53401f000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d530540f4085e4f85eb81b8bd6afd77f728ea75716108cb29cd02aa031def6be65e97e98db40430554669d7b64476d76fd9ae6646529b7abfeee1ac4ad67de0bce9608040f3fc057a9ad0e4a0132040826e2c8e3ca0678ebd515146b8825f527f31195e1966d8424cdf9e963b7335178cab820534e1bd4ede4e8addf47c1bc449a764cec400962c7b22626173655661756c7441646472657373223a22222c22726563656976657241646472657373223a22227d7520fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2ac2030edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052ba201e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833ba529c21c0636e6671d0135074f83177c5e456191043de9bd54744423b88d6b1ab4751650f00000000" msgTx, err := ParseTx(hexSignedTx) if err != nil { diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index b3a90407..19693d11 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -26,8 +26,8 @@ type OutputTx struct { } type UTXO struct { - WalletAddress string `bson:"wallet_address" json:"walletAddress"` - TxHash string `bson:"tx_hash" json:"txHash"` - OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` - OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` + IsRelayersMultisig bool `bson:"is_relayers_multisig" json:"isRelayersMultisig"` + TxHash string `bson:"tx_hash" json:"txHash"` + OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` + OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` } diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index ef84aecb..43c5f618 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -8,7 +8,10 @@ import ( "net/http" "net/http/httptest" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/gin-gonic/gin" ) @@ -53,10 +56,10 @@ func postRequestSignSlaveRelayer1(c *gin.Context) { } chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } @@ -71,9 +74,61 @@ func postRequestSignSlaveRelayer2(c *gin.Context) { } chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) +} + +func UserSignTx( + privKey string, + msgTx *wire.MsgTx, + inputs []*UTXO, + multisigWallet *MultisigWallet, + indexTapLeaf int, + chainParam *chaincfg.Params, +) ([][]byte, error) { + wif, err := btcutil.DecodeWIF(privKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) + } + + // sign on each TxIn + if len(inputs) != len(msgTx.TxIn) { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) + } + + prevOuts := txscript.NewMultiPrevOutFetcher(nil) + for _, in := range inputs { + utxoHash, err := chainhash.NewHashFromStr(in.TxHash) + if err != nil { + return nil, err + } + outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: multisigWallet.PKScript, + }) + } + txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + + sigs := [][]byte{} + for i := range msgTx.TxIn { + if (!inputs[i].IsRelayersMultisig) { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } + fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) + + sigs = append(sigs, sig) + } else { + sigs = append(sigs, []byte{}) + } + } + + return sigs, nil } \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 8a282a58..e5ccc355 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -3,7 +3,6 @@ package multisig import ( "bytes" "encoding/hex" - "errors" "fmt" "strings" @@ -23,7 +22,8 @@ func CreateMultisigTx( feePerOutput uint64, chainParam *chaincfg.Params, changeReceiverAddress string, - sourcePKScript []byte, + relayersPKScript []byte, + userPKScript []byte, ) (*wire.MsgTx, *txscript.MultiPrevOutFetcher, error) { msgTx := wire.NewMsgTx(wire.TxVersion) @@ -42,9 +42,16 @@ func CreateMultisigTx( msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount + var pkScript []byte + if (in.IsRelayersMultisig) { + pkScript = relayersPKScript + } else { + pkScript = userPKScript + } + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ Value: int64(in.OutputAmount), - PkScript: sourcePKScript, + PkScript: pkScript, }) } @@ -113,9 +120,12 @@ func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, inputs []*UTXO, - multisigWallet *MultisigWallet, - indexTapLeaf int, + relayersPKScript []byte, + relayersTapLeaf txscript.TapLeaf, + userPKScript []byte, + userTapLeaf txscript.TapLeaf, chainParam *chaincfg.Params, + isMasterRelayer bool, ) ([][]byte, error) { wif, err := btcutil.DecodeWIF(privKey) if err != nil { @@ -135,88 +145,90 @@ func PartSignOnRawExternalTx( } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + var pkScript []byte + if (in.IsRelayersMultisig) { + pkScript = relayersPKScript + } else { + pkScript = userPKScript + } + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ Value: int64(in.OutputAmount), - PkScript: multisigWallet.PKScript, + PkScript: pkScript, }) } txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) sigs := [][]byte{} for i := range msgTx.TxIn { - sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) - if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) - } - fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) + if (inputs[i].IsRelayersMultisig) { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } - sigs = append(sigs, sig) + sigs = append(sigs, sig) + } else if (isMasterRelayer) { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } + + sigs = append(sigs, sig) + } else { + sigs = append(sigs, []byte{}) + } } return sigs, nil } +func TransposeSigs(sigs [][][]byte) [][][]byte { + xl := len(sigs[0]) + yl := len(sigs) + result := make([][][]byte, xl) + + for i := range result { + result[i] = make([][]byte, yl) + } + for i := 0; i < xl; i++ { + for j := 0; j < yl; j++ { + result[i][j] = sigs[j][i] + } + } + return result +} + // combine all the signatures to create the signed tx // input: unsigned tx message, signatures, multisig struct // output: signed tx message, tx hash func CombineMultisigSigs( - multisigInfo *MultisigInfo, - multisigWallet *MultisigWallet, + relayersMultisigTapLeafScript []byte, + relayersMultisigControlBlock []byte, + userMultisigTapLeafScript []byte, + userMultisigControlBlock []byte, msgTx *wire.MsgTx, - totalSigs [][][]byte, + inputs []*UTXO, + transposedSigs [][][]byte, ) (*wire.MsgTx, error) { - // combine multisigs and finalize tx - numSig := uint(0) - sigs := make([][][]byte, len(msgTx.TxIn)) - for i := range sigs { - sigs[i] = [][]byte{} - } - - for _, sigsFromOneSigner := range totalSigs { - if numSig == uint(multisigInfo.NumberRequiredSigs) { - for indexInput := range sigsFromOneSigner { - if indexInput >= len(sigs) { - return nil, errors.New("invalid length of sigs") - } - sigs[indexInput] = append(sigs[indexInput], []byte{}) - } - } else { - for indexInput, sig := range sigsFromOneSigner { - if indexInput >= len(sigs) { - return nil, errors.New("invalid length of sigs") - } - - sigs[indexInput] = append(sigs[indexInput], sig) - } - numSig++ - } - } - - for idxInput, v := range sigs { - ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) - ctrlBlockBytes, err := ctrlBlock.ToBytes() - if err != nil { - return nil, fmt.Errorf("error including control block: %v", err) - } - + for idxInput, v := range transposedSigs { reverseV := [][]byte{} for i := len(v) - 1; i >= 0; i-- { - reverseV = append(reverseV, v[i]) + if (len(v[i]) != 0) { + reverseV = append(reverseV, v[i]) + } } - witness := append([][]byte{}, reverseV...) - witness = append(witness, multisigWallet.TapLeaves[0].Script) - witness = append(witness, ctrlBlockBytes) - witnessHexStr := []string{} - for _, w := range witness { - witnessHexStr = append(witnessHexStr, hex.EncodeToString(w)) - fmt.Printf("w idxInput %v - %v\n", idxInput, witnessHexStr) + witness := append([][]byte{}, reverseV...) + if (inputs[idxInput].IsRelayersMultisig) { + witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlock) + } else { + witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlock) } - fmt.Printf("Len witness %v: %v \n", idxInput, len(v)+len(multisigWallet.TapLeaves[0].Script)+len(ctrlBlockBytes)) - msgTx.TxIn[idxInput].Witness = witness } diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 51e233c6..59fdd17b 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -22,14 +22,14 @@ func GeneratePrivateKeyFromSeed(seed []byte, chainParam *chaincfg.Params) *btcec return privateKey } -func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcutil.AddressPubKey) { +func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][]byte, []*btcutil.AddressPubKey) { privKeys := []string{} pubKeys := [][]byte{} ECPubKeys := []*btcutil.AddressPubKey{} for i := 0; i < n; i++ { - privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) + privKey := GeneratePrivateKeyFromSeed([]byte{byte(seeds[i])}, chainParam) wif, _ := btcutil.NewWIF(privKey, chainParam, true) ECPubKey, _ := btcutil.NewAddressPubKey(wif.SerializePubKey(), chainParam) @@ -42,9 +42,8 @@ func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcu return privKeys, pubKeys, ECPubKeys } - -func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params) ([]string, *MultisigInfo) { - privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam) +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int) ([]string, *MultisigInfo) { + privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ PubKeys: pubKeys, EcPubKeys: EcPubKeys, @@ -52,5 +51,4 @@ func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params) ([]string, *M } return privKeys, &vaultInfo - } \ No newline at end of file From 0a904f5b4d74f17e779866e1b0f0fbd65c6de744 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 3 Jul 2024 16:52:15 +0700 Subject: [PATCH 004/113] BB-106 remove redundant code and update comments --- utils/multisig/multisig_test.go | 7 +++--- utils/multisig/structure.go | 1 - utils/multisig/tx.go | 44 +++++++++++++-------------------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 6277af0c..bc319683 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -94,9 +94,8 @@ func TestCreateTx(t *testing.T) { multisigWallet, _ := GenerateMultisigWallet(multisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) fmt.Println("msgTx: ", msgTx) - fmt.Println("prevOuts: ", prevOuts) fmt.Println("err: ", err) } @@ -123,7 +122,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { multisigWallet, _ := GenerateMultisigWallet(multisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX @@ -204,7 +203,7 @@ func TestMultisigUserSwap(t *testing.T) { userMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) + msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 19693d11..f2e1df3f 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -15,7 +15,6 @@ type MultisigInfo struct { type MultisigWallet struct { TapScriptTree *txscript.IndexedTapScriptTree TapLeaves []txscript.TapLeaf - PKScript []byte SharedPublicKey *btcec.PublicKey } diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index e5ccc355..30bfb54f 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -14,8 +14,8 @@ import ( ) // create unsigned multisig transaction -// input: UTXO, output, tx fee, chain config, change receiver -// output: unsigned tx message, previous output fetcher +// input: UTXOs, output, tx fee, chain config, change receiver, PK scripts +// output: unsigned tx message func CreateMultisigTx( inputs []*UTXO, outputs []*OutputTx, @@ -24,35 +24,22 @@ func CreateMultisigTx( changeReceiverAddress string, relayersPKScript []byte, userPKScript []byte, -) (*wire.MsgTx, *txscript.MultiPrevOutFetcher, error) { +) (*wire.MsgTx, error) { msgTx := wire.NewMsgTx(wire.TxVersion) // add TxIns into raw tx // totalInputAmount in external unit totalInputAmount := uint64(0) - prevOuts := txscript.NewMultiPrevOutFetcher(nil) for _, in := range inputs { utxoHash, err := chainhash.NewHashFromStr(in.TxHash) if err != nil { - return nil, nil, err + return nil, err } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) txIn := wire.NewTxIn(outPoint, nil, nil) txIn.Sequence = uint32(feePerOutput) msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount - - var pkScript []byte - if (in.IsRelayersMultisig) { - pkScript = relayersPKScript - } else { - pkScript = userPKScript - } - - prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ - Value: int64(in.OutputAmount), - PkScript: pkScript, - }) } // add TxOuts into raw tx @@ -62,16 +49,16 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) if err != nil { - return nil, nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + return nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, nil, err + return nil, err } // adding the destination address and the amount to the transaction if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { - return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) } redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) @@ -81,7 +68,7 @@ func CreateMultisigTx( // check amount of input coins and output coins if totalInputAmount < totalOutputAmount { - return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) } // calculate the change output @@ -90,11 +77,11 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) if err != nil { - return nil, nil, err + return nil, err } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, nil, err + return nil, err } // adding the destination address and the amount to the transaction @@ -110,12 +97,15 @@ func CreateMultisigTx( var rawTxBytes bytes.Buffer err := msgTx.Serialize(&rawTxBytes) if err != nil { - return nil, nil, err + return nil, err } - return msgTx, prevOuts, nil + return msgTx, nil } +// sign the tx with 1 relayer multisig key +// input: private key, unsigned tx message, UTXOs, PK scripts, tap leave, chain config, relayer type +// output: signatures func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, @@ -202,8 +192,8 @@ func TransposeSigs(sigs [][][]byte) [][][]byte { } // combine all the signatures to create the signed tx -// input: unsigned tx message, signatures, multisig struct -// output: signed tx message, tx hash +// input: tap leave, control blocks, unsigned tx message, UTXOs, signatures collection +// output: signed tx func CombineMultisigSigs( relayersMultisigTapLeafScript []byte, relayersMultisigControlBlock []byte, From daf929348dee8ce1c7d81c619d0707da3bbd9cf9 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Sat, 6 Jul 2024 11:51:43 +0700 Subject: [PATCH 005/113] BB-107 update to test on signet --- utils/multisig/constants.go | 2 +- utils/multisig/multisig_test.go | 90 ++++++++++++++------------------- utils/multisig/test_utils.go | 60 ++-------------------- utils/multisig/tx.go | 14 ++--- 4 files changed, 50 insertions(+), 116 deletions(-) diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 40949478..7f7d3948 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,3 +1,3 @@ package multisig -const MIN_SAT = 546 +const MIN_SAT = 100 diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index bc319683..7edc4716 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -15,7 +15,7 @@ import ( ) func TestGenerateKeys(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams for i := 0; i < 3; i++ { privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) @@ -29,7 +29,7 @@ func TestGenerateKeys(t *testing.T) { } func TestLoadWalletFromPrivateKey(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams wif, _ := btcutil.DecodeWIF("cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy") pubKey := wif.SerializePubKey(); @@ -40,32 +40,23 @@ func TestLoadWalletFromPrivateKey(t *testing.T) { } func TestRandomKeys(t *testing.T) { - randomKeys(3, &chaincfg.RegressionNetParams, []int{0, 1, 2}) + randomKeys(3, &chaincfg.SigNetParams, []int{0, 1, 2}) } func TestBuildMultisigTapScript(t *testing.T) { - // 2/3: bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz - // 3/3: bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h - totalSigs := 3 + totalSigs := 2 numSigsRequired := 2 - chainParam := &chaincfg.RegressionNetParams - // 3 for multisig vault, 1 for recovery key - _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam, []int{0, 1, 2}) + chainParam := &chaincfg.SigNetParams - fmt.Printf("Len pub key: %v\n", len(pubKeys[0])) - - multisigInfo := &MultisigInfo{ - PubKeys: pubKeys, - EcPubKeys: ECPubKeys, - NumberRequiredSigs: numSigsRequired, - } + _, multisigInfo := randomMultisigInfo(totalSigs, numSigsRequired, chainParam, []int{0, 3}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + multisigAddress, err := AddressOnChain(chainParam, multisigWallet) fmt.Println("address, err : ", multisigAddress, err) } func TestCreateTx(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ // 2/3 - empty data @@ -90,39 +81,36 @@ func TestCreateTx(t *testing.T) { }, } - _, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, 0) fmt.Println("msgTx: ", msgTx) fmt.Println("err: ", err) } func TestMultisigUserClaimLiquidity(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ { - IsRelayersMultisig: true, - TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + IsRelayersMultisig: false, + TxHash: "e16260c0de027d2f12ea8bbf6fa68fa57a26a3797d44bea27867cbfc6c1f0470", OutputIdx: 0, - OutputAmount: 10000, + OutputAmount: 778, }, } outputs := []*OutputTx{ { - ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", - Amount: 8000, + ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", + Amount: 556, }, } - privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + privKeys, multisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + msgTx, _ := CreateMultisigTx(inputs, outputs, 222, chainParam, changeReceiverAddress, 0) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX @@ -169,41 +157,37 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { } func TestMultisigUserSwap(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ { - IsRelayersMultisig: true, - TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + IsRelayersMultisig: false, + TxHash: "63181e1932a78e0735ce04d0989b50a37decc8ed6f6db071688ac83c95df6cb4", OutputIdx: 0, - OutputAmount: 10000, + OutputAmount: 1168, }, { - IsRelayersMultisig: false, - TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", - OutputIdx: 0, - OutputAmount: 20000, + IsRelayersMultisig: true, + TxHash: "555a2bb0ed3587edf108c626d2a43a16fedb1ff7ff7ceb8e7dbcc98da29c5dce", + OutputIdx: 1, + OutputAmount: 4900, }, } outputs := []*OutputTx{ { - ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", - Amount: 8000, - }, - { - ReceiverAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", - Amount: 8000, + ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", + Amount: 1834, }, } relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) - userPrivKeys, _ := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) - userMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) + userMultisigWallet, _ := GenerateMultisigWallet(userMultisigInfo) - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) + changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + msgTx, _ := CreateMultisigTx(inputs, outputs, 333, chainParam, changeReceiverAddress, 0) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX @@ -232,7 +216,7 @@ func TestMultisigUserSwap(t *testing.T) { totalSigs = append(totalSigs, sigs2) // USER SIGN TX - userSigs, _ := UserSignTx(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0, chainParam) + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) // add user sign to total sigs for i := range msgTx.TxIn { if (!inputs[i].IsRelayersMultisig) { @@ -243,16 +227,16 @@ func TestMultisigUserSwap(t *testing.T) { // MATSTER RELAYER COMBINE SIGNS transposedSigs := TransposeSigs(totalSigs) + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script ctrlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) - relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() + relayersMultisigControlBlockBytes, _ := ctrlBlock.ToBytes() userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script userCtrlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) - userMultisigControlBlock, _ := userCtrlBlock.ToBytes() - - signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, userMultisigTapLeafScript, userMultisigControlBlock, msgTx, inputs, transposedSigs) + userMultisigControlBlockBytes, _ := userCtrlBlock.ToBytes() + signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes, userMultisigTapLeafScript, userMultisigControlBlockBytes, msgTx, inputs, transposedSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index 43c5f618..a05c5005 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -55,8 +55,8 @@ func postRequestSignSlaveRelayer1(c *gin.Context) { return } - chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) + chainParam := &chaincfg.SigNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) @@ -73,62 +73,10 @@ func postRequestSignSlaveRelayer2(c *gin.Context) { return } - chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) + chainParam := &chaincfg.SigNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } - -func UserSignTx( - privKey string, - msgTx *wire.MsgTx, - inputs []*UTXO, - multisigWallet *MultisigWallet, - indexTapLeaf int, - chainParam *chaincfg.Params, -) ([][]byte, error) { - wif, err := btcutil.DecodeWIF(privKey) - if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) - } - - // sign on each TxIn - if len(inputs) != len(msgTx.TxIn) { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) - } - - prevOuts := txscript.NewMultiPrevOutFetcher(nil) - for _, in := range inputs { - utxoHash, err := chainhash.NewHashFromStr(in.TxHash) - if err != nil { - return nil, err - } - outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) - - prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ - Value: int64(in.OutputAmount), - PkScript: multisigWallet.PKScript, - }) - } - txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) - - sigs := [][]byte{} - for i := range msgTx.TxIn { - if (!inputs[i].IsRelayersMultisig) { - sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) - if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) - } - fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) - - sigs = append(sigs, sig) - } else { - sigs = append(sigs, []byte{}) - } - } - - return sigs, nil -} \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 30bfb54f..e7114a05 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -22,10 +22,12 @@ func CreateMultisigTx( feePerOutput uint64, chainParam *chaincfg.Params, changeReceiverAddress string, - relayersPKScript []byte, - userPKScript []byte, + lockTime uint32, ) (*wire.MsgTx, error) { msgTx := wire.NewMsgTx(wire.TxVersion) + if lockTime > 0 { + msgTx.LockTime = lockTime + } // add TxIns into raw tx // totalInputAmount in external unit @@ -153,17 +155,17 @@ func PartSignOnRawExternalTx( for i := range msgTx.TxIn { if (inputs[i].IsRelayersMultisig) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashAll, wif.PrivKey) + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when relayers-multisig key signing on raw btc tx: %v", err) } sigs = append(sigs, sig) } else if (isMasterRelayer) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashAll, wif.PrivKey) + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when user-multisig key signing on raw btc tx: %v", err) } sigs = append(sigs, sig) From b168f431e3318a1120794cffd6bc9e5b7100a1d5 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 8 Jul 2024 17:34:11 +0700 Subject: [PATCH 006/113] remove redundant import --- utils/multisig/test_utils.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index a05c5005..baedab95 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -8,9 +8,7 @@ import ( "net/http" "net/http/httptest" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/gin-gonic/gin" From 134f2f1e82c1a672b617027fd07df4c10af8c0d2 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 10 Jul 2024 10:02:57 +0700 Subject: [PATCH 007/113] BB-106 fix Invalid Schnorr signature for swap tx; optimize multisig code --- utils/multisig/constants.go | 1 + utils/multisig/multisig_test.go | 109 ++++++++++----------------- utils/multisig/structure.go | 8 ++ utils/multisig/test_utils.go | 59 ++++++++------- utils/multisig/tx.go | 128 ++++++++++++++++---------------- utils/multisig/wallet.go | 7 +- 6 files changed, 143 insertions(+), 169 deletions(-) diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 7f7d3948..7c17d056 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,3 +1,4 @@ package multisig const MIN_SAT = 100 +const SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" \ No newline at end of file diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 7edc4716..305daddf 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -55,66 +55,41 @@ func TestBuildMultisigTapScript(t *testing.T) { fmt.Println("address, err : ", multisigAddress, err) } -func TestCreateTx(t *testing.T) { - chainParam := &chaincfg.SigNetParams - - inputs := []*UTXO{ - // 2/3 - empty data - { - IsRelayersMultisig: true, - TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", - OutputIdx: 0, - OutputAmount: 10000, - }, - { - IsRelayersMultisig: true, - TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", - OutputIdx: 0, - OutputAmount: 20000, - }, - } - - outputs := []*OutputTx{ - { - ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", - Amount: 8000, - }, - } - - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, 0) - fmt.Println("msgTx: ", msgTx) - fmt.Println("err: ", err) -} - func TestMultisigUserClaimLiquidity(t *testing.T) { chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ { - IsRelayersMultisig: false, - TxHash: "e16260c0de027d2f12ea8bbf6fa68fa57a26a3797d44bea27867cbfc6c1f0470", - OutputIdx: 0, - OutputAmount: 778, + IsRelayersMultisig: true, + TxHash: "9ed822adb7c3623fcc6776bc93dadb030bf3b887e36975521d540c2a49510e27", + OutputIdx: 1, + OutputAmount: 3901, }, } outputs := []*OutputTx{ { ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", - Amount: 556, + Amount: 1000, }, } - privKeys, multisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, _ := CreateMultisigTx(inputs, outputs, 222, chainParam, changeReceiverAddress, 0) + msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: relayersMultisigWallet.PKScript, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: []byte{}, + UserTapLeaf: txscript.TapLeaf{}, + } totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, true) + sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) if err != nil { fmt.Println("err sign: ", err) } @@ -123,8 +98,9 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { router := SetUpRouter() // create post body using an instance of the requestSignInput struct rsi := requestSignInput{ - MsgTx: msgTx, - Inputs: inputs, + MsgTx: hexRawTx, + UTXOs: inputs, + TapSigInfo: tapSigParams, } requestJson, _ := json.Marshal(rsi) @@ -139,12 +115,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { totalSigs = append(totalSigs, sigs2) // MATSTER RELAYER COMBINE SIGNS - transposedSigs := TransposeSigs(totalSigs) - relayersMultisigTapLeafScript := multisigWallet.TapLeaves[0].Script - ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) - relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() - - signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, nil, nil, msgTx, inputs, transposedSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, relayersMultisigWallet, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -162,15 +133,15 @@ func TestMultisigUserSwap(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "63181e1932a78e0735ce04d0989b50a37decc8ed6f6db071688ac83c95df6cb4", + TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", OutputIdx: 0, - OutputAmount: 1168, + OutputAmount: 1501, }, { IsRelayersMultisig: true, - TxHash: "555a2bb0ed3587edf108c626d2a43a16fedb1ff7ff7ceb8e7dbcc98da29c5dce", + TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", OutputIdx: 1, - OutputAmount: 4900, + OutputAmount: 4234, }, } @@ -187,11 +158,18 @@ func TestMultisigUserSwap(t *testing.T) { userMultisigWallet, _ := GenerateMultisigWallet(userMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, _ := CreateMultisigTx(inputs, outputs, 333, chainParam, changeReceiverAddress, 0) + msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: relayersMultisigWallet.PKScript, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[0], + } totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) + sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) if err != nil { fmt.Println("err sign: ", err) } @@ -200,8 +178,9 @@ func TestMultisigUserSwap(t *testing.T) { router := SetUpRouter() // create post body using an instance of the requestSignInput struct rsi := requestSignInput{ - MsgTx: msgTx, - Inputs: inputs, + MsgTx: hexRawTx, + UTXOs: inputs, + TapSigInfo: tapSigParams, } requestJson, _ := json.Marshal(rsi) @@ -216,7 +195,8 @@ func TestMultisigUserSwap(t *testing.T) { totalSigs = append(totalSigs, sigs2) // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + // add user sign to total sigs for i := range msgTx.TxIn { if (!inputs[i].IsRelayersMultisig) { @@ -226,17 +206,7 @@ func TestMultisigUserSwap(t *testing.T) { fmt.Println("--------totalSig: ", totalSigs) // MATSTER RELAYER COMBINE SIGNS - transposedSigs := TransposeSigs(totalSigs) - - relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script - ctrlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) - relayersMultisigControlBlockBytes, _ := ctrlBlock.ToBytes() - - userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script - userCtrlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) - userMultisigControlBlockBytes, _ := userCtrlBlock.ToBytes() - - signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes, userMultisigTapLeafScript, userMultisigControlBlockBytes, msgTx, inputs, transposedSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, userMultisigWallet, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -258,7 +228,6 @@ func TestGenSharedInternalPubKey(t *testing.T) { } func TestParseTx(t *testing.T) { - // hexSignedTx := "02000000000104f6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0000000000ffffffffd9a54f6610fbc9b56cea421230b79edf5c48d92052c13c166656591f2d9ed1fd0000000000ffffffff7b02c2d6a2c8d14d3a1c717f4093306a2c485b4a0cff672ed26715555dff1fde0000000000fffffffff6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0100000000ffffffff05f82a000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd3c3d0900000000002251203cb3f6132189f271733e94476de372e022ea84dc2cb914c7ff691c453ddce563bcb1000000000000160014a355d136171b816b2b2f08d531cf94555d796751e803000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cda22d020000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd01401bdbfd310cbd31807024070825fc5a3fec6e7b37eb1d359dd3027727e5719c52e68b178f438d18c9218b13e3d95b8e3bd8efe1b422778fb88a59a8e5d4a7ba1601418f67cd9c4799e32ac9aed36c14a60e0a2442c4497cddb176ae118a9aeec099f0eaa68901681b0d6df6cdf45c062b70b73171d002d2c50345ea3c53bc51b6e8198301410315713b00ab6f47392e947e90aa4c67c37b77f9c76d1c5cb80a0df5f725dde2b883177dda0abe8dcbc7e06453c2720fa0eefea78e4b905a333929ee03e065bf830140430cc6f8e554c98930c7e67e9512bdc3c73a6944a60a58033607a9b195c857d0426ef570fb6640b07234ef33402a2ce22c66199ec57cbda27ce6028d3258f53100000000" hexSignedTx := "01000000000101bcbbb24bd5953d424debb9a24c8009298771eecd3ac0d3c4b219d906a319dfa80000000000e803000002e803000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d53401f000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d530540f4085e4f85eb81b8bd6afd77f728ea75716108cb29cd02aa031def6be65e97e98db40430554669d7b64476d76fd9ae6646529b7abfeee1ac4ad67de0bce9608040f3fc057a9ad0e4a0132040826e2c8e3ca0678ebd515146b8825f527f31195e1966d8424cdf9e963b7335178cab820534e1bd4ede4e8addf47c1bc449a764cec400962c7b22626173655661756c7441646472657373223a22222c22726563656976657241646472657373223a22227d7520fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2ac2030edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052ba201e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833ba529c21c0636e6671d0135074f83177c5e456191043de9bd54744423b88d6b1ab4751650f00000000" msgTx, err := ParseTx(hexSignedTx) if err != nil { diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index f2e1df3f..0ccb1ff5 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -30,3 +30,11 @@ type UTXO struct { OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` } + +type TapSigParams struct { + TxSigHashes *txscript.TxSigHashes `bson:"tx_sig_hashes" json:"txSigHashes"` + RelayersPKScript []byte `bson:"relayers_PK_script" json:"relayersPKScript"` + RelayersTapLeaf txscript.TapLeaf `bson:"relayers_tap_leaf" json:"relayersTapLeaf"` + UserPKScript []byte `bson:"user_PK_script" json:"userPKScript"` + UserTapLeaf txscript.TapLeaf `bson:"user_tap_leaf" json:"userTapLeaf"` +} diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index baedab95..3c0f6799 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -9,25 +9,23 @@ import ( "net/http/httptest" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" "github.com/gin-gonic/gin" ) func SetUpRouter() *gin.Engine{ - router := gin.Default() + router := gin.Default() router.POST("/requestSign1", postRequestSignSlaveRelayer1) router.POST("/requestSign2", postRequestSignSlaveRelayer2) - return router + return router } func requestSign(url string, requestJson []byte, router *gin.Engine) [][]byte{ req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestJson)) - w := httptest.NewRecorder() - router.ServeHTTP(w, req) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) - responseData, _ := io.ReadAll(w.Body) + responseData, _ := io.ReadAll(w.Body) sigs := [][]byte{} err := json.Unmarshal(responseData, &sigs) @@ -39,42 +37,43 @@ func requestSign(url string, requestJson []byte, router *gin.Engine) [][]byte{ } type requestSignInput struct { - MsgTx *wire.MsgTx `json:"msgTx"` - Inputs []*UTXO `json:"inputs"` + MsgTx string `json:"msgTx"` + UTXOs []*UTXO `json:"UTXOs"` + TapSigInfo TapSigParams `json:"tapSigInfo"` } func postRequestSignSlaveRelayer1(c *gin.Context) { - var input requestSignInput + var input requestSignInput if err := c.ShouldBindJSON(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), - }) - return - } + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } chainParam := &chaincfg.SigNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + msgTx, _ := ParseTx(input.MsgTx) + sigs, _ := PartSignOnRawExternalTx(privKeys[1], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) - sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) - c.IndentedJSON(http.StatusOK, sigs) + c.IndentedJSON(http.StatusOK, sigs) } func postRequestSignSlaveRelayer2(c *gin.Context) { - var input requestSignInput + var input requestSignInput - if err := c.ShouldBindJSON(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), - }) - return - } + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } chainParam := &chaincfg.SigNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + msgTx, _ := ParseTx(input.MsgTx) + sigs, _ := PartSignOnRawExternalTx(privKeys[2], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) - sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) - c.IndentedJSON(http.StatusOK, sigs) + c.IndentedJSON(http.StatusOK, sigs) } diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index e7114a05..428005f2 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -17,13 +17,15 @@ import ( // input: UTXOs, output, tx fee, chain config, change receiver, PK scripts // output: unsigned tx message func CreateMultisigTx( - inputs []*UTXO, - outputs []*OutputTx, - feePerOutput uint64, - chainParam *chaincfg.Params, - changeReceiverAddress string, + inputs []*UTXO, + outputs []*OutputTx, + feePerOutput uint64, + relayersMultisigWallet *MultisigWallet, + userMultisigWallet *MultisigWallet, + chainParam *chaincfg.Params, + changeReceiverAddress string, lockTime uint32, -) (*wire.MsgTx, error) { +) (*wire.MsgTx, string, *txscript.TxSigHashes, error) { msgTx := wire.NewMsgTx(wire.TxVersion) if lockTime > 0 { msgTx.LockTime = lockTime @@ -32,16 +34,29 @@ func CreateMultisigTx( // add TxIns into raw tx // totalInputAmount in external unit totalInputAmount := uint64(0) + prevOuts := txscript.NewMultiPrevOutFetcher(nil) for _, in := range inputs { utxoHash, err := chainhash.NewHashFromStr(in.TxHash) if err != nil { - return nil, err + return nil, "", nil, err } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) txIn := wire.NewTxIn(outPoint, nil, nil) txIn.Sequence = uint32(feePerOutput) msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount + + var pkScript []byte + if (in.IsRelayersMultisig) { + pkScript = relayersMultisigWallet.PKScript + } else { + pkScript = userMultisigWallet.PKScript + } + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: pkScript, + }) } // add TxOuts into raw tx @@ -51,16 +66,16 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) if err != nil { - return nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + return nil, "", nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, err + return nil, "", nil, err } // adding the destination address and the amount to the transaction if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { - return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) } redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) @@ -70,7 +85,7 @@ func CreateMultisigTx( // check amount of input coins and output coins if totalInputAmount < totalOutputAmount { - return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) } // calculate the change output @@ -79,11 +94,11 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) if err != nil { - return nil, err + return nil, "", nil, err } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, err + return nil, "", nil, err } // adding the destination address and the amount to the transaction @@ -99,10 +114,13 @@ func CreateMultisigTx( var rawTxBytes bytes.Buffer err := msgTx.Serialize(&rawTxBytes) if err != nil { - return nil, err + return nil, "", nil, err } + hexRawTx := hex.EncodeToString(rawTxBytes.Bytes()) - return msgTx, nil + txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + + return msgTx, hexRawTx, txSigHashes, nil } // sign the tx with 1 relayer multisig key @@ -112,10 +130,7 @@ func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, inputs []*UTXO, - relayersPKScript []byte, - relayersTapLeaf txscript.TapLeaf, - userPKScript []byte, - userTapLeaf txscript.TapLeaf, + tapSigParams TapSigParams, chainParam *chaincfg.Params, isMasterRelayer bool, ) ([][]byte, error) { @@ -129,33 +144,11 @@ func PartSignOnRawExternalTx( return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) } - prevOuts := txscript.NewMultiPrevOutFetcher(nil) - for _, in := range inputs { - utxoHash, err := chainhash.NewHashFromStr(in.TxHash) - if err != nil { - return nil, err - } - outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) - - var pkScript []byte - if (in.IsRelayersMultisig) { - pkScript = relayersPKScript - } else { - pkScript = userPKScript - } - - prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ - Value: int64(in.OutputAmount), - PkScript: pkScript, - }) - } - txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) - sigs := [][]byte{} for i := range msgTx.TxIn { if (inputs[i].IsRelayersMultisig) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) + msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.RelayersPKScript, tapSigParams.RelayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when relayers-multisig key signing on raw btc tx: %v", err) } @@ -163,7 +156,7 @@ func PartSignOnRawExternalTx( sigs = append(sigs, sig) } else if (isMasterRelayer) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashDefault, wif.PrivKey) + msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.UserPKScript, tapSigParams.UserTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when user-multisig key signing on raw btc tx: %v", err) } @@ -179,32 +172,40 @@ func PartSignOnRawExternalTx( func TransposeSigs(sigs [][][]byte) [][][]byte { xl := len(sigs[0]) - yl := len(sigs) - result := make([][][]byte, xl) - - for i := range result { - result[i] = make([][]byte, yl) - } - for i := 0; i < xl; i++ { - for j := 0; j < yl; j++ { - result[i][j] = sigs[j][i] - } - } - return result + yl := len(sigs) + result := make([][][]byte, xl) + + for i := range result { + result[i] = make([][]byte, yl) + } + for i := 0; i < xl; i++ { + for j := 0; j < yl; j++ { + result[i][j] = sigs[j][i] + } + } + + return result } // combine all the signatures to create the signed tx // input: tap leave, control blocks, unsigned tx message, UTXOs, signatures collection // output: signed tx func CombineMultisigSigs( - relayersMultisigTapLeafScript []byte, - relayersMultisigControlBlock []byte, - userMultisigTapLeafScript []byte, - userMultisigControlBlock []byte, - msgTx *wire.MsgTx, + msgTx *wire.MsgTx, inputs []*UTXO, - transposedSigs [][][]byte, + relayersMultisigWallet *MultisigWallet, + userMultisigWallet *MultisigWallet, + totalSigs [][][]byte, ) (*wire.MsgTx, error) { + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script + relayersMultisigControlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) + relayersMultisigControlBlockBytes, _ := relayersMultisigControlBlock.ToBytes() + + userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script + userMultisigControlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) + userMultisigControlBlockBytes, _ := userMultisigControlBlock.ToBytes() + + transposedSigs := TransposeSigs(totalSigs) for idxInput, v := range transposedSigs { reverseV := [][]byte{} for i := len(v) - 1; i >= 0; i-- { @@ -214,11 +215,10 @@ func CombineMultisigSigs( } witness := append([][]byte{}, reverseV...) - if (inputs[idxInput].IsRelayersMultisig) { - witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlock) + witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes) } else { - witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlock) + witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlockBytes) } msgTx.TxIn[idxInput].Witness = witness diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index 1d2dd9d9..9a17d54f 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -13,9 +13,6 @@ import ( "github.com/btcsuite/btcd/txscript" ) -// hardcode temporarily -const SharedRandomHex = "304575862a092eb80b87dcbafdaac720687694f451ef063b4fb109071f9252ee" - func toXOnly(pubKey []byte) []byte { if len(pubKey) == 33 { return pubKey[1:33] @@ -101,7 +98,7 @@ func genSharedInternalPubKey(sharedRandom *big.Int) (*btcec.PublicKey, []byte, e // input: multisig info (public keys, number of sigs required) // output: multisig struct func GenerateMultisigWallet( - multisigInfo *MultisigInfo, + multisigInfo *MultisigInfo, ) (*MultisigWallet, error) { // Taptree structure: @@ -117,7 +114,7 @@ func GenerateMultisigWallet( tapScriptRootHash := tapScriptTree.RootNode.TapHash() - sharedRandomBytes, _ := hex.DecodeString(SharedRandomHex) + sharedRandomBytes, _ := hex.DecodeString(SHARED_RANDOM_HEX) sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) From bd3722a82c509fa745916bc5587a2a6c3cad9131 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 10 Jul 2024 16:48:49 +0700 Subject: [PATCH 008/113] BB-104 update lock time tap-leaf to the multisig --- utils/multisig/multisig_test.go | 27 +++++---- utils/multisig/structure.go | 2 + utils/multisig/test_utils.go | 8 +-- utils/multisig/utils.go | 10 +-- utils/multisig/wallet.go | 104 ++++++++++++++++++++++---------- 5 files changed, 99 insertions(+), 52 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 305daddf..9b359b40 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -44,15 +44,18 @@ func TestRandomKeys(t *testing.T) { } func TestBuildMultisigTapScript(t *testing.T) { - totalSigs := 2 - numSigsRequired := 2 chainParam := &chaincfg.SigNetParams - _, multisigInfo := randomMultisigInfo(totalSigs, numSigsRequired, chainParam, []int{0, 3}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + _, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) + _, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - multisigAddress, err := AddressOnChain(chainParam, multisigWallet) - fmt.Println("address, err : ", multisigAddress, err) + relayersMultisigAddress, err := AddressOnChain(chainParam, relayersMultisigWallet) + fmt.Println("relayersMultisigAddress, err : ", relayersMultisigAddress, err) + + userMultisigAddress, err := AddressOnChain(chainParam, userMultisigWallet) + fmt.Println("userMultisigAddress, err : ", userMultisigAddress, err) } func TestMultisigUserClaimLiquidity(t *testing.T) { @@ -74,8 +77,8 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { }, } - relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) @@ -152,10 +155,10 @@ func TestMultisigUserSwap(t *testing.T) { }, } - relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) - userMultisigWallet, _ := GenerateMultisigWallet(userMultisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 0ccb1ff5..1f7d4893 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -10,6 +10,8 @@ type MultisigInfo struct { PubKeys [][]byte EcPubKeys []*btcutil.AddressPubKey NumberRequiredSigs int + RecoveryPubKey []byte + RecoveryBlockHeight uint64 } type MultisigWallet struct { diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index 3c0f6799..bb453723 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -53,9 +53,9 @@ func postRequestSignSlaveRelayer1(c *gin.Context) { } chainParam := &chaincfg.SigNetParams - privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + privKeys, _, _ := randomKeys(1, chainParam, []int{1}) msgTx, _ := ParseTx(input.MsgTx) - sigs, _ := PartSignOnRawExternalTx(privKeys[1], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) + sigs, _ := PartSignOnRawExternalTx(privKeys[0], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } @@ -71,9 +71,9 @@ func postRequestSignSlaveRelayer2(c *gin.Context) { } chainParam := &chaincfg.SigNetParams - privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + privKeys, _, _ := randomKeys(1, chainParam, []int{2}) msgTx, _ := ParseTx(input.MsgTx) - sigs, _ := PartSignOnRawExternalTx(privKeys[2], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) + sigs, _ := PartSignOnRawExternalTx(privKeys[0], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 59fdd17b..65d43f9d 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -42,12 +42,14 @@ func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][] return privKeys, pubKeys, ECPubKeys } -func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int) ([]string, *MultisigInfo) { +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryBlockHeight uint64) ([]string, *MultisigInfo) { privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ - PubKeys: pubKeys, - EcPubKeys: EcPubKeys, - NumberRequiredSigs: k, + PubKeys: pubKeys, + EcPubKeys: EcPubKeys, + NumberRequiredSigs: k, + RecoveryPubKey: pubKeys[recoveryKeyIdx], + RecoveryBlockHeight: recoveryBlockHeight, } return privKeys, &vaultInfo diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index 9a17d54f..a40ca465 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -47,6 +47,67 @@ func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, stri return redeemScript, "", nil } +// Point time lock contract script +// use OP_CHECKLOCKTIMEVERIFY +func buildPTLCTapScript( + expiredBlkHeight uint64, + pubKey []byte, +) ([]byte, string, error) { + + // OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG + + builder := txscript.NewScriptBuilder() + // builder.AddData(new(big.Int).SetUint64(expiredBlkHeight).Bytes()) // TODO: need to fixed length? + builder.AddInt64(int64(expiredBlkHeight)) + builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY) + builder.AddOp(txscript.OP_DROP) + builder.AddData(toXOnly(pubKey)) + builder.AddOp(txscript.OP_CHECKSIG) + + scriptBytes, err := builder.Script() + if err != nil { + return []byte{}, "", fmt.Errorf("buildPTLCTapScript could not build script - Error %v", err) + } + + return scriptBytes, "", nil +} + +func buildMultisigWalletFromScripts(scripts [][]byte) (*MultisigWallet, error) { + tapLeaves := []txscript.TapLeaf{} + for _, script := range scripts { + tapLeaf := txscript.NewBaseTapLeaf(script) + tapLeaves = append(tapLeaves, tapLeaf) + } + + tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...) + tapScriptRootHash := tapScriptTree.RootNode.TapHash() + + sharedRandomBytes, _ := hex.DecodeString(SHARED_RANDOM_HEX) + sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) + + sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) + if err != nil { + return nil, err + } + + outputKey := txscript.ComputeTaprootOutputKey( + sharedPublicKey, tapScriptRootHash[:], + ) + + pkScript, err := txscript.PayToTaprootScript(outputKey) + if err != nil { + return nil, fmt.Errorf("build taproot PK script err %v", err) + } + + return &MultisigWallet{ + PKScript: pkScript, + SharedPublicKey: sharedPublicKey, + + TapScriptTree: tapScriptTree, + TapLeaves: tapLeaves, + }, nil +} + func computeYCoordinate(x *big.Int) *big.Int { // secp256k1 curve parameters params := btcec.S256() @@ -97,48 +158,27 @@ func genSharedInternalPubKey(sharedRandom *big.Int) (*btcec.PublicKey, []byte, e // create multisig struct contain multisig wallet detail // input: multisig info (public keys, number of sigs required) // output: multisig struct -func GenerateMultisigWallet( +func BuildMultisigWallet( multisigInfo *MultisigInfo, ) (*MultisigWallet, error) { - // Taptree structure: // TapLeaf 1: - + // TapLeaf 2: script1, _, err := buildMultisigTapScript(multisigInfo.NumberRequiredSigs, multisigInfo.PubKeys) if err != nil { - return nil, fmt.Errorf("build script 1 err %v", err) - } - - tapLeaf1 := txscript.NewBaseTapLeaf(script1) - tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf1) - - tapScriptRootHash := tapScriptTree.RootNode.TapHash() - - sharedRandomBytes, _ := hex.DecodeString(SHARED_RANDOM_HEX) - sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) - - sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) - if err != nil { - return nil, err + return nil, fmt.Errorf("build script multisig err %v", err) } - outputKey := txscript.ComputeTaprootOutputKey( - sharedPublicKey, tapScriptRootHash[:], - ) + if multisigInfo.RecoveryBlockHeight == 0 { + return buildMultisigWalletFromScripts([][]byte{script1}) + } else { + script2, _, err := buildPTLCTapScript(multisigInfo.RecoveryBlockHeight, multisigInfo.RecoveryPubKey) + if err != nil { + return nil, fmt.Errorf("build script PTLC err %v", err) + } - pkScript, err := txscript.PayToTaprootScript(outputKey) - if err != nil { - return nil, fmt.Errorf("build taproot pk script err %v", err) + return buildMultisigWalletFromScripts([][]byte{script1, script2}) } - - return &MultisigWallet{ - PKScript: pkScript, - SharedPublicKey: sharedPublicKey, - - TapScriptTree: tapScriptTree, - TapLeaves: []txscript.TapLeaf{tapLeaf1}, - }, nil - } func AddressOnChain( From 33572f2a8629be4f9fafe09a2929aa4dbc202cff Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 12 Jul 2024 21:05:07 +0700 Subject: [PATCH 009/113] BB-106 update multisig time lock recovery test --- utils/multisig/multisig_test.go | 55 +++++++++++++++++++++++++++++++-- utils/multisig/tx.go | 12 ++++--- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 9b359b40..f1181cec 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -118,7 +118,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { totalSigs = append(totalSigs, sigs2) // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, relayersMultisigWallet, totalSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, relayersMultisigWallet, 0, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -209,7 +209,7 @@ func TestMultisigUserSwap(t *testing.T) { fmt.Println("--------totalSig: ", totalSigs) // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, userMultisigWallet, totalSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, userMultisigWallet, 0, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -246,3 +246,54 @@ func TestParseTx(t *testing.T) { fmt.Printf("txOut: %+v\n ", txOut) } } + +func TestUserRecoveryTimeLock(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "69c88fa67f3c5aad9b4494618046969f4a8e0dfccaa10def6dbbb5ff192c9924", + OutputIdx: 1, + OutputAmount: 7308, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pnlfh96hs3sc0tvanxhqlcfnwz32shff726f8yt6vay4tk62y4c9sluydah", + Amount: 1500, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1p2u4dx80df4xa87fxzw8wrqh698xxa2deu9nyfkjkrfd3fgk3l8dqc0tg3t" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 428005f2..5aa8f926 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -183,7 +183,7 @@ func TransposeSigs(sigs [][][]byte) [][][]byte { result[i][j] = sigs[j][i] } } - + return result } @@ -194,15 +194,17 @@ func CombineMultisigSigs( msgTx *wire.MsgTx, inputs []*UTXO, relayersMultisigWallet *MultisigWallet, + relayersIndexTapLeaf int, userMultisigWallet *MultisigWallet, + userIndexTapLeaf int, totalSigs [][][]byte, ) (*wire.MsgTx, error) { - relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script - relayersMultisigControlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[relayersIndexTapLeaf].Script + relayersMultisigControlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[relayersIndexTapLeaf].ToControlBlock(relayersMultisigWallet.SharedPublicKey) relayersMultisigControlBlockBytes, _ := relayersMultisigControlBlock.ToBytes() - userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script - userMultisigControlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) + userMultisigTapLeafScript := userMultisigWallet.TapLeaves[userIndexTapLeaf].Script + userMultisigControlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[userIndexTapLeaf].ToControlBlock(userMultisigWallet.SharedPublicKey) userMultisigControlBlockBytes, _ := userMultisigControlBlock.ToBytes() transposedSigs := TransposeSigs(totalSigs) From 54e80e746e17b5e6dc1b169458ac216cb83bea0f Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 15 Jul 2024 21:14:31 +0700 Subject: [PATCH 010/113] BB-106 update multisig recovery to relative timelock --- go.work.sum | 1184 +++++++++++++++++++++++++++++++ utils/multisig/multisig_test.go | 12 +- utils/multisig/structure.go | 2 +- utils/multisig/tx.go | 10 +- utils/multisig/utils.go | 4 +- utils/multisig/wallet.go | 16 +- 6 files changed, 1205 insertions(+), 23 deletions(-) create mode 100644 go.work.sum diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 00000000..20099db4 --- /dev/null +++ b/go.work.sum @@ -0,0 +1,1184 @@ +4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= +4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= +cloud.google.com/go v0.0.0-20170206221025-ce650573d812/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= +cloud.google.com/go/accessapproval v1.7.5/go.mod h1:g88i1ok5dvQ9XJsxpUInWWvUBrIZhyPDPbk4T01OoJ0= +cloud.google.com/go/accessapproval v1.7.7/go.mod h1:10ZDPYiTm8tgxuMPid8s2DL93BfCt6xBh/Vg0Xd8pU0= +cloud.google.com/go/accesscontextmanager v1.8.5/go.mod h1:TInEhcZ7V9jptGNqN3EzZ5XMhT6ijWxTGjzyETwmL0Q= +cloud.google.com/go/accesscontextmanager v1.8.7/go.mod h1:jSvChL1NBQ+uLY9zUBdPy9VIlozPoHptdBnRYeWuQoM= +cloud.google.com/go/aiplatform v1.60.0/go.mod h1:eTlGuHOahHprZw3Hio5VKmtThIOak5/qy6pzdsqcQnM= +cloud.google.com/go/aiplatform v1.67.0/go.mod h1:s/sJ6btBEr6bKnrNWdK9ZgHCvwbZNdP90b3DDtxxw+Y= +cloud.google.com/go/analytics v0.23.0/go.mod h1:YPd7Bvik3WS95KBok2gPXDqQPHy08TsCQG6CdUCb+u0= +cloud.google.com/go/analytics v0.23.2/go.mod h1:vtE3olAXZ6edJYk1UOndEs6EfaEc9T2B28Y4G5/a7Fo= +cloud.google.com/go/apigateway v1.6.5/go.mod h1:6wCwvYRckRQogyDDltpANi3zsCDl6kWi0b4Je+w2UiI= +cloud.google.com/go/apigateway v1.6.7/go.mod h1:7wAMb/33Rzln+PrGK16GbGOfA1zAO5Pq6wp19jtIt7c= +cloud.google.com/go/apigeeconnect v1.6.5/go.mod h1:MEKm3AiT7s11PqTfKE3KZluZA9O91FNysvd3E6SJ6Ow= +cloud.google.com/go/apigeeconnect v1.6.7/go.mod h1:hZxCKvAvDdKX8+eT0g5eEAbRSS9Gkzi+MPWbgAMAy5U= +cloud.google.com/go/apigeeregistry v0.8.3/go.mod h1:aInOWnqF4yMQx8kTjDqHNXjZGh/mxeNlAf52YqtASUs= +cloud.google.com/go/apigeeregistry v0.8.5/go.mod h1:ZMg60hq2K35tlqZ1VVywb9yjFzk9AJ7zqxrysOxLi3o= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/appengine v1.8.5/go.mod h1:uHBgNoGLTS5di7BvU25NFDuKa82v0qQLjyMJLuPQrVo= +cloud.google.com/go/appengine v1.8.7/go.mod h1:1Fwg2+QTgkmN6Y+ALGwV8INLbdkI7+vIvhcKPZCML0g= +cloud.google.com/go/area120 v0.8.5/go.mod h1:BcoFCbDLZjsfe4EkCnEq1LKvHSK0Ew/zk5UFu6GMyA0= +cloud.google.com/go/area120 v0.8.7/go.mod h1:L/xTq4NLP9mmxiGdcsVz7y1JLc9DI8pfaXRXbnjkR6w= +cloud.google.com/go/artifactregistry v1.14.7/go.mod h1:0AUKhzWQzfmeTvT4SjfI4zjot72EMfrkvL9g9aRjnnM= +cloud.google.com/go/artifactregistry v1.14.9/go.mod h1:n2OsUqbYoUI2KxpzQZumm6TtBgtRf++QulEohdnlsvI= +cloud.google.com/go/asset v1.17.2/go.mod h1:SVbzde67ehddSoKf5uebOD1sYw8Ab/jD/9EIeWg99q4= +cloud.google.com/go/asset v1.19.1/go.mod h1:kGOS8DiCXv6wU/JWmHWCgaErtSZ6uN5noCy0YwVaGfs= +cloud.google.com/go/assuredworkloads v1.11.5/go.mod h1:FKJ3g3ZvkL2D7qtqIGnDufFkHxwIpNM9vtmhvt+6wqk= +cloud.google.com/go/assuredworkloads v1.11.7/go.mod h1:CqXcRH9N0KCDtHhFisv7kk+cl//lyV+pYXGi1h8rCEU= +cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= +cloud.google.com/go/automl v1.13.5/go.mod h1:MDw3vLem3yh+SvmSgeYUmUKqyls6NzSumDm9OJ3xJ1Y= +cloud.google.com/go/automl v1.13.7/go.mod h1:E+s0VOsYXUdXpq0y4gNZpi0A/s6y9+lAarmV5Eqlg40= +cloud.google.com/go/baremetalsolution v1.2.4/go.mod h1:BHCmxgpevw9IEryE99HbYEfxXkAEA3hkMJbYYsHtIuY= +cloud.google.com/go/baremetalsolution v1.2.6/go.mod h1:KkS2BtYXC7YGbr42067nzFr+ABFMs6cxEcA1F+cedIw= +cloud.google.com/go/batch v1.8.0/go.mod h1:k8V7f6VE2Suc0zUM4WtoibNrA6D3dqBpB+++e3vSGYc= +cloud.google.com/go/batch v1.8.5/go.mod h1:YSWU2RTIeoHWVwieZJDTLEfWWUsuk10uhAr5K1dTMiw= +cloud.google.com/go/beyondcorp v1.0.4/go.mod h1:Gx8/Rk2MxrvWfn4WIhHIG1NV7IBfg14pTKv1+EArVcc= +cloud.google.com/go/beyondcorp v1.0.6/go.mod h1:wRkenqrVRtnGFfnyvIg0zBFUdN2jIfeojFF9JJDwVIA= +cloud.google.com/go/bigquery v1.59.1/go.mod h1:VP1UJYgevyTwsV7desjzNzDND5p6hZB+Z8gZJN1GQUc= +cloud.google.com/go/bigquery v1.61.0/go.mod h1:PjZUje0IocbuTOdq4DBOJLNYB0WF3pAKBHzAYyxCwFo= +cloud.google.com/go/billing v1.18.2/go.mod h1:PPIwVsOOQ7xzbADCwNe8nvK776QpfrOAUkvKjCUcpSE= +cloud.google.com/go/billing v1.18.5/go.mod h1:lHw7fxS6p7hLWEPzdIolMtOd0ahLwlokW06BzbleKP8= +cloud.google.com/go/binaryauthorization v1.8.1/go.mod h1:1HVRyBerREA/nhI7yLang4Zn7vfNVA3okoAR9qYQJAQ= +cloud.google.com/go/binaryauthorization v1.8.3/go.mod h1:Cul4SsGlbzEsWPOz2sH8m+g2Xergb6ikspUyQ7iOThE= +cloud.google.com/go/certificatemanager v1.7.5/go.mod h1:uX+v7kWqy0Y3NG/ZhNvffh0kuqkKZIXdvlZRO7z0VtM= +cloud.google.com/go/certificatemanager v1.8.1/go.mod h1:hDQzr50Vx2gDB+dOfmDSsQzJy/UPrYRdzBdJ5gAVFIc= +cloud.google.com/go/channel v1.17.5/go.mod h1:FlpaOSINDAXgEext0KMaBq/vwpLMkkPAw9b2mApQeHc= +cloud.google.com/go/channel v1.17.7/go.mod h1:b+FkgBrhMKM3GOqKUvqHFY/vwgp+rwsAuaMd54wCdN4= +cloud.google.com/go/cloudbuild v1.15.1/go.mod h1:gIofXZSu+XD2Uy+qkOrGKEx45zd7s28u/k8f99qKals= +cloud.google.com/go/cloudbuild v1.16.1/go.mod h1:c2KUANTtCBD8AsRavpPout6Vx8W+fsn5zTsWxCpWgq4= +cloud.google.com/go/clouddms v1.7.4/go.mod h1:RdrVqoFG9RWI5AvZ81SxJ/xvxPdtcRhFotwdE79DieY= +cloud.google.com/go/clouddms v1.7.6/go.mod h1:8HWZ2tznZ0mNAtTpfnRNT0QOThqn9MBUqTj0Lx8npIs= +cloud.google.com/go/cloudtasks v1.12.6/go.mod h1:b7c7fe4+TJsFZfDyzO51F7cjq7HLUlRi/KZQLQjDsaY= +cloud.google.com/go/cloudtasks v1.12.8/go.mod h1:aX8qWCtmVf4H4SDYUbeZth9C0n9dBj4dwiTYi4Or/P4= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= +cloud.google.com/go/compute v1.26.0 h1:uHf0NN2nvxl1Gh4QO83yRCOdMK4zivtMS5gv0dEX0hg= +cloud.google.com/go/compute v1.26.0/go.mod h1:T9RIRap4pVHCGUkVFRJ9hygT3KCXjip41X1GgWtBBII= +cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI= +cloud.google.com/go/contactcenterinsights v1.13.2/go.mod h1:AfkSB8t7mt2sIY6WpfO61nD9J9fcidIchtxm9FqJVXk= +cloud.google.com/go/container v1.31.0/go.mod h1:7yABn5s3Iv3lmw7oMmyGbeV6tQj86njcTijkkGuvdZA= +cloud.google.com/go/container v1.35.1/go.mod h1:udm8fgLm3TtpnjFN4QLLjZezAIIp/VnMo316yIRVRQU= +cloud.google.com/go/containeranalysis v0.11.4/go.mod h1:cVZT7rXYBS9NG1rhQbWL9pWbXCKHWJPYraE8/FTSYPE= +cloud.google.com/go/containeranalysis v0.11.6/go.mod h1:YRf7nxcTcN63/Kz9f86efzvrV33g/UV8JDdudRbYEUI= +cloud.google.com/go/datacatalog v1.19.3/go.mod h1:ra8V3UAsciBpJKQ+z9Whkxzxv7jmQg1hfODr3N3YPJ4= +cloud.google.com/go/datacatalog v1.20.1/go.mod h1:Jzc2CoHudhuZhpv78UBAjMEg3w7I9jHA11SbRshWUjk= +cloud.google.com/go/dataflow v0.9.5/go.mod h1:udl6oi8pfUHnL0z6UN9Lf9chGqzDMVqcYTcZ1aPnCZQ= +cloud.google.com/go/dataflow v0.9.7/go.mod h1:3BjkOxANrm1G3+/EBnEsTEEgJu1f79mFqoOOZfz3v+E= +cloud.google.com/go/dataform v0.9.2/go.mod h1:S8cQUwPNWXo7m/g3DhWHsLBoufRNn9EgFrMgne2j7cI= +cloud.google.com/go/dataform v0.9.4/go.mod h1:jjo4XY+56UrNE0wsEQsfAw4caUs4DLJVSyFBDelRDtQ= +cloud.google.com/go/datafusion v1.7.5/go.mod h1:bYH53Oa5UiqahfbNK9YuYKteeD4RbQSNMx7JF7peGHc= +cloud.google.com/go/datafusion v1.7.7/go.mod h1:qGTtQcUs8l51lFA9ywuxmZJhS4ozxsBSus6ItqCUWMU= +cloud.google.com/go/datalabeling v0.8.5/go.mod h1:IABB2lxQnkdUbMnQaOl2prCOfms20mcPxDBm36lps+s= +cloud.google.com/go/datalabeling v0.8.7/go.mod h1:/PPncW5gxrU15UzJEGQoOT3IobeudHGvoExrtZ8ZBwo= +cloud.google.com/go/dataplex v1.14.2/go.mod h1:0oGOSFlEKef1cQeAHXy4GZPB/Ife0fz/PxBf+ZymA2U= +cloud.google.com/go/dataplex v1.16.0/go.mod h1:OlBoytuQ56+7aUCC03D34CtoF/4TJ5SiIrLsBdDu87Q= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataproc/v2 v2.4.0/go.mod h1:3B1Ht2aRB8VZIteGxQS/iNSJGzt9+CA0WGnDVMEm7Z4= +cloud.google.com/go/dataproc/v2 v2.4.2/go.mod h1:smGSj1LZP3wtnsM9eyRuDYftNAroAl6gvKp/Wk64XDE= +cloud.google.com/go/dataqna v0.8.5/go.mod h1:vgihg1mz6n7pb5q2YJF7KlXve6tCglInd6XO0JGOlWM= +cloud.google.com/go/dataqna v0.8.7/go.mod h1:hvxGaSvINAVH5EJJsONIwT1y+B7OQogjHPjizOFoWOo= +cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= +cloud.google.com/go/datastore v1.17.0/go.mod h1:RiRZU0G6VVlIVlv1HRo3vSAPFHULV0ddBNsXO+Sony4= +cloud.google.com/go/datastream v1.10.4/go.mod h1:7kRxPdxZxhPg3MFeCSulmAJnil8NJGGvSNdn4p1sRZo= +cloud.google.com/go/datastream v1.10.6/go.mod h1:lPeXWNbQ1rfRPjBFBLUdi+5r7XrniabdIiEaCaAU55o= +cloud.google.com/go/deploy v1.17.1/go.mod h1:SXQyfsXrk0fBmgBHRzBjQbZhMfKZ3hMQBw5ym7MN/50= +cloud.google.com/go/deploy v1.18.1/go.mod h1:uyUQPHkz695IbRyyCtmU+jypWZlbd69Le55hhAqEx4A= +cloud.google.com/go/dialogflow v1.49.0/go.mod h1:dhVrXKETtdPlpPhE7+2/k4Z8FRNUp6kMV3EW3oz/fe0= +cloud.google.com/go/dialogflow v1.53.0/go.mod h1:LqAvxq7bXiiGC3/DWIz9XXCxth2z2qpSnBAAmlNOj6U= +cloud.google.com/go/dlp v1.11.2/go.mod h1:9Czi+8Y/FegpWzgSfkRlyz+jwW6Te9Rv26P3UfU/h/w= +cloud.google.com/go/dlp v1.13.0/go.mod h1:5T/dFtKOn2Q3QLnaKjjir7nEGA8K00WaqoKodLkbF/c= +cloud.google.com/go/documentai v1.25.0/go.mod h1:ftLnzw5VcXkLItp6pw1mFic91tMRyfv6hHEY5br4KzY= +cloud.google.com/go/documentai v1.28.0/go.mod h1:ZTt9RkTRmqOn5GQgU4JxHJxbobemOoo6FSy0byEQHqY= +cloud.google.com/go/domains v0.9.5/go.mod h1:dBzlxgepazdFhvG7u23XMhmMKBjrkoUNaw0A8AQB55Y= +cloud.google.com/go/domains v0.9.7/go.mod h1:u/yVf3BgfPJW3QDZl51qTJcDXo9PLqnEIxfGmGgbHEc= +cloud.google.com/go/edgecontainer v1.1.5/go.mod h1:rgcjrba3DEDEQAidT4yuzaKWTbkTI5zAMu3yy6ZWS0M= +cloud.google.com/go/edgecontainer v1.2.1/go.mod h1:OE2D0lbkmGDVYLCvpj8Y0M4a4K076QB7E2JupqOR/qU= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.6.6/go.mod h1:XbqHJGaiH0v2UvtuucfOzFXN+rpL/aU5BCZLn4DYl1Q= +cloud.google.com/go/essentialcontacts v1.6.8/go.mod h1:EHONVDSum2xxG2p+myyVda/FwwvGbY58ZYC4XqI/lDQ= +cloud.google.com/go/eventarc v1.13.4/go.mod h1:zV5sFVoAa9orc/52Q+OuYUG9xL2IIZTbbuTHC6JSY8s= +cloud.google.com/go/eventarc v1.13.6/go.mod h1:QReOaYnDNdjwAQQWNC7nfr63WnaKFUw7MSdQ9PXJYj0= +cloud.google.com/go/filestore v1.8.1/go.mod h1:MbN9KcaM47DRTIuLfQhJEsjaocVebNtNQhSLhKCF5GM= +cloud.google.com/go/filestore v1.8.3/go.mod h1:QTpkYpKBF6jlPRmJwhLqXfJQjVrQisplyb4e2CwfJWc= +cloud.google.com/go/firestore v1.14.0/go.mod h1:96MVaHLsEhbvkBEdZgfN+AS/GIkco1LRpH9Xp9YZfzQ= +cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= +cloud.google.com/go/functions v1.16.0/go.mod h1:nbNpfAG7SG7Duw/o1iZ6ohvL7mc6MapWQVpqtM29n8k= +cloud.google.com/go/functions v1.16.2/go.mod h1:+gMvV5E3nMb9EPqX6XwRb646jTyVz8q4yk3DD6xxHpg= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v1.3.5/go.mod h1:KJ77KkNN7Wm1LdMopOelV6OodM01pMuK2/5Zt1t4Tvc= +cloud.google.com/go/gkebackup v1.4.1/go.mod h1:tVwSKC1/UxEA011ijRG8vlXaZThzTSy6vReO9fTOlX8= +cloud.google.com/go/gkeconnect v0.8.5/go.mod h1:LC/rS7+CuJ5fgIbXv8tCD/mdfnlAadTaUufgOkmijuk= +cloud.google.com/go/gkeconnect v0.8.7/go.mod h1:iUH1jgQpTyNFMK5LgXEq2o0beIJ2p7KKUUFerkf/eGc= +cloud.google.com/go/gkehub v0.14.5/go.mod h1:6bzqxM+a+vEH/h8W8ec4OJl4r36laxTs3A/fMNHJ0wA= +cloud.google.com/go/gkehub v0.14.7/go.mod h1:NLORJVTQeCdxyAjDgUwUp0A6BLEaNLq84mCiulsM4OE= +cloud.google.com/go/gkemulticloud v1.1.1/go.mod h1:C+a4vcHlWeEIf45IB5FFR5XGjTeYhF83+AYIpTy4i2Q= +cloud.google.com/go/gkemulticloud v1.1.3/go.mod h1:4WzfPnsOfdCIj6weekE5FIGCaeQKZ1HzGNUVZ1PpIxw= +cloud.google.com/go/grafeas v0.3.4/go.mod h1:A5m316hcG+AulafjAbPKXBO/+I5itU4LOdKO2R/uDIc= +cloud.google.com/go/grafeas v0.3.5/go.mod h1:y54iTBcI+lgUdI+kAPKb8jtPqeTkA2dsYzWSrQtpc5s= +cloud.google.com/go/gsuiteaddons v1.6.5/go.mod h1:Lo4P2IvO8uZ9W+RaC6s1JVxo42vgy+TX5a6hfBZ0ubs= +cloud.google.com/go/gsuiteaddons v1.6.7/go.mod h1:u+sGBvr07OKNnOnQiB/Co1q4U2cjo50ERQwvnlcpNis= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.7/go.mod h1:J4PMPg8TtyurAUvSmPj8FF3EDgY1SPRZxcUGrn7WXGA= +cloud.google.com/go/iap v1.9.4/go.mod h1:vO4mSq0xNf/Pu6E5paORLASBwEmphXEjgCFg7aeNu1w= +cloud.google.com/go/iap v1.9.6/go.mod h1:YiK+tbhDszhaVifvzt2zTEF2ch9duHtp6xzxj9a0sQk= +cloud.google.com/go/ids v1.4.5/go.mod h1:p0ZnyzjMWxww6d2DvMGnFwCsSxDJM666Iir1bK1UuBo= +cloud.google.com/go/ids v1.4.7/go.mod h1:yUkDC71u73lJoTaoONy0dsA0T7foekvg6ZRg9IJL0AA= +cloud.google.com/go/iot v1.7.5/go.mod h1:nq3/sqTz3HGaWJi1xNiX7F41ThOzpud67vwk0YsSsqs= +cloud.google.com/go/iot v1.7.7/go.mod h1:tr0bCOSPXtsg64TwwZ/1x+ReTWKlQRVXbM+DnrE54yM= +cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= +cloud.google.com/go/kms v1.16.0/go.mod h1:olQUXy2Xud+1GzYfiBO9N0RhjsJk5IJLU6n/ethLXVc= +cloud.google.com/go/language v1.12.3/go.mod h1:evFX9wECX6mksEva8RbRnr/4wi/vKGYnAJrTRXU8+f8= +cloud.google.com/go/language v1.12.5/go.mod h1:w/6a7+Rhg6Bc2Uzw6thRdKKNjnOzfKTJuxzD0JZZ0nM= +cloud.google.com/go/lifesciences v0.9.5/go.mod h1:OdBm0n7C0Osh5yZB7j9BXyrMnTRGBJIZonUMxo5CzPw= +cloud.google.com/go/lifesciences v0.9.7/go.mod h1:FQ713PhjAOHqUVnuwsCe1KPi9oAdaTfh58h1xPiW13g= +cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= +cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= +cloud.google.com/go/managedidentities v1.6.5/go.mod h1:fkFI2PwwyRQbjLxlm5bQ8SjtObFMW3ChBGNqaMcgZjI= +cloud.google.com/go/managedidentities v1.6.7/go.mod h1:UzslJgHnc6luoyx2JV19cTCi2Fni/7UtlcLeSYRzTV8= +cloud.google.com/go/maps v1.6.4/go.mod h1:rhjqRy8NWmDJ53saCfsXQ0LKwBHfi6OSh5wkq6BaMhI= +cloud.google.com/go/maps v1.8.0/go.mod h1:b/O9YYxiySNN0N/9swc9SHIM4b4phuoGORN2/H965Ek= +cloud.google.com/go/mediatranslation v0.8.5/go.mod h1:y7kTHYIPCIfgyLbKncgqouXJtLsU+26hZhHEEy80fSs= +cloud.google.com/go/mediatranslation v0.8.7/go.mod h1:6eJbPj1QJwiCP8R4K413qMx6ZHZJUi9QFpApqY88xWU= +cloud.google.com/go/memcache v1.10.5/go.mod h1:/FcblbNd0FdMsx4natdj+2GWzTq+cjZvMa1I+9QsuMA= +cloud.google.com/go/memcache v1.10.7/go.mod h1:SrU6+QBhvXJV0TA59+B3oCHtLkPx37eqdKmRUlmSE1k= +cloud.google.com/go/metastore v1.13.4/go.mod h1:FMv9bvPInEfX9Ac1cVcRXp8EBBQnBcqH6gz3KvJ9BAE= +cloud.google.com/go/metastore v1.13.6/go.mod h1:OBCVMCP7X9vA4KKD+5J4Q3d+tiyKxalQZnksQMq5MKY= +cloud.google.com/go/monitoring v1.18.0/go.mod h1:c92vVBCeq/OB4Ioyo+NbN2U7tlg5ZH41PZcdvfc+Lcg= +cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw= +cloud.google.com/go/networkconnectivity v1.14.4/go.mod h1:PU12q++/IMnDJAB+3r+tJtuCXCfwfN+C6Niyj6ji1Po= +cloud.google.com/go/networkconnectivity v1.14.6/go.mod h1:/azB7+oCSmyBs74Z26EogZ2N3UcXxdCHkCPcz8G32bU= +cloud.google.com/go/networkmanagement v1.9.4/go.mod h1:daWJAl0KTFytFL7ar33I6R/oNBH8eEOX/rBNHrC/8TA= +cloud.google.com/go/networkmanagement v1.13.2/go.mod h1:24VrV/5HFIOXMEtVQEUoB4m/w8UWvUPAYjfnYZcBc4c= +cloud.google.com/go/networksecurity v0.9.5/go.mod h1:KNkjH/RsylSGyyZ8wXpue8xpCEK+bTtvof8SBfIhMG8= +cloud.google.com/go/networksecurity v0.9.7/go.mod h1:aB6UiPnh/l32+TRvgTeOxVRVAHAFFqvK+ll3idU5BoY= +cloud.google.com/go/notebooks v1.11.3/go.mod h1:0wQyI2dQC3AZyQqWnRsp+yA+kY4gC7ZIVP4Qg3AQcgo= +cloud.google.com/go/notebooks v1.11.5/go.mod h1:pz6P8l2TvhWqAW3sysIsS0g2IUJKOzEklsjWJfi8sd4= +cloud.google.com/go/optimization v1.6.3/go.mod h1:8ve3svp3W6NFcAEFr4SfJxrldzhUl4VMUJmhrqVKtYA= +cloud.google.com/go/optimization v1.6.5/go.mod h1:eiJjNge1NqqLYyY75AtIGeQWKO0cvzD1ct/moCFaP2Q= +cloud.google.com/go/orchestration v1.8.5/go.mod h1:C1J7HesE96Ba8/hZ71ISTV2UAat0bwN+pi85ky38Yq8= +cloud.google.com/go/orchestration v1.9.2/go.mod h1:8bGNigqCQb/O1kK7PeStSNlyi58rQvZqDiuXT9KAcbg= +cloud.google.com/go/orgpolicy v1.12.1/go.mod h1:aibX78RDl5pcK3jA8ysDQCFkVxLj3aOQqrbBaUL2V5I= +cloud.google.com/go/orgpolicy v1.12.3/go.mod h1:6BOgIgFjWfJzTsVcib/4QNHOAeOjCdaBj69aJVs//MA= +cloud.google.com/go/osconfig v1.12.5/go.mod h1:D9QFdxzfjgw3h/+ZaAb5NypM8bhOMqBzgmbhzWViiW8= +cloud.google.com/go/osconfig v1.12.7/go.mod h1:ID7Lbqr0fiihKMwAOoPomWRqsZYKWxfiuafNZ9j1Y1M= +cloud.google.com/go/oslogin v1.13.1/go.mod h1:vS8Sr/jR7QvPWpCjNqy6LYZr5Zs1e8ZGW/KPn9gmhws= +cloud.google.com/go/oslogin v1.13.3/go.mod h1:WW7Rs1OJQ1iSUckZDilvNBSNPE8on740zF+4ZDR4o8U= +cloud.google.com/go/phishingprotection v0.8.5/go.mod h1:g1smd68F7mF1hgQPuYn3z8HDbNre8L6Z0b7XMYFmX7I= +cloud.google.com/go/phishingprotection v0.8.7/go.mod h1:FtYaOyGc/HQQU7wY4sfwYZBFDKAL+YtVBjUj8E3A3/I= +cloud.google.com/go/policytroubleshooter v1.10.3/go.mod h1:+ZqG3agHT7WPb4EBIRqUv4OyIwRTZvsVDHZ8GlZaoxk= +cloud.google.com/go/policytroubleshooter v1.10.5/go.mod h1:bpOf94YxjWUqsVKokzPBibMSAx937Jp2UNGVoMAtGYI= +cloud.google.com/go/privatecatalog v0.9.5/go.mod h1:fVWeBOVe7uj2n3kWRGlUQqR/pOd450J9yZoOECcQqJk= +cloud.google.com/go/privatecatalog v0.9.7/go.mod h1:NWLa8MCL6NkRSt8jhL8Goy2A/oHkvkeAxiA0gv0rIXI= +cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE= +cloud.google.com/go/pubsub v1.38.0/go.mod h1:IPMJSWSus/cu57UyR01Jqa/bNOQA+XnPF6Z4dKW4fAA= +cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= +cloud.google.com/go/recaptchaenterprise/v2 v2.9.2/go.mod h1:trwwGkfhCmp05Ll5MSJPXY7yvnO0p4v3orGANAFHAuU= +cloud.google.com/go/recaptchaenterprise/v2 v2.13.0/go.mod h1:jNYyn2ScR4DTg+VNhjhv/vJQdaU8qz+NpmpIzEE7HFQ= +cloud.google.com/go/recommendationengine v0.8.5/go.mod h1:A38rIXHGFvoPvmy6pZLozr0g59NRNREz4cx7F58HAsQ= +cloud.google.com/go/recommendationengine v0.8.7/go.mod h1:YsUIbweUcpm46OzpVEsV5/z+kjuV6GzMxl7OAKIGgKE= +cloud.google.com/go/recommender v1.12.1/go.mod h1:gf95SInWNND5aPas3yjwl0I572dtudMhMIG4ni8nr+0= +cloud.google.com/go/recommender v1.12.3/go.mod h1:OgN0MjV7/6FZUUPgF2QPQtYErtZdZc4u+5onvurcGEI= +cloud.google.com/go/redis v1.14.2/go.mod h1:g0Lu7RRRz46ENdFKQ2EcQZBAJ2PtJHJLuiiRuEXwyQw= +cloud.google.com/go/redis v1.14.4/go.mod h1:EnHDflqTNQmCBPCN4FQPZdM28vLdweAgxe6avAZpqug= +cloud.google.com/go/resourcemanager v1.9.5/go.mod h1:hep6KjelHA+ToEjOfO3garMKi/CLYwTqeAw7YiEI9x8= +cloud.google.com/go/resourcemanager v1.9.7/go.mod h1:cQH6lJwESufxEu6KepsoNAsjrUtYYNXRwxm4QFE5g8A= +cloud.google.com/go/resourcesettings v1.6.5/go.mod h1:WBOIWZraXZOGAgoR4ukNj0o0HiSMO62H9RpFi9WjP9I= +cloud.google.com/go/resourcesettings v1.6.7/go.mod h1:zwRL5ZoNszs1W6+eJYMk6ILzgfnTj13qfU4Wvfupuqk= +cloud.google.com/go/retail v1.16.0/go.mod h1:LW7tllVveZo4ReWt68VnldZFWJRzsh9np+01J9dYWzE= +cloud.google.com/go/retail v1.16.2/go.mod h1:T7UcBh4/eoxRBpP3vwZCoa+PYA9/qWRTmOCsV8DRdZ0= +cloud.google.com/go/run v1.3.4/go.mod h1:FGieuZvQ3tj1e9GnzXqrMABSuir38AJg5xhiYq+SF3o= +cloud.google.com/go/run v1.3.7/go.mod h1:iEUflDx4Js+wK0NzF5o7hE9Dj7QqJKnRj0/b6rhVq20= +cloud.google.com/go/scheduler v1.10.6/go.mod h1:pe2pNCtJ+R01E06XCDOJs1XvAMbv28ZsQEbqknxGOuE= +cloud.google.com/go/scheduler v1.10.8/go.mod h1:0YXHjROF1f5qTMvGTm4o7GH1PGAcmu/H/7J7cHOiHl0= +cloud.google.com/go/secretmanager v1.11.5/go.mod h1:eAGv+DaCHkeVyQi0BeXgAHOU0RdrMeZIASKc+S7VqH4= +cloud.google.com/go/secretmanager v1.13.0/go.mod h1:yWdfNmM2sLIiyv6RM6VqWKeBV7CdS0SO3ybxJJRhBEs= +cloud.google.com/go/security v1.15.5/go.mod h1:KS6X2eG3ynWjqcIX976fuToN5juVkF6Ra6c7MPnldtc= +cloud.google.com/go/security v1.16.1/go.mod h1:UoF8QXvvJlV9ORs4YW/izW5GmDQtFUoq2P6TJgPlif8= +cloud.google.com/go/securitycenter v1.24.4/go.mod h1:PSccin+o1EMYKcFQzz9HMMnZ2r9+7jbc+LvPjXhpwcU= +cloud.google.com/go/securitycenter v1.30.0/go.mod h1:/tmosjS/dfTnzJxOzZhTXdX3MXWsCmPWfcYOgkJmaJk= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicedirectory v1.11.4/go.mod h1:Bz2T9t+/Ehg6x+Y7Ycq5xiShYLD96NfEsWNHyitj1qM= +cloud.google.com/go/servicedirectory v1.11.6/go.mod h1:peVGYNc1xArhcqSuhPP+NXp8kdl22XhB5E8IiNBNfZY= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/shell v1.7.5/go.mod h1:hL2++7F47/IfpfTO53KYf1EC+F56k3ThfNEXd4zcuiE= +cloud.google.com/go/shell v1.7.7/go.mod h1:7OYaMm3TFMSZBh8+QYw6Qef+fdklp7CjjpxYAoJpZbQ= +cloud.google.com/go/spanner v1.57.0/go.mod h1:aXQ5QDdhPRIqVhYmnkAdwPYvj/DRN0FguclhEWw+jOo= +cloud.google.com/go/spanner v1.61.0/go.mod h1:+hdNE+zL7EWNfOWRetw01jxz8H5qsE/ayZvF/pfrAl8= +cloud.google.com/go/speech v1.21.1/go.mod h1:E5GHZXYQlkqWQwY5xRSLHw2ci5NMQNG52FfMU1aZrIA= +cloud.google.com/go/speech v1.23.1/go.mod h1:UNgzNxhNBuo/OxpF1rMhA/U2rdai7ILL6PBXFs70wq0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= +cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g= +cloud.google.com/go/storagetransfer v1.10.4/go.mod h1:vef30rZKu5HSEf/x1tK3WfWrL0XVoUQN/EPDRGPzjZs= +cloud.google.com/go/storagetransfer v1.10.6/go.mod h1:3sAgY1bx1TpIzfSzdvNGHrGYldeCTyGI/Rzk6Lc6A7w= +cloud.google.com/go/talent v1.6.6/go.mod h1:y/WQDKrhVz12WagoarpAIyKKMeKGKHWPoReZ0g8tseQ= +cloud.google.com/go/talent v1.6.8/go.mod h1:kqPAJvhxmhoUTuqxjjk2KqA8zUEeTDmH+qKztVubGlQ= +cloud.google.com/go/texttospeech v1.7.5/go.mod h1:tzpCuNWPwrNJnEa4Pu5taALuZL4QRRLcb+K9pbhXT6M= +cloud.google.com/go/texttospeech v1.7.7/go.mod h1:XO4Wr2VzWHjzQpMe3gS58Oj68nmtXMyuuH+4t0wy9eA= +cloud.google.com/go/tpu v1.6.5/go.mod h1:P9DFOEBIBhuEcZhXi+wPoVy/cji+0ICFi4TtTkMHSSs= +cloud.google.com/go/tpu v1.6.7/go.mod h1:o8qxg7/Jgt7TCgZc3jNkd4kTsDwuYD3c4JTMqXZ36hU= +cloud.google.com/go/trace v1.10.5/go.mod h1:9hjCV1nGBCtXbAE4YK7OqJ8pmPYSxPA0I67JwRd5s3M= +cloud.google.com/go/trace v1.10.7/go.mod h1:qk3eiKmZX0ar2dzIJN/3QhY2PIFh1eqcIdaN5uEjQPM= +cloud.google.com/go/translate v1.10.1/go.mod h1:adGZcQNom/3ogU65N9UXHOnnSvjPwA/jKQUMnsYXOyk= +cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= +cloud.google.com/go/video v1.20.4/go.mod h1:LyUVjyW+Bwj7dh3UJnUGZfyqjEto9DnrvTe1f/+QrW0= +cloud.google.com/go/video v1.20.6/go.mod h1:d5AOlIfWXpDg15wvztHmjFvKTTImWJU7EnMVWkoiEAk= +cloud.google.com/go/videointelligence v1.11.5/go.mod h1:/PkeQjpRponmOerPeJxNPuxvi12HlW7Em0lJO14FC3I= +cloud.google.com/go/videointelligence v1.11.7/go.mod h1:iMCXbfjurmBVgKuyLedTzv90kcnppOJ6ttb0+rLDID0= +cloud.google.com/go/vision/v2 v2.8.0/go.mod h1:ocqDiA2j97pvgogdyhoxiQp2ZkDCyr0HWpicywGGRhU= +cloud.google.com/go/vision/v2 v2.8.2/go.mod h1:BHZA1LC7dcHjSr9U9OVhxMtLKd5l2jKPzLRALEJvuaw= +cloud.google.com/go/vmmigration v1.7.5/go.mod h1:pkvO6huVnVWzkFioxSghZxIGcsstDvYiVCxQ9ZH3eYI= +cloud.google.com/go/vmmigration v1.7.7/go.mod h1:qYIK5caZY3IDMXQK+A09dy81QU8qBW0/JDTc39OaKRw= +cloud.google.com/go/vmwareengine v1.1.1/go.mod h1:nMpdsIVkUrSaX8UvmnBhzVzG7PPvNYc5BszcvIVudYs= +cloud.google.com/go/vmwareengine v1.1.3/go.mod h1:UoyF6LTdrIJRvDN8uUB8d0yimP5A5Ehkr1SRzL1APZw= +cloud.google.com/go/vpcaccess v1.7.5/go.mod h1:slc5ZRvvjP78c2dnL7m4l4R9GwL3wDLcpIWz6P/ziig= +cloud.google.com/go/vpcaccess v1.7.7/go.mod h1:EzfSlgkoAnFWEMznZW0dVNvdjFjEW97vFlKk4VNBhwY= +cloud.google.com/go/webrisk v1.9.5/go.mod h1:aako0Fzep1Q714cPEM5E+mtYX8/jsfegAuS8aivxy3U= +cloud.google.com/go/webrisk v1.9.7/go.mod h1:7FkQtqcKLeNwXCdhthdXHIQNcFWPF/OubrlyRcLHNuQ= +cloud.google.com/go/websecurityscanner v1.6.5/go.mod h1:QR+DWaxAz2pWooylsBF854/Ijvuoa3FCyS1zBa1rAVQ= +cloud.google.com/go/websecurityscanner v1.6.7/go.mod h1:EpiW84G5KXxsjtFKK7fSMQNt8JcuLA8tQp7j0cyV458= +cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= +cloud.google.com/go/workflows v1.12.6/go.mod h1:oDbEHKa4otYg4abwdw2Z094jB0TLLiFGAPA78EDAKag= +cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.3/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= +cosmossdk.io/log v1.2.0/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8= +cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= +cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= +cosmossdk.io/store v1.0.2/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= +cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= +cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= +cosmossdk.io/x/tx v0.13.0/go.mod h1:CpNQtmoqbXa33/DVxWQNx5Dcnbkv2xGUhL7tYQ5wUsY= +cosmossdk.io/x/upgrade v0.1.0/go.mod h1:/6jjNGbiPCNtmA1N+rBtP601sr0g4ZXuj3yC6ClPCGY= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= +github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= +github.com/Antonboom/nilnil v0.1.3/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= +github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= +github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= +github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794/go.mod h1:7e+I0LQFUI9AXWxOfsQROs9xPhoJtbsyWcjJqDd4KPY= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY= +github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= +github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= +github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= +github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= +github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA= +github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ= +github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= +github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= +github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= +github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= +github.com/bufbuild/buf v1.15.1/go.mod h1:TQeGKam1QMfHy/xsSnnMpxN3JK5HBb6aNvZj4m52gkE= +github.com/bufbuild/connect-go v1.5.2/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrIQMm1/a6LnHk= +github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40= +github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= +github.com/chigopher/pathlib v0.12.0/go.mod h1:EJ5UtJ/sK8Nt6q3VWN+EwZLZ3g0afJiG8NegYiQQ/gQ= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM= +github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/cockroachdb/pebble v0.0.0-20220817183557-09c6e030a677/go.mod h1:890yq1fUb9b6dGNwssgeUO5vQV9qfXnCPxAJhBQfXw0= +github.com/cockroachdb/pebble v0.0.0-20231101195458-481da04154d6/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= +github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= +github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= +github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= +github.com/cosmos/cosmos-sdk v0.50.3/go.mod h1:tlrkY1sntOt1q0OX/rqF0zRJtmXNoffAS6VFTcky+w8= +github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU= +github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= +github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= +github.com/cosmos/iavl v1.1.1/go.mod h1:jLeUvm6bGT1YutCaL2fIar/8vGUE8cPZvh/gXEWDaDM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= +github.com/creachadair/command v0.0.0-20220916173946-56a74cdd66b6/go.mod h1:jN7ZJM5YSVtD3SHmkAdN/cOC1dXiqg2Y9K5Sr5a8Nxw= +github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cristalhq/acmd v0.11.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= +github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= +github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/emicklei/dot v1.4.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emicklei/dot v1.6.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= +github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= +github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= +github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= +github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= +github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= +github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= +github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= +github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= +github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= +github.com/golangci/golangci-lint v1.52.0/go.mod h1:wlTh+d/oVlgZC2yCe6nlxrxNAnuhEQC0Zdygoh72Uak= +github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= +github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= +github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= +github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= +github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= +github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= +github.com/google/go-github/v43 v43.0.0/go.mod h1:ZkTvvmCXBvsfPpTHXnH/d2hP9Y0cTbvN9kr5xqyXOIc= +github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= +github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= +github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= +github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= +github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= +github.com/guptarohit/asciigraph v0.5.5/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= +github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= +github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-metrics v0.5.2/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= +github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/hydrogen18/memlistener v1.0.0/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/informalsystems/tm-load-test v1.3.0/go.mod h1:OQ5AQ9TbT5hKWBNIwsMjn6Bf4O0U4b1kRc+0qZlQJKw= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/httpexpect/v2 v2.12.1/go.mod h1:7+RB6W5oNClX7PTwJgJnsQP3ZuUUYB3u61KCqeSgZ88= +github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= +github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= +github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= +github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8= +github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I= +github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk= +github.com/kataras/golog v0.1.8/go.mod h1:rGPAin4hYROfk1qT9wZP6VY2rsb4zzc37QpdPjdkqVw= +github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U= +github.com/kataras/iris/v12 v12.2.0/go.mod h1:BLzBpEunc41GbE68OUaQlqX4jzi791mx5HU04uPb90Y= +github.com/kataras/jwt v0.1.8/go.mod h1:Q5j2IkcIHnfwy+oNY3TVWuEBJNw0ADgCcXK9CaZwV4o= +github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw= +github.com/kataras/neffos v0.0.21/go.mod h1:FeGka8lu8cjD2H+0OpBvW8c6xXawy3fj5VX6xcIJ1Fg= +github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= +github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZyUvI= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= +github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= +github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= +github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= +github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= +github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= +github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= +github.com/linxGnu/grocksdb v1.7.15/go.mod h1:pY55D0o+r8yUYLq70QmhdudxYvoDb9F+9puf4m3/W+U= +github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.12/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= +github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= +github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moricho/tparallel v0.3.0/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= +github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= +github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= +github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= +github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= +github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= +github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/ory/dockertest/v3 v3.9.1/go.mod h1:42Ir9hmvaAPm0Mgibk6mBPi7SFvTXxEcnztDYOJ//uM= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= +github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/pointlander/compress v1.1.1-0.20190518213731-ff44bd196cc3/go.mod h1:q5NXNGzqj5uPnVuhGkZfmgHqNUhf15VLi6L9kW0VEc0= +github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4/go.mod h1:RdR1j20Aj5pB6+fw6Y9Ur7lMHpegTEjY1vc19hEZL40= +github.com/pointlander/peg v1.0.1/go.mod h1:5hsGDQR2oZI4QoWz0/Kdg3VSVEC31iJw/b7WjqCBGRI= +github.com/polyfloyd/go-errorlint v1.4.5/go.mod h1:sIZEbFoDOCnTYYZoVkjc4hTnM459tuWA9H/EkdXwsKk= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ= +github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4= +github.com/protolambda/messagediff v1.4.0/go.mod h1:LboJp0EwIbJsePYpzh5Op/9G1/4mIztMRYzzwR0dR2M= +github.com/protolambda/zrnt v0.32.2/go.mod h1:A0fezkp9Tt3GBLATSPIbuY4ywYESyAuc/FFmPKg8Lqs= +github.com/protolambda/ztyp v0.2.2/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU= +github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk= +github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/remyoudompheng/go-dbus v0.0.0-20121104212943-b7232d34b1d5/go.mod h1:+u151txRmLpwxBmpYn9z3d1sdJdjRPQpsXuYeY9jNls= +github.com/remyoudompheng/go-liblzma v0.0.0-20190506200333-81bf2d431b96/go.mod h1:90HvCY7+oHHUKkbeMCiHt1WuFR2/hPJ9QrljDG+v6ls= +github.com/remyoudompheng/go-misc v0.0.0-20190427085024-2d6ac652a50e/go.mod h1:80FQABjoFzZ2M5uEa6FUaJYEmqU2UOKojlFVak1UAwI= +github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= +github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= +github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.17.0/go.mod h1:SMtHTvdmsZMuY/bpZoqokSoChIrcJ/epOxZN58PbZDg= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= +github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/shirou/gopsutil/v3 v3.23.2/go.mod h1:gv0aQw33GLo3pG8SiWKiQrbDzbRY1K80RyZJ7V4Th1M= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= +github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= +github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= +github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= +github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/strangelove-ventures/cometbft-client v0.1.0/go.mod h1:QzThgjzvsGgUNVNpGPitmxOWMIhp6a0oqf80nCRNt/0= +github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= +github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= +github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk= +github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= +github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= +github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= +github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= +github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= +github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= +github.com/vektra/mockery/v2 v2.23.1/go.mod h1:Zh3Kv1ckKs6FokhlVLcCu6UTyzfS3M8mpROz1lBNp+w= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= +gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= +go.einride.tech/aip v0.66.0/go.mod h1:qAhMsfT7plxBX+Oy7Huol6YUvZ0ZzdUz26yZsQwfl1M= +go.einride.tech/aip v0.67.1/go.mod h1:ZGX4/zKw8dcgzdLsrvpOOGxfxI2QSk12SlP7d6c0/XI= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= +go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= +go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA= +go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= +go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= +go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/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.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= +golang.org/x/perf v0.0.0-20230113213139-801c7ef9e5c5/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.0/go.mod h1:JWIHJ7U20drSQb/aDpTetJzfC1KlAPldJLpkSy88dvQ= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= +google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.160.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= +google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= +google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.176.1/go.mod h1:j2MaSDYcvYV1lkZ1+SMW4IeF90SrEyFA+tluDYWRrFg= +google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw= +google.golang.org/api v0.178.0/go.mod h1:84/k2v8DFpDRebpGcooklv/lais3MEfqpaBLA12gl2U= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/api v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:PVreiBMirk8ypES6aw9d4p6iiBNSIfZEBqr3UGoAi2E= +google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be/go.mod h1:dvdCTIoAGbkWbcIKBniID56/7XHTt6WfxXNMxuziJ+w= +google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6/go.mod h1:10yRODfgim2/T8csjQsMPgZOMvtytXKTDRzH6HRGzRw= +google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240509183442-62759503f434/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:om8Bj876Z0v9ei+RD1LnEWig7vpHQ371PUqsgjmLQEA= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240429193739-8cf5692501f6/go.mod h1:ULqtoQMxDLNRfW+pJbKA68wtIy1OiYjdIsJs3PMpzh8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240228201840-1f18d85a4ec2/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/ccgo/v3 v3.17.0/go.mod h1:Sg3fwVpmLvCUTaqEUjiBDAvshIaKDB0RXaf+zgqFu8I= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= +mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= +mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index f1181cec..eb96ab4a 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -253,24 +253,24 @@ func TestUserRecoveryTimeLock(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "69c88fa67f3c5aad9b4494618046969f4a8e0dfccaa10def6dbbb5ff192c9924", + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", OutputIdx: 1, - OutputAmount: 7308, + OutputAmount: 3808, }, } outputs := []*OutputTx{ { - ReceiverAddress: "tb1pnlfh96hs3sc0tvanxhqlcfnwz32shff726f8yt6vay4tk62y4c9sluydah", - Amount: 1500, + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, }, } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1p2u4dx80df4xa87fxzw8wrqh698xxa2deu9nyfkjkrfd3fgk3l8dqc0tg3t" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 1f7d4893..6c102102 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -11,7 +11,7 @@ type MultisigInfo struct { EcPubKeys []*btcutil.AddressPubKey NumberRequiredSigs int RecoveryPubKey []byte - RecoveryBlockHeight uint64 + RecoveryLockTime uint64 } type MultisigWallet struct { diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 5aa8f926..3a694229 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -26,10 +26,10 @@ func CreateMultisigTx( changeReceiverAddress string, lockTime uint32, ) (*wire.MsgTx, string, *txscript.TxSigHashes, error) { - msgTx := wire.NewMsgTx(wire.TxVersion) - if lockTime > 0 { - msgTx.LockTime = lockTime - } + msgTx := wire.NewMsgTx(2) + // if lockTime > 0 { + // msgTx.LockTime = lockTime + // } // add TxIns into raw tx // totalInputAmount in external unit @@ -42,7 +42,7 @@ func CreateMultisigTx( } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) txIn := wire.NewTxIn(outPoint, nil, nil) - txIn.Sequence = uint32(feePerOutput) + txIn.Sequence = lockTime msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 65d43f9d..2d6ea113 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -42,14 +42,14 @@ func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][] return privKeys, pubKeys, ECPubKeys } -func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryBlockHeight uint64) ([]string, *MultisigInfo) { +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryLockTime uint64) ([]string, *MultisigInfo) { privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ PubKeys: pubKeys, EcPubKeys: EcPubKeys, NumberRequiredSigs: k, RecoveryPubKey: pubKeys[recoveryKeyIdx], - RecoveryBlockHeight: recoveryBlockHeight, + RecoveryLockTime: recoveryLockTime, } return privKeys, &vaultInfo diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index a40ca465..3a4f64e3 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -48,18 +48,16 @@ func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, stri } // Point time lock contract script -// use OP_CHECKLOCKTIMEVERIFY +// use OP_CHECKLOCKTIMEVERIFY or OP_CHECKSEQUENCEVERIFY func buildPTLCTapScript( - expiredBlkHeight uint64, + lockTime uint64, pubKey []byte, ) ([]byte, string, error) { - // OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG - builder := txscript.NewScriptBuilder() - // builder.AddData(new(big.Int).SetUint64(expiredBlkHeight).Bytes()) // TODO: need to fixed length? - builder.AddInt64(int64(expiredBlkHeight)) - builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY) + builder.AddInt64(int64(lockTime)) + // builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) builder.AddOp(txscript.OP_DROP) builder.AddData(toXOnly(pubKey)) builder.AddOp(txscript.OP_CHECKSIG) @@ -169,10 +167,10 @@ func BuildMultisigWallet( return nil, fmt.Errorf("build script multisig err %v", err) } - if multisigInfo.RecoveryBlockHeight == 0 { + if multisigInfo.RecoveryLockTime == 0 { return buildMultisigWalletFromScripts([][]byte{script1}) } else { - script2, _, err := buildPTLCTapScript(multisigInfo.RecoveryBlockHeight, multisigInfo.RecoveryPubKey) + script2, _, err := buildPTLCTapScript(multisigInfo.RecoveryLockTime, multisigInfo.RecoveryPubKey) if err != nil { return nil, fmt.Errorf("build script PTLC err %v", err) } From dabc047b34a8bd96c12c2a35753d02c2f7532344 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 17 Jul 2024 17:44:05 +0700 Subject: [PATCH 011/113] BB-160 update rune transfering lib --- go.mod | 1 + go.sum | 2 ++ utils/multisig/multisig_test.go | 57 +++++++++++++++++++++++++++++++++ utils/multisig/rune.go | 45 ++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 utils/multisig/rune.go diff --git a/go.mod b/go.mod index 4dd838fb..96b11cd3 100644 --- a/go.mod +++ b/go.mod @@ -227,6 +227,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-varint v0.0.7 github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect diff --git a/go.sum b/go.sum index c6e1b6c5..b196c420 100644 --- a/go.sum +++ b/go.sum @@ -955,6 +955,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index eb96ab4a..90bba098 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" ) func TestGenerateKeys(t *testing.T) { @@ -293,6 +294,62 @@ func TestUserRecoveryTimeLock(t *testing.T) { hexSignedTx := hex.EncodeToString(signedTx.Bytes()) signedMsgTxID := signedMsgTx.TxHash().String() + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} + +func TestTransferRune(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + // Add Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 0 + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + msgTx.AddTxOut(wire.NewTxOut(0, script1)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + fmt.Println("hexSignedTx: ", hexSignedTx) fmt.Println("signedMsgTxID: ", signedMsgTxID) fmt.Println("err sign: ", err) diff --git a/utils/multisig/rune.go b/utils/multisig/rune.go new file mode 100644 index 00000000..9cd276db --- /dev/null +++ b/utils/multisig/rune.go @@ -0,0 +1,45 @@ +package multisig + +import ( + "math/big" + + "github.com/btcsuite/btcd/txscript" + "github.com/multiformats/go-varint" +) + +type Rune struct { + BlockNumber uint64 + TxIndex uint32 +} + +// Varint encoder, ported from +// https://github.com/ordinals/ord/blob/1e6cb641faf3b1eb0aba501a7a2822d7a3dc8643/crates/ordinals/src/varint.rs#L3-L39 +// Using big.Int since go doesn't support u128 +func encodeToSlice(n *big.Int) []byte { + var result []byte + var oneTwentyEight = big.NewInt(128) + + for n.Cmp(oneTwentyEight) >= 0 { + temp := new(big.Int).Mod(n, oneTwentyEight) + tempByte := byte(temp.Uint64()) | 0x80 + result = append(result, tempByte) + n.Div(n, oneTwentyEight) + } + result = append(result, byte(n.Uint64())) + return result +} + +func CreateRuneTransferScript(rune Rune, amount *big.Int, output uint64) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(txscript.OP_13) + + data := varint.ToUvarint(0) + data = append(data, encodeToSlice(big.NewInt(int64(rune.BlockNumber)))...) + data = append(data, encodeToSlice(big.NewInt(int64(rune.TxIndex)))...) + data = append(data, encodeToSlice(amount)...) + data = append(data, encodeToSlice(big.NewInt(int64(output)))...) + + return builder.AddData(data).Script() +} \ No newline at end of file From 9bc478fc33d66d114bc0062134273b81ba9baa3b Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 19 Jul 2024 10:50:26 +0700 Subject: [PATCH 012/113] BB-160 update runestone decipher --- go.mod | 6 +++++- go.sum | 7 +++++++ utils/multisig/multisig_test.go | 13 ++++++++++++- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 96b11cd3..0934d42e 100644 --- a/go.mod +++ b/go.mod @@ -41,11 +41,14 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bshuster-repo/logrus-logstash-hook v0.4.1 // indirect - github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd // indirect + github.com/btcsuite/btcd v0.24.0 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9 // indirect github.com/cespare/cp v1.1.1 // indirect github.com/cosmos/ibc-go/v8 v8.0.0 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/evalphobia/logrus_fluent v0.5.4 // indirect github.com/fluent/fluent-logger-golang v1.9.0 // indirect @@ -97,6 +100,7 @@ require ( gopkg.in/go-playground/validator.v9 v9.31.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + lukechampine.com/uint128 v1.3.0 // indirect ) require ( diff --git a/go.sum b/go.sum index b196c420..56d7a461 100644 --- a/go.sum +++ b/go.sum @@ -322,6 +322,8 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= +github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= @@ -334,6 +336,7 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -345,6 +348,8 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= +github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9 h1:vQzL9/RqazAbUe0o5OwVCMIQllDl1Nfzvx2JYcwGurI= +github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9/go.mod h1:pieyLaoNj2JsfnMzZm9McEZmGU804aTBsRQNTwqeqVk= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -1937,6 +1942,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 90bba098..8c10873a 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/bxelab/runestone" ) func TestGenerateKeys(t *testing.T) { @@ -353,4 +354,14 @@ func TestTransferRune(t *testing.T) { fmt.Println("hexSignedTx: ", hexSignedTx) fmt.Println("signedMsgTxID: ", signedMsgTxID) fmt.Println("err sign: ", err) -} \ No newline at end of file + + // Decipher runestone + r := &runestone.Runestone{} + artifact, err := r.Decipher(signedMsgTx) + if err != nil { + fmt.Println(err) + return + } + a, _ := json.Marshal(artifact) + fmt.Printf("Artifact: %s\n", string(a)) +} From 74b6b2acfa79de6f5346648052b6d31c8664dabc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=C3=A2n=20Nguy=E1=BB=85n?= <30438379+quankori@users.noreply.github.com> Date: Tue, 30 Jul 2024 11:39:57 +0700 Subject: [PATCH 013/113] Bb 158 relayer btc support init connection between shard of multisig wallet (#2) * feat: add transmission and bitcoin module --------- Co-authored-by: k0r1 --- README.md | 21 + cmd/bitcoin.go | 18 + cmd/root.go | 1 + go.work.sum | 927 +++++++++++++++++++++++++++ relayer/chains/bitcoin/client.go | 14 + relayer/chains/bitcoin/master.go | 114 ++++ relayer/chains/bitcoin/slave.go | 36 ++ relayer/chains/evm/event_parse.go | 6 +- relayer/chains/icon/query.go | 6 +- relayer/transmission/transmission.go | 38 ++ 10 files changed, 1179 insertions(+), 2 deletions(-) create mode 100644 cmd/bitcoin.go create mode 100644 go.work.sum create mode 100644 relayer/chains/bitcoin/client.go create mode 100644 relayer/chains/bitcoin/master.go create mode 100644 relayer/chains/bitcoin/slave.go create mode 100644 relayer/transmission/transmission.go diff --git a/README.md b/README.md index cb1df404..9b9d1535 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,24 @@ The following chains are supported: ## How to use ? Refer to the [WIKI](). + +## Bitcoin Relay + +How to run Slave server + +### Prerequisites + +Go 1.x installed +Set up your environment variables as required + +### Start Slave + +```bash +GO_ENV=master MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin +``` + +### Start Master + +```bash +GO_ENV=slave MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin +``` diff --git a/cmd/bitcoin.go b/cmd/bitcoin.go new file mode 100644 index 00000000..c9d56a88 --- /dev/null +++ b/cmd/bitcoin.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/icon-project/centralized-relay/relayer/chains/bitcoin" + "github.com/spf13/cobra" +) + +func bitcoinCmd(a *appState) *cobra.Command { + bitcoinCmd := &cobra.Command{ + Use: "bitcoin", + Short: "Run Bitcoin Relayer", + Run: func(cmd *cobra.Command, args []string) { + bitcoin.RunApp() + }, + } + + return bitcoinCmd +} diff --git a/cmd/root.go b/cmd/root.go index 6c59a737..1c9dbdd9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -159,6 +159,7 @@ func NewRootCmd(log *zap.Logger) *cobra.Command { dbCmd(a), keystoreCmd(a), contractCMD(a), + bitcoinCmd(a), ) return rootCmd } diff --git a/go.work.sum b/go.work.sum new file mode 100644 index 00000000..c252a7ee --- /dev/null +++ b/go.work.sum @@ -0,0 +1,927 @@ +4d63.com/gocheckcompilerdirectives v1.2.1/go.mod h1:yjDJSxmDTtIHHCqX0ufRYZDL6vQtMG7tJdKVeWwsqvs= +4d63.com/gochecknoglobals v0.2.1/go.mod h1:KRE8wtJB3CXCsb1xy421JfTHIIbmT3U5ruxw2Qu8fSU= +cloud.google.com/go v0.0.0-20170206221025-ce650573d812/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= +cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= +cloud.google.com/go/accessapproval v1.7.7/go.mod h1:10ZDPYiTm8tgxuMPid8s2DL93BfCt6xBh/Vg0Xd8pU0= +cloud.google.com/go/accesscontextmanager v1.8.7/go.mod h1:jSvChL1NBQ+uLY9zUBdPy9VIlozPoHptdBnRYeWuQoM= +cloud.google.com/go/aiplatform v1.67.0/go.mod h1:s/sJ6btBEr6bKnrNWdK9ZgHCvwbZNdP90b3DDtxxw+Y= +cloud.google.com/go/analytics v0.23.2/go.mod h1:vtE3olAXZ6edJYk1UOndEs6EfaEc9T2B28Y4G5/a7Fo= +cloud.google.com/go/apigateway v1.6.7/go.mod h1:7wAMb/33Rzln+PrGK16GbGOfA1zAO5Pq6wp19jtIt7c= +cloud.google.com/go/apigeeconnect v1.6.7/go.mod h1:hZxCKvAvDdKX8+eT0g5eEAbRSS9Gkzi+MPWbgAMAy5U= +cloud.google.com/go/apigeeregistry v0.8.5/go.mod h1:ZMg60hq2K35tlqZ1VVywb9yjFzk9AJ7zqxrysOxLi3o= +cloud.google.com/go/appengine v1.8.7/go.mod h1:1Fwg2+QTgkmN6Y+ALGwV8INLbdkI7+vIvhcKPZCML0g= +cloud.google.com/go/area120 v0.8.7/go.mod h1:L/xTq4NLP9mmxiGdcsVz7y1JLc9DI8pfaXRXbnjkR6w= +cloud.google.com/go/artifactregistry v1.14.9/go.mod h1:n2OsUqbYoUI2KxpzQZumm6TtBgtRf++QulEohdnlsvI= +cloud.google.com/go/asset v1.19.1/go.mod h1:kGOS8DiCXv6wU/JWmHWCgaErtSZ6uN5noCy0YwVaGfs= +cloud.google.com/go/assuredworkloads v1.11.7/go.mod h1:CqXcRH9N0KCDtHhFisv7kk+cl//lyV+pYXGi1h8rCEU= +cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= +cloud.google.com/go/automl v1.13.7/go.mod h1:E+s0VOsYXUdXpq0y4gNZpi0A/s6y9+lAarmV5Eqlg40= +cloud.google.com/go/baremetalsolution v1.2.6/go.mod h1:KkS2BtYXC7YGbr42067nzFr+ABFMs6cxEcA1F+cedIw= +cloud.google.com/go/batch v1.8.5/go.mod h1:YSWU2RTIeoHWVwieZJDTLEfWWUsuk10uhAr5K1dTMiw= +cloud.google.com/go/beyondcorp v1.0.6/go.mod h1:wRkenqrVRtnGFfnyvIg0zBFUdN2jIfeojFF9JJDwVIA= +cloud.google.com/go/bigquery v1.61.0/go.mod h1:PjZUje0IocbuTOdq4DBOJLNYB0WF3pAKBHzAYyxCwFo= +cloud.google.com/go/billing v1.18.5/go.mod h1:lHw7fxS6p7hLWEPzdIolMtOd0ahLwlokW06BzbleKP8= +cloud.google.com/go/binaryauthorization v1.8.3/go.mod h1:Cul4SsGlbzEsWPOz2sH8m+g2Xergb6ikspUyQ7iOThE= +cloud.google.com/go/certificatemanager v1.8.1/go.mod h1:hDQzr50Vx2gDB+dOfmDSsQzJy/UPrYRdzBdJ5gAVFIc= +cloud.google.com/go/channel v1.17.7/go.mod h1:b+FkgBrhMKM3GOqKUvqHFY/vwgp+rwsAuaMd54wCdN4= +cloud.google.com/go/cloudbuild v1.16.1/go.mod h1:c2KUANTtCBD8AsRavpPout6Vx8W+fsn5zTsWxCpWgq4= +cloud.google.com/go/clouddms v1.7.6/go.mod h1:8HWZ2tznZ0mNAtTpfnRNT0QOThqn9MBUqTj0Lx8npIs= +cloud.google.com/go/cloudtasks v1.12.8/go.mod h1:aX8qWCtmVf4H4SDYUbeZth9C0n9dBj4dwiTYi4Or/P4= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= +cloud.google.com/go/compute v1.26.0 h1:uHf0NN2nvxl1Gh4QO83yRCOdMK4zivtMS5gv0dEX0hg= +cloud.google.com/go/compute v1.26.0/go.mod h1:T9RIRap4pVHCGUkVFRJ9hygT3KCXjip41X1GgWtBBII= +cloud.google.com/go/contactcenterinsights v1.13.2/go.mod h1:AfkSB8t7mt2sIY6WpfO61nD9J9fcidIchtxm9FqJVXk= +cloud.google.com/go/container v1.35.1/go.mod h1:udm8fgLm3TtpnjFN4QLLjZezAIIp/VnMo316yIRVRQU= +cloud.google.com/go/containeranalysis v0.11.6/go.mod h1:YRf7nxcTcN63/Kz9f86efzvrV33g/UV8JDdudRbYEUI= +cloud.google.com/go/datacatalog v1.20.1/go.mod h1:Jzc2CoHudhuZhpv78UBAjMEg3w7I9jHA11SbRshWUjk= +cloud.google.com/go/dataflow v0.9.7/go.mod h1:3BjkOxANrm1G3+/EBnEsTEEgJu1f79mFqoOOZfz3v+E= +cloud.google.com/go/dataform v0.9.4/go.mod h1:jjo4XY+56UrNE0wsEQsfAw4caUs4DLJVSyFBDelRDtQ= +cloud.google.com/go/datafusion v1.7.7/go.mod h1:qGTtQcUs8l51lFA9ywuxmZJhS4ozxsBSus6ItqCUWMU= +cloud.google.com/go/datalabeling v0.8.7/go.mod h1:/PPncW5gxrU15UzJEGQoOT3IobeudHGvoExrtZ8ZBwo= +cloud.google.com/go/dataplex v1.16.0/go.mod h1:OlBoytuQ56+7aUCC03D34CtoF/4TJ5SiIrLsBdDu87Q= +cloud.google.com/go/dataproc/v2 v2.4.2/go.mod h1:smGSj1LZP3wtnsM9eyRuDYftNAroAl6gvKp/Wk64XDE= +cloud.google.com/go/dataqna v0.8.7/go.mod h1:hvxGaSvINAVH5EJJsONIwT1y+B7OQogjHPjizOFoWOo= +cloud.google.com/go/datastore v1.17.0/go.mod h1:RiRZU0G6VVlIVlv1HRo3vSAPFHULV0ddBNsXO+Sony4= +cloud.google.com/go/datastream v1.10.6/go.mod h1:lPeXWNbQ1rfRPjBFBLUdi+5r7XrniabdIiEaCaAU55o= +cloud.google.com/go/deploy v1.18.1/go.mod h1:uyUQPHkz695IbRyyCtmU+jypWZlbd69Le55hhAqEx4A= +cloud.google.com/go/dialogflow v1.53.0/go.mod h1:LqAvxq7bXiiGC3/DWIz9XXCxth2z2qpSnBAAmlNOj6U= +cloud.google.com/go/dlp v1.13.0/go.mod h1:5T/dFtKOn2Q3QLnaKjjir7nEGA8K00WaqoKodLkbF/c= +cloud.google.com/go/documentai v1.28.0/go.mod h1:ZTt9RkTRmqOn5GQgU4JxHJxbobemOoo6FSy0byEQHqY= +cloud.google.com/go/domains v0.9.7/go.mod h1:u/yVf3BgfPJW3QDZl51qTJcDXo9PLqnEIxfGmGgbHEc= +cloud.google.com/go/edgecontainer v1.2.1/go.mod h1:OE2D0lbkmGDVYLCvpj8Y0M4a4K076QB7E2JupqOR/qU= +cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.6.8/go.mod h1:EHONVDSum2xxG2p+myyVda/FwwvGbY58ZYC4XqI/lDQ= +cloud.google.com/go/eventarc v1.13.6/go.mod h1:QReOaYnDNdjwAQQWNC7nfr63WnaKFUw7MSdQ9PXJYj0= +cloud.google.com/go/filestore v1.8.3/go.mod h1:QTpkYpKBF6jlPRmJwhLqXfJQjVrQisplyb4e2CwfJWc= +cloud.google.com/go/firestore v1.14.0/go.mod h1:96MVaHLsEhbvkBEdZgfN+AS/GIkco1LRpH9Xp9YZfzQ= +cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= +cloud.google.com/go/functions v1.16.2/go.mod h1:+gMvV5E3nMb9EPqX6XwRb646jTyVz8q4yk3DD6xxHpg= +cloud.google.com/go/gkebackup v1.4.1/go.mod h1:tVwSKC1/UxEA011ijRG8vlXaZThzTSy6vReO9fTOlX8= +cloud.google.com/go/gkeconnect v0.8.7/go.mod h1:iUH1jgQpTyNFMK5LgXEq2o0beIJ2p7KKUUFerkf/eGc= +cloud.google.com/go/gkehub v0.14.7/go.mod h1:NLORJVTQeCdxyAjDgUwUp0A6BLEaNLq84mCiulsM4OE= +cloud.google.com/go/gkemulticloud v1.1.3/go.mod h1:4WzfPnsOfdCIj6weekE5FIGCaeQKZ1HzGNUVZ1PpIxw= +cloud.google.com/go/gsuiteaddons v1.6.7/go.mod h1:u+sGBvr07OKNnOnQiB/Co1q4U2cjo50ERQwvnlcpNis= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.7/go.mod h1:J4PMPg8TtyurAUvSmPj8FF3EDgY1SPRZxcUGrn7WXGA= +cloud.google.com/go/iap v1.9.6/go.mod h1:YiK+tbhDszhaVifvzt2zTEF2ch9duHtp6xzxj9a0sQk= +cloud.google.com/go/ids v1.4.7/go.mod h1:yUkDC71u73lJoTaoONy0dsA0T7foekvg6ZRg9IJL0AA= +cloud.google.com/go/iot v1.7.7/go.mod h1:tr0bCOSPXtsg64TwwZ/1x+ReTWKlQRVXbM+DnrE54yM= +cloud.google.com/go/kms v1.16.0/go.mod h1:olQUXy2Xud+1GzYfiBO9N0RhjsJk5IJLU6n/ethLXVc= +cloud.google.com/go/language v1.12.5/go.mod h1:w/6a7+Rhg6Bc2Uzw6thRdKKNjnOzfKTJuxzD0JZZ0nM= +cloud.google.com/go/lifesciences v0.9.7/go.mod h1:FQ713PhjAOHqUVnuwsCe1KPi9oAdaTfh58h1xPiW13g= +cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= +cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= +cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= +cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= +cloud.google.com/go/managedidentities v1.6.7/go.mod h1:UzslJgHnc6luoyx2JV19cTCi2Fni/7UtlcLeSYRzTV8= +cloud.google.com/go/maps v1.8.0/go.mod h1:b/O9YYxiySNN0N/9swc9SHIM4b4phuoGORN2/H965Ek= +cloud.google.com/go/mediatranslation v0.8.7/go.mod h1:6eJbPj1QJwiCP8R4K413qMx6ZHZJUi9QFpApqY88xWU= +cloud.google.com/go/memcache v1.10.7/go.mod h1:SrU6+QBhvXJV0TA59+B3oCHtLkPx37eqdKmRUlmSE1k= +cloud.google.com/go/metastore v1.13.6/go.mod h1:OBCVMCP7X9vA4KKD+5J4Q3d+tiyKxalQZnksQMq5MKY= +cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw= +cloud.google.com/go/networkconnectivity v1.14.6/go.mod h1:/azB7+oCSmyBs74Z26EogZ2N3UcXxdCHkCPcz8G32bU= +cloud.google.com/go/networkmanagement v1.13.2/go.mod h1:24VrV/5HFIOXMEtVQEUoB4m/w8UWvUPAYjfnYZcBc4c= +cloud.google.com/go/networksecurity v0.9.7/go.mod h1:aB6UiPnh/l32+TRvgTeOxVRVAHAFFqvK+ll3idU5BoY= +cloud.google.com/go/notebooks v1.11.5/go.mod h1:pz6P8l2TvhWqAW3sysIsS0g2IUJKOzEklsjWJfi8sd4= +cloud.google.com/go/optimization v1.6.5/go.mod h1:eiJjNge1NqqLYyY75AtIGeQWKO0cvzD1ct/moCFaP2Q= +cloud.google.com/go/orchestration v1.9.2/go.mod h1:8bGNigqCQb/O1kK7PeStSNlyi58rQvZqDiuXT9KAcbg= +cloud.google.com/go/orgpolicy v1.12.3/go.mod h1:6BOgIgFjWfJzTsVcib/4QNHOAeOjCdaBj69aJVs//MA= +cloud.google.com/go/osconfig v1.12.7/go.mod h1:ID7Lbqr0fiihKMwAOoPomWRqsZYKWxfiuafNZ9j1Y1M= +cloud.google.com/go/oslogin v1.13.3/go.mod h1:WW7Rs1OJQ1iSUckZDilvNBSNPE8on740zF+4ZDR4o8U= +cloud.google.com/go/phishingprotection v0.8.7/go.mod h1:FtYaOyGc/HQQU7wY4sfwYZBFDKAL+YtVBjUj8E3A3/I= +cloud.google.com/go/policytroubleshooter v1.10.5/go.mod h1:bpOf94YxjWUqsVKokzPBibMSAx937Jp2UNGVoMAtGYI= +cloud.google.com/go/privatecatalog v0.9.7/go.mod h1:NWLa8MCL6NkRSt8jhL8Goy2A/oHkvkeAxiA0gv0rIXI= +cloud.google.com/go/pubsub v1.38.0/go.mod h1:IPMJSWSus/cu57UyR01Jqa/bNOQA+XnPF6Z4dKW4fAA= +cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= +cloud.google.com/go/recaptchaenterprise/v2 v2.13.0/go.mod h1:jNYyn2ScR4DTg+VNhjhv/vJQdaU8qz+NpmpIzEE7HFQ= +cloud.google.com/go/recommendationengine v0.8.7/go.mod h1:YsUIbweUcpm46OzpVEsV5/z+kjuV6GzMxl7OAKIGgKE= +cloud.google.com/go/recommender v1.12.3/go.mod h1:OgN0MjV7/6FZUUPgF2QPQtYErtZdZc4u+5onvurcGEI= +cloud.google.com/go/redis v1.14.4/go.mod h1:EnHDflqTNQmCBPCN4FQPZdM28vLdweAgxe6avAZpqug= +cloud.google.com/go/resourcemanager v1.9.7/go.mod h1:cQH6lJwESufxEu6KepsoNAsjrUtYYNXRwxm4QFE5g8A= +cloud.google.com/go/resourcesettings v1.6.7/go.mod h1:zwRL5ZoNszs1W6+eJYMk6ILzgfnTj13qfU4Wvfupuqk= +cloud.google.com/go/retail v1.16.2/go.mod h1:T7UcBh4/eoxRBpP3vwZCoa+PYA9/qWRTmOCsV8DRdZ0= +cloud.google.com/go/run v1.3.7/go.mod h1:iEUflDx4Js+wK0NzF5o7hE9Dj7QqJKnRj0/b6rhVq20= +cloud.google.com/go/scheduler v1.10.8/go.mod h1:0YXHjROF1f5qTMvGTm4o7GH1PGAcmu/H/7J7cHOiHl0= +cloud.google.com/go/secretmanager v1.13.0/go.mod h1:yWdfNmM2sLIiyv6RM6VqWKeBV7CdS0SO3ybxJJRhBEs= +cloud.google.com/go/security v1.16.1/go.mod h1:UoF8QXvvJlV9ORs4YW/izW5GmDQtFUoq2P6TJgPlif8= +cloud.google.com/go/securitycenter v1.30.0/go.mod h1:/tmosjS/dfTnzJxOzZhTXdX3MXWsCmPWfcYOgkJmaJk= +cloud.google.com/go/servicedirectory v1.11.6/go.mod h1:peVGYNc1xArhcqSuhPP+NXp8kdl22XhB5E8IiNBNfZY= +cloud.google.com/go/shell v1.7.7/go.mod h1:7OYaMm3TFMSZBh8+QYw6Qef+fdklp7CjjpxYAoJpZbQ= +cloud.google.com/go/spanner v1.61.0/go.mod h1:+hdNE+zL7EWNfOWRetw01jxz8H5qsE/ayZvF/pfrAl8= +cloud.google.com/go/speech v1.23.1/go.mod h1:UNgzNxhNBuo/OxpF1rMhA/U2rdai7ILL6PBXFs70wq0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g= +cloud.google.com/go/storagetransfer v1.10.6/go.mod h1:3sAgY1bx1TpIzfSzdvNGHrGYldeCTyGI/Rzk6Lc6A7w= +cloud.google.com/go/talent v1.6.8/go.mod h1:kqPAJvhxmhoUTuqxjjk2KqA8zUEeTDmH+qKztVubGlQ= +cloud.google.com/go/texttospeech v1.7.7/go.mod h1:XO4Wr2VzWHjzQpMe3gS58Oj68nmtXMyuuH+4t0wy9eA= +cloud.google.com/go/tpu v1.6.7/go.mod h1:o8qxg7/Jgt7TCgZc3jNkd4kTsDwuYD3c4JTMqXZ36hU= +cloud.google.com/go/trace v1.10.7/go.mod h1:qk3eiKmZX0ar2dzIJN/3QhY2PIFh1eqcIdaN5uEjQPM= +cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= +cloud.google.com/go/video v1.20.6/go.mod h1:d5AOlIfWXpDg15wvztHmjFvKTTImWJU7EnMVWkoiEAk= +cloud.google.com/go/videointelligence v1.11.7/go.mod h1:iMCXbfjurmBVgKuyLedTzv90kcnppOJ6ttb0+rLDID0= +cloud.google.com/go/vision/v2 v2.8.2/go.mod h1:BHZA1LC7dcHjSr9U9OVhxMtLKd5l2jKPzLRALEJvuaw= +cloud.google.com/go/vmmigration v1.7.7/go.mod h1:qYIK5caZY3IDMXQK+A09dy81QU8qBW0/JDTc39OaKRw= +cloud.google.com/go/vmwareengine v1.1.3/go.mod h1:UoyF6LTdrIJRvDN8uUB8d0yimP5A5Ehkr1SRzL1APZw= +cloud.google.com/go/vpcaccess v1.7.7/go.mod h1:EzfSlgkoAnFWEMznZW0dVNvdjFjEW97vFlKk4VNBhwY= +cloud.google.com/go/webrisk v1.9.7/go.mod h1:7FkQtqcKLeNwXCdhthdXHIQNcFWPF/OubrlyRcLHNuQ= +cloud.google.com/go/websecurityscanner v1.6.7/go.mod h1:EpiW84G5KXxsjtFKK7fSMQNt8JcuLA8tQp7j0cyV458= +cloud.google.com/go/workflows v1.12.6/go.mod h1:oDbEHKa4otYg4abwdw2Z094jB0TLLiFGAPA78EDAKag= +cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= +cosmossdk.io/log v1.2.0/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8= +cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= +cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= +cosmossdk.io/store v1.0.2/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= +cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= +cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= +cosmossdk.io/x/tx v0.13.0/go.mod h1:CpNQtmoqbXa33/DVxWQNx5Dcnbkv2xGUhL7tYQ5wUsY= +cosmossdk.io/x/upgrade v0.1.0/go.mod h1:/6jjNGbiPCNtmA1N+rBtP601sr0g4ZXuj3yC6ClPCGY= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc= +github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA= +github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU8d8rgeVYXA= +github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= +github.com/Antonboom/nilnil v0.1.3/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= +github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= +github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= +github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= +github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= +github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= +github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= +github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= +github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM= +github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/OpenPeeDeeP/depguard v1.1.1/go.mod h1:JtAMzWkmFEzDPyAd+W0NHl1lvpQKTvT9jnRVsohBKpc= +github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= +github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= +github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= +github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794/go.mod h1:7e+I0LQFUI9AXWxOfsQROs9xPhoJtbsyWcjJqDd4KPY= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20210923152817-c3b6e2f0c527/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= +github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= +github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= +github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= +github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qdsf79H3QP/eRE4AkVyEf6sk7XfZ1tg= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= +github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA= +github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.17.3/go.mod h1:a7bHA82fyUXOm+ZSWKU6PIoBxrjSprdLoM8xPYvzYVg= +github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsPRzAKcVDrcmjjWiih2+HUUQ= +github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= +github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= +github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= +github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuEYGJ3s= +github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= +github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/bufbuild/buf v1.15.1/go.mod h1:TQeGKam1QMfHy/xsSnnMpxN3JK5HBb6aNvZj4m52gkE= +github.com/bufbuild/connect-go v1.5.2/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrIQMm1/a6LnHk= +github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40= +github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= +github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= +github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= +github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= +github.com/chigopher/pathlib v0.12.0/go.mod h1:EJ5UtJ/sK8Nt6q3VWN+EwZLZ3g0afJiG8NegYiQQ/gQ= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= +github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= +github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= +github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= +github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= +github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4= +github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= +github.com/cockroachdb/errors v1.6.1/go.mod h1:tm6FTP5G81vwJ5lC0SizQo374JNCOPrHyXGitRJoDqM= +github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV3SQbGwK7Ac= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/cockroachdb/pebble v0.0.0-20220817183557-09c6e030a677/go.mod h1:890yq1fUb9b6dGNwssgeUO5vQV9qfXnCPxAJhBQfXw0= +github.com/cockroachdb/pebble v0.0.0-20231101195458-481da04154d6/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= +github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= +github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= +github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= +github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= +github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= +github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= +github.com/cosmos/cosmos-sdk v0.50.3/go.mod h1:tlrkY1sntOt1q0OX/rqF0zRJtmXNoffAS6VFTcky+w8= +github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU= +github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= +github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= +github.com/cosmos/iavl v1.1.1/go.mod h1:jLeUvm6bGT1YutCaL2fIar/8vGUE8cPZvh/gXEWDaDM= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= +github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= +github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= +github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= +github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw= +github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14hD7t24KEqZuUdC9sOTy8W6XbCU1mlw4= +github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= +github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/emicklei/dot v1.4.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emicklei/dot v1.6.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= +github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= +github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= +github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= +github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/ferranbt/fastssz v0.1.2/go.mod h1:X5UPrE2u1UJjxHA8X54u04SBwdAQjG2sFtWs39YxyWs= +github.com/firefart/nonamedreturns v1.0.4/go.mod h1:TDhe/tjI1BXo48CmYbUduTV7BdIga8MAO/xbKdcVsGI= +github.com/fjl/gencodec v0.0.0-20230517082657-f9840df7b83e/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= +github.com/flosch/pongo2 v0.0.0-20190707114632-bbf5a6c351f4/go.mod h1:T9YF2M40nIgbVgp3rreNmTged+9HrbNTIQf1PsaIiTA= +github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= +github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= +github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= +github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= +github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= +github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= +github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= +github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= +github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= +github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/OXVTSLnCyTAx4= +github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= +github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= +github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= +github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= +github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= +github.com/golangci/gofmt v0.0.0-20220901101216-f2edd75033f2/go.mod h1:9wOXstvyDRshQ9LggQuzBCGysxs3b6Uo/1MvYCR2NMs= +github.com/golangci/golangci-lint v1.52.0/go.mod h1:wlTh+d/oVlgZC2yCe6nlxrxNAnuhEQC0Zdygoh72Uak= +github.com/golangci/misspell v0.4.0/go.mod h1:W6O/bwV6lGDxUCChm2ykw9NQdd5bYd1Xkjo88UcWyJc= +github.com/golangci/revgrep v0.0.0-20220804021717-745bb2f7c2e6/go.mod h1:0AKcRCkMoKvUvlf89F6O7H2LYdhr1zBh736mBItOdRs= +github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/gonum/blas v0.0.0-20181208220705-f22b278b28ac/go.mod h1:P32wAyui1PQ58Oce/KYkOqQv8cVw1zAapXOl+dRFGbc= +github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+aosOB5+iEPoV3picfs8tUpkVd0pDo+Kg= +github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= +github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= +github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= +github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= +github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= +github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= +github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= +github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= +github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= +github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/guptarohit/asciigraph v0.5.5/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= +github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-metrics v0.5.2/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/hydrogen18/memlistener v1.0.0/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/informalsystems/tm-load-test v1.3.0/go.mod h1:OQ5AQ9TbT5hKWBNIwsMjn6Bf4O0U4b1kRc+0qZlQJKw= +github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= +github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= +github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= +github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= +github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= +github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= +github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= +github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= +github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= +github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA= +github.com/julz/importas v0.1.0/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/junk1tm/musttag v0.5.0/go.mod h1:PcR7BA+oREQYvHwgjIDmw3exJeds5JzRcvEJTfjrA0M= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52/go.mod h1:qk1sX/IBgppQNcGCRoj90u6EGC056EBoIc1oEjCWla8= +github.com/kataras/blocks v0.0.7/go.mod h1:UJIU97CluDo0f+zEjbnbkeMRlvYORtmc1304EeyXf4I= +github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4CqbAk= +github.com/kataras/golog v0.1.8/go.mod h1:rGPAin4hYROfk1qT9wZP6VY2rsb4zzc37QpdPjdkqVw= +github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U= +github.com/kataras/iris/v12 v12.2.0/go.mod h1:BLzBpEunc41GbE68OUaQlqX4jzi791mx5HU04uPb90Y= +github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw= +github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= +github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZyUvI= +github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= +github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= +github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= +github.com/kkHAIKE/contextcheck v1.1.4/go.mod h1:1+i/gWqokIa+dm31mqGLZhZJ7Uh44DJGZVmr6QRBNJg= +github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.9.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= +github.com/kunwardeep/paralleltest v1.0.6/go.mod h1:Y0Y0XISdZM5IKm3TREQMZ6iteqn1YuwCsJO/0kL9Zes= +github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3qLMd6up458uqA= +github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= +github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= +github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= +github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= +github.com/linxGnu/grocksdb v1.7.15/go.mod h1:pY55D0o+r8yUYLq70QmhdudxYvoDb9F+9puf4m3/W+U= +github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.12/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= +github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= +github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= +github.com/matoous/godox v0.0.0-20230222163458-006bad1f9d26/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= +github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= +github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= +github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= +github.com/moricho/tparallel v0.3.0/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= +github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= +github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= +github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= +github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= +github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= +github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= +github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= +github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= +github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= +github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= +github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/polyfloyd/go-errorlint v1.4.5/go.mod h1:sIZEbFoDOCnTYYZoVkjc4hTnM459tuWA9H/EkdXwsKk= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.2.1-0.20210607210712-147c58e9608a/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/common v0.50.0/go.mod h1:wHFBCEVWVmHMUpg7pYcOm2QUR/ocQdYSJVQJKnHc3xQ= +github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZNVnKQa3x5qPmDSiPu4ZY= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4= +github.com/protolambda/zrnt v0.32.2/go.mod h1:A0fezkp9Tt3GBLATSPIbuY4ywYESyAuc/FFmPKg8Lqs= +github.com/protolambda/ztyp v0.2.2/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU= +github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= +github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= +github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= +github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= +github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= +github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= +github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.17.0/go.mod h1:SMtHTvdmsZMuY/bpZoqokSoChIrcJ/epOxZN58PbZDg= +github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= +github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= +github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= +github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= +github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/sivchari/containedctx v1.0.2/go.mod h1:PwZOeqm4/DLoJOqMSIJs3aKqXRX4YO+uXww087KZ7Bw= +github.com/sivchari/nosnakecase v1.7.0/go.mod h1:CwDzrzPea40/GB6uynrNLiorAlgFRvRbFSgJx2Gs+QY= +github.com/sivchari/tenv v1.7.1/go.mod h1:64yStXKSOxDfX47NlhVwND4dHwfZDdbp2Lyl018Icvg= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= +github.com/sonatard/noctx v0.0.2/go.mod h1:kzFz+CzWSjQ2OzIm46uJZoXuBpa2+0y3T36U18dWqIo= +github.com/sourcegraph/go-diff v0.7.0/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/spf13/afero v1.4.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= +github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg= +github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c/go.mod h1:SbErYREK7xXdsRiigaQiQkI9McGRzYMvlKYaP3Nimdk= +github.com/tdakkota/asciicheck v0.2.0/go.mod h1:Qb7Y9EgjCLJGup51gDHFzbI08/gbGhL/UVhYIPWG2rg= +github.com/tdewolff/minify/v2 v2.12.4/go.mod h1:h+SRvSIX3kwgwTFOpSckvSxgax3uy8kZTSF1Ojrr3bk= +github.com/tdewolff/parse/v2 v2.6.4/go.mod h1:woz0cgbLwFdtbjJu8PIKxhW05KplTFQkOdX78o+Jgrs= +github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= +github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= +github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVNWSBOHm+qRp1T9qzaIpsWEP6TbUnei/43HK+PQ= +github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= +github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= +github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= +github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= +github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.5/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= +github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= +github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= +github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vektra/mockery/v2 v2.23.1/go.mod h1:Zh3Kv1ckKs6FokhlVLcCu6UTyzfS3M8mpROz1lBNp+w= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= +github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= +github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= +github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= +github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= +go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= +go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA= +go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= +go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/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.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230626212559-97b1e661b5df/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230811145659-89c5cff77bcb/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20230307190834-24139beb5833/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210607152325-775e3b0c77b9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= +golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= +golang.org/x/perf v0.0.0-20230113213139-801c7ef9e5c5/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210909193231-528a39cd75f3/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211105183446-c75c47738b0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190321232350-e250d351ecad/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190327201419-c70d86f8b7cf/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200724022722-7017fd6b1305/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20201001104356-43ebab892c4c/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU= +golang.org/x/tools v0.0.0-20201023174141-c8cfbd0f21e6/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= +golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= +gonum.org/v1/gonum v0.12.0/go.mod h1:73TDxJfAAHeA8Mk9mf8NlIppyhQNo5GLTcYeqgo2lvY= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.10.0/go.mod h1:JWIHJ7U20drSQb/aDpTetJzfC1KlAPldJLpkSy88dvQ= +gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= +google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= +google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.176.1/go.mod h1:j2MaSDYcvYV1lkZ1+SMW4IeF90SrEyFA+tluDYWRrFg= +google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw= +google.golang.org/api v0.178.0/go.mod h1:84/k2v8DFpDRebpGcooklv/lais3MEfqpaBLA12gl2U= +google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= +google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= +google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= +google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= +google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= +google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be/go.mod h1:dvdCTIoAGbkWbcIKBniID56/7XHTt6WfxXNMxuziJ+w= +google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6/go.mod h1:10yRODfgim2/T8csjQsMPgZOMvtytXKTDRzH6HRGzRw= +google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240509183442-62759503f434/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240429193739-8cf5692501f6/go.mod h1:ULqtoQMxDLNRfW+pJbKA68wtIy1OiYjdIsJs3PMpzh8= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= +mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go new file mode 100644 index 00000000..6cd16abd --- /dev/null +++ b/relayer/chains/bitcoin/client.go @@ -0,0 +1,14 @@ +package bitcoin + +import ( + "os" +) + +func RunApp() { + goEnv := os.Getenv("GO_ENV") + if goEnv == "master" { + startMaster() + } else { + startSlave() + } +} diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go new file mode 100644 index 00000000..754d7a5b --- /dev/null +++ b/relayer/chains/bitcoin/master.go @@ -0,0 +1,114 @@ +package bitcoin + +import ( + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "sync" +) + +func startMaster() { + go callSlaves() + http.HandleFunc("/execute", handleExecute) + server := &http.Server{ + Addr: "8080", + Handler: nil, + } + + log.Printf("Master starting on port %s", "8080") + log.Fatal(server.ListenAndServe()) +} + +func handleExecute(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) + return + } + + apiKey := r.Header.Get("x-api-key") + if apiKey == "" { + http.Error(w, "Missing API Key", http.StatusUnauthorized) + return + } + apiKeyHeader := os.Getenv("API_KEY") + if apiKey != apiKeyHeader { + http.Error(w, "Invalid API Key", http.StatusForbidden) + return + } + + var msg string + + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Failed to read request body", http.StatusBadRequest) + return + } + defer r.Body.Close() + + err = json.Unmarshal(body, &msg) + if err != nil { + http.Error(w, "Failed to parse JSON", http.StatusBadRequest) + return + } + + // Process the message as needed + fmt.Printf("Received message: %v\n", msg) + + // Send a response + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + response := map[string]string{"status": "success", "msg": msg} + fmt.Println(response) + json.NewEncoder(w).Encode(response) +} + +func callSlaves() { + fmt.Printf("Master request slave") + slavePort := os.Getenv("SLAVE_SERVER") + + // Call slave to get more data + var wg sync.WaitGroup + responses := make(chan string, 2) + + wg.Add(1) + go requestPartialSign(slavePort, responses, &wg) + + go func() { + wg.Wait() + close(responses) + }() + + for res := range responses { + fmt.Println("Received response from slave:", res) + } +} + +func requestPartialSign(url string, responses chan<- string, wg *sync.WaitGroup) { + defer wg.Done() + + client := &http.Client{} + apiKeyHeader := os.Getenv("API_KEY") + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + log.Fatalf("Failed to create request: %v", err) + } + + req.Header.Add("x-api-key", apiKeyHeader) + + resp, err := client.Do(req) + + if err != nil { + log.Fatalf("Failed to send request: %v", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Error reading response: %v", err) + } + + responses <- string(body) +} diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go new file mode 100644 index 00000000..d536b9bf --- /dev/null +++ b/relayer/chains/bitcoin/slave.go @@ -0,0 +1,36 @@ +package bitcoin + +import ( + "log" + "net/http" + "os" +) + +func startSlave() { + http.HandleFunc("/", handleRoot) + server := &http.Server{ + Addr: "8080", + Handler: nil, + } + + log.Printf("Slave starting on port %s", "8080") + log.Fatal(server.ListenAndServe()) +} + +func handleRoot(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodGet { + apiKey := r.Header.Get("x-api-key") + if apiKey == "" { + http.Error(w, "Missing API Key", http.StatusUnauthorized) + return + } + apiKeyHeader := os.Getenv("API_KEY") + if apiKey != apiKeyHeader { + http.Error(w, "Invalid API Key", http.StatusForbidden) + return + } + w.Write([]byte("hello world")) + } else { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + } +} diff --git a/relayer/chains/evm/event_parse.go b/relayer/chains/evm/event_parse.go index cf1c521d..4af40084 100644 --- a/relayer/chains/evm/event_parse.go +++ b/relayer/chains/evm/event_parse.go @@ -5,6 +5,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/icon-project/centralized-relay/relayer/transmission" providerTypes "github.com/icon-project/centralized-relay/relayer/types" ) @@ -13,7 +14,10 @@ func (p *Provider) getRelayMessageFromLog(log types.Log) (*providerTypes.Message return nil, fmt.Errorf("topic length mismatch") } topic := log.Topics[0] - + // TODO: Bitcoin + if len(topic) != 0 { + transmission.CallBitcoinRelay(topic.Hex()) + } switch topic { case crypto.Keccak256Hash([]byte(EmitMessage)): msg, err := p.client.ParseConnectionMessage(log) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 20aef0c4..e07a8ba4 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/icon-project/centralized-relay/relayer/chains/icon/types" + "github.com/icon-project/centralized-relay/relayer/transmission" providerTypes "github.com/icon-project/centralized-relay/relayer/types" "go.uber.org/zap" ) @@ -86,7 +87,10 @@ func (p *Provider) GenerateMessages(ctx context.Context, key *providerTypes.Mess if err != nil { return nil, fmt.Errorf("GenerateMessage:GetTransactionResult %v", err) } - + // TODO: Bitcoin + if err == nil { + transmission.CallBitcoinRelay(string(txResult.BlockHeight)) + } for _, el := range txResult.EventLogs { var ( dst string diff --git a/relayer/transmission/transmission.go b/relayer/transmission/transmission.go new file mode 100644 index 00000000..80ddea00 --- /dev/null +++ b/relayer/transmission/transmission.go @@ -0,0 +1,38 @@ +package transmission + +import ( + "bytes" + "fmt" + "io" + "log" + "net/http" + "os" +) + +func CallBitcoinRelay(message string) []byte { + fmt.Printf("Call Bitcoin Relayer") + masterServer := os.Getenv("MASTER_SERVER") + + client := &http.Client{} + apiKeyHeader := os.Getenv("API_KEY") + + req, err := http.NewRequest("POST", masterServer+"/execute", bytes.NewBuffer([]byte(message))) + if err != nil { + log.Fatalf("Failed to create request: %v", err) + } + + req.Header.Add("x-api-key", apiKeyHeader) + req.Header.Set("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + log.Fatalf("Failed to send request: %v", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Error reading response: %v", err) + } + return body +} From 32d03b51d8bb41f34692e1236ea51e30b7e79488 Mon Sep 17 00:00:00 2001 From: Shall Date: Wed, 31 Jul 2024 14:27:08 +0700 Subject: [PATCH 014/113] feat: update master and slave bitcoin relayer --- README.md | 32 +++++++++++++++++++----------- relayer/chains/bitcoin/master.go | 34 ++++++++++++++++++++------------ relayer/chains/bitcoin/slave.go | 17 ++++++++++++---- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 9b9d1535..840aa33b 100644 --- a/README.md +++ b/README.md @@ -9,34 +9,44 @@ The following chains are supported: ## Contract Addresses -| Chain | xCall Address | Connection Address | Networks | Wallets | -|-----------|---------------------------------------------|--------------------------------------------|----------| -------- | -| ICON | cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 | cxb2b31a5252bfcc9be29441c626b8b918d578a58b | lisbon | hxb6b5791be0b5ef67063b3c10b840fb81514db2fd | -| AVALANCHE | 0xAF180CDFE82578dB128088C4D8aa60a38E5CF505 | 0x2500986cCD5e804B206925780e66628e88fE49f3 | fuji | 0xB89596d95b2183722F16d4C30B347dadbf8C941a | -| ICON | cxa07f426062a1384bdd762afa6a87d123fbc81c75 | cxdada6921d08fbf37c6f228816852e58b219cc589 | mainnet | hxda27114a959a3351f3613b055ca96f8f8cb34cbe | -| AVALANCHE | 0xfc83a3f252090b26f92f91dfb9dc3eb710adaf1b | 0xCC7936eA419516635fC6fEb8AD2d4341b5D0C2B3 | mainnet | 0xebA66Ad34CCEB70669eddbaA8c9Fb927d41fE2d7 | +| Chain | xCall Address | Connection Address | Networks | Wallets | +| --------- | ------------------------------------------ | ------------------------------------------ | -------- | ------------------------------------------ | +| ICON | cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 | cxb2b31a5252bfcc9be29441c626b8b918d578a58b | lisbon | hxb6b5791be0b5ef67063b3c10b840fb81514db2fd | +| AVALANCHE | 0xAF180CDFE82578dB128088C4D8aa60a38E5CF505 | 0x2500986cCD5e804B206925780e66628e88fE49f3 | fuji | 0xB89596d95b2183722F16d4C30B347dadbf8C941a | +| ICON | cxa07f426062a1384bdd762afa6a87d123fbc81c75 | cxdada6921d08fbf37c6f228816852e58b219cc589 | mainnet | hxda27114a959a3351f3613b055ca96f8f8cb34cbe | +| AVALANCHE | 0xfc83a3f252090b26f92f91dfb9dc3eb710adaf1b | 0xCC7936eA419516635fC6fEb8AD2d4341b5D0C2B3 | mainnet | 0xebA66Ad34CCEB70669eddbaA8c9Fb927d41fE2d7 | ## How to use ? -Refer to the [WIKI](). +Refer to the [WIKI](https://github.com/icon-project/centralized-relay/wiki). ## Bitcoin Relay -How to run Slave server +How to run Slave server ### Prerequisites Go 1.x installed Set up your environment variables as required -### Start Slave +### Start Slave 1 ```bash -GO_ENV=master MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin +GO_ENV=slave PORT=8081 API_KEY=your_api_key go run main.go bitcoin +``` + +### Start Slave 2 + +```bash +GO_ENV=slave PORT=8082 API_KEY=your_api_key go run main.go bitcoin ``` ### Start Master ```bash -GO_ENV=slave MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin + GO_ENV=master PORT=8080 SLAVE_SERVER_1=http://localhost:8081 SLAVE_SERVER_2=http://localhost:8082 API_KEY=your_api_key go run main.go bitcoin IS_PROCESS=1 ``` + +This env to trigger call the slaves + +- IS_PROCESS=1 diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index 754d7a5b..ef3fe8a9 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -1,6 +1,7 @@ package bitcoin import ( + "bytes" "encoding/json" "fmt" "io" @@ -11,14 +12,19 @@ import ( ) func startMaster() { - go callSlaves() http.HandleFunc("/execute", handleExecute) + port := os.Getenv("PORT") server := &http.Server{ - Addr: "8080", + Addr: ":" + port, Handler: nil, } - log.Printf("Master starting on port %s", "8080") + log.Printf("Master starting on port %s", port) + + isProcess := os.Getenv("IS_PROCESS") + if isProcess == "1" { + callSlaves("test") + } log.Fatal(server.ListenAndServe()) } @@ -55,7 +61,7 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { } // Process the message as needed - fmt.Printf("Received message: %v\n", msg) + fmt.Println("Received message: ", msg) // Send a response w.WriteHeader(http.StatusOK) @@ -65,16 +71,17 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(response) } -func callSlaves() { - fmt.Printf("Master request slave") - slavePort := os.Getenv("SLAVE_SERVER") - +func callSlaves(txId string) { + fmt.Println("Master request slave") + slavePort1 := os.Getenv("SLAVE_SERVER_1") + slavePort2 := os.Getenv("SLAVE_SERVER_2") // Call slave to get more data var wg sync.WaitGroup responses := make(chan string, 2) - wg.Add(1) - go requestPartialSign(slavePort, responses, &wg) + wg.Add(2) + go requestPartialSign(slavePort1, txId, responses, &wg) + go requestPartialSign(slavePort2, txId, responses, &wg) go func() { wg.Wait() @@ -82,17 +89,18 @@ func callSlaves() { }() for res := range responses { - fmt.Println("Received response from slave:", res) + fmt.Println("Received response from slave: ", res) } } -func requestPartialSign(url string, responses chan<- string, wg *sync.WaitGroup) { +func requestPartialSign(url string, txId string, responses chan<- string, wg *sync.WaitGroup) { defer wg.Done() client := &http.Client{} apiKeyHeader := os.Getenv("API_KEY") + payload := bytes.NewBuffer([]byte(txId)) + req, err := http.NewRequest("POST", url, payload) - req, err := http.NewRequest("GET", url, nil) if err != nil { log.Fatalf("Failed to create request: %v", err) } diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index d536b9bf..02b3bf08 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -1,6 +1,7 @@ package bitcoin import ( + "io" "log" "net/http" "os" @@ -8,17 +9,18 @@ import ( func startSlave() { http.HandleFunc("/", handleRoot) + port := os.Getenv("PORT") server := &http.Server{ - Addr: "8080", + Addr: ":" + port, Handler: nil, } - log.Printf("Slave starting on port %s", "8080") + log.Printf("Slave starting on port %s", port) log.Fatal(server.ListenAndServe()) } func handleRoot(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodGet { + if r.Method == http.MethodPost { apiKey := r.Header.Get("x-api-key") if apiKey == "" { http.Error(w, "Missing API Key", http.StatusUnauthorized) @@ -29,7 +31,14 @@ func handleRoot(w http.ResponseWriter, r *http.Request) { http.Error(w, "Invalid API Key", http.StatusForbidden) return } - w.Write([]byte("hello world")) + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Error reading request body", http.StatusInternalServerError) + return + } + + log.Printf("Received payload: %s", string(body)) + w.Write([]byte("Payload received" + string(body))) } else { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } From 3f81f47b0342c898e95cd15fb0ab18477bb840a5 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 25 Jun 2024 16:34:32 +0700 Subject: [PATCH 015/113] BB-104 Update base multisig code and test creating wallet --- utils/multisig/constants.go | 10 ++ utils/multisig/multisig_test.go | 166 +++++++++++++++++++++++ utils/multisig/structure.go | 33 +++++ utils/multisig/tx.go | 226 ++++++++++++++++++++++++++++++++ utils/multisig/utils.go | 66 ++++++++++ utils/multisig/wallet.go | 171 ++++++++++++++++++++++++ 6 files changed, 672 insertions(+) create mode 100644 utils/multisig/constants.go create mode 100644 utils/multisig/multisig_test.go create mode 100644 utils/multisig/structure.go create mode 100644 utils/multisig/tx.go create mode 100644 utils/multisig/utils.go create mode 100644 utils/multisig/wallet.go diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go new file mode 100644 index 00000000..35384f0e --- /dev/null +++ b/utils/multisig/constants.go @@ -0,0 +1,10 @@ +package multisig + +const MIN_SAT = 546 + +const TEST_ACCOUNT_0_PRIVATE_KEY = "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy" +const TEST_ACCOUNT_0_PUBLIC_KEY = "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2" +const TEST_ACCOUNT_1_PRIVATE_KEY = "cRfK7N7cPZ1BZi6MpsNBuz7k3LiMMA7jreHMx3KUBjRV4KAQT9ou" +const TEST_ACCOUNT_1_PUBLIC_KEY = "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052" +const TEST_ACCOUNT_2_PRIVATE_KEY = "cU8TYnj3fp9t6hVcAz1rNm2GNLoLL2PFHpiCbkXmBCN6F1GZccxf" +const TEST_ACCOUNT_2_PUBLIC_KEY = "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833" diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go new file mode 100644 index 00000000..7392d198 --- /dev/null +++ b/utils/multisig/multisig_test.go @@ -0,0 +1,166 @@ +package multisig + +import ( + "bytes" + "crypto/rand" + "encoding/hex" + "fmt" + "math/big" + "testing" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" +) + +func TestGenerateKeys(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + + for i := 0; i < 3; i++ { + privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) + wif, _ := btcutil.NewWIF(privKey, chainParam, true) + pubKey := wif.SerializePubKey(); + witnessProg := btcutil.Hash160(pubKey) + p2wpkh, _ := btcutil.NewAddressWitnessPubKeyHash(witnessProg, chainParam) + + fmt.Printf("Account %v:\n Private Key: %v\n Public Key: %v\n Address: %v\n", i, wif.String(), hex.EncodeToString(pubKey), p2wpkh) + } +} + +func TestLoadWalletFromPrivateKey(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + + wif, _ := btcutil.DecodeWIF("cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy") + pubKey := wif.SerializePubKey(); + witnessProg := btcutil.Hash160(pubKey) + p2wpkh, _ := btcutil.NewAddressWitnessPubKeyHash(witnessProg, chainParam) + + fmt.Printf("Account:\n Private Key: %v\n Public Key: %v\n Address: %v\n", string(wif.String()), hex.EncodeToString(pubKey), p2wpkh) +} + +func TestRandomKeys(t *testing.T) { + randomKeys(3, &chaincfg.RegressionNetParams) +} + +func TestBuildMultisigTapScript(t *testing.T) { + // 2/3: bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz + // 3/3: bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h + totalSigs := 3 + numSigsRequired := 2 + chainParam := &chaincfg.RegressionNetParams + // 3 for multisig vault, 1 for recovery key + _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam) + + fmt.Printf("Len pub key: %v\n", len(pubKeys[0])) + + multisigInfo := &MultisigInfo{ + PubKeys: pubKeys, + EcPubKeys: ECPubKeys, + NumberRequiredSigs: numSigsRequired, + } + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + multisigAddress, err := AddressOnChain(chainParam, multisigWallet) + fmt.Println("address, err : ", multisigAddress, err) +} + +func TestCreateTx(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + + inputs := []*UTXO{ + // 2/3 - empty data + // { + // WalletAddress: "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz", + // TxHash: "1a532a1bd32b6be1140a3e1de414aa4d0d7a215066d62e8a27b96810a80de9ea", + // OutputIdx: 0, + // OutputAmount: 100000, + // }, + // 2/3 - empty data + { + WalletAddress: "bcrt1ptkwstjj0fm24qfm4whkamzxlnp902fpqk2w0ust0usfu9fcmsccs9zvh5n", + TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + OutputIdx: 0, + OutputAmount: 10000, + }, + // 3/3 + // { + // WalletAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", + // TxHash: "18166fe8fe7ca9a9ea5632021d1173860af5ad2c332424a6d1f7d835c37ff347", + // OutputIdx: 0, + // OutputAmount: 100000, + // }, + + // // 2/3 + // { + // WalletAddress: "bcrt1pmq64qc50jnn89s9e2cqn03y83rvqx75r2c2nx0fqqfp8w9jrfktsfkdyjs", + // TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", + // OutputIdx: 0, + // OutputAmount: 10000, + // }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", + Amount: 8000, + }, + } + + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" + msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + fmt.Println("msgTx: ", msgTx) + fmt.Println("prevOuts: ", prevOuts) + fmt.Println("err: ", err) + + // validators sign tx + totalSigs := [][][]byte{} // index private key -> index input -> sig + for _, privKey := range privKeys { + sigs, _, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, prevOuts, multisigWallet, chainParam) + if err != nil { + fmt.Println("err sign: ", err) + } + + totalSigs = append(totalSigs, sigs) + } + + signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} + +func TestGenSharedInternalPubKey(t *testing.T) { + + b := make([]byte, 32) + rand.Read(b) + bHex := hex.EncodeToString(b) + fmt.Printf("bHex: %v\n", bHex) + sharedRandom := new(big.Int).SetBytes(b) + genSharedInternalPubKey(sharedRandom) +} + +func TestParseTx(t *testing.T) { + // hexSignedTx := "02000000000104f6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0000000000ffffffffd9a54f6610fbc9b56cea421230b79edf5c48d92052c13c166656591f2d9ed1fd0000000000ffffffff7b02c2d6a2c8d14d3a1c717f4093306a2c485b4a0cff672ed26715555dff1fde0000000000fffffffff6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0100000000ffffffff05f82a000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd3c3d0900000000002251203cb3f6132189f271733e94476de372e022ea84dc2cb914c7ff691c453ddce563bcb1000000000000160014a355d136171b816b2b2f08d531cf94555d796751e803000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cda22d020000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd01401bdbfd310cbd31807024070825fc5a3fec6e7b37eb1d359dd3027727e5719c52e68b178f438d18c9218b13e3d95b8e3bd8efe1b422778fb88a59a8e5d4a7ba1601418f67cd9c4799e32ac9aed36c14a60e0a2442c4497cddb176ae118a9aeec099f0eaa68901681b0d6df6cdf45c062b70b73171d002d2c50345ea3c53bc51b6e8198301410315713b00ab6f47392e947e90aa4c67c37b77f9c76d1c5cb80a0df5f725dde2b883177dda0abe8dcbc7e06453c2720fa0eefea78e4b905a333929ee03e065bf830140430cc6f8e554c98930c7e67e9512bdc3c73a6944a60a58033607a9b195c857d0426ef570fb6640b07234ef33402a2ce22c66199ec57cbda27ce6028d3258f53100000000" + + hexSignedTx := "01000000000101bcbbb24bd5953d424debb9a24c8009298771eecd3ac0d3c4b219d906a319dfa80000000000e803000002e803000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d53401f000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d530540f4085e4f85eb81b8bd6afd77f728ea75716108cb29cd02aa031def6be65e97e98db40430554669d7b64476d76fd9ae6646529b7abfeee1ac4ad67de0bce9608040f3fc057a9ad0e4a0132040826e2c8e3ca0678ebd515146b8825f527f31195e1966d8424cdf9e963b7335178cab820534e1bd4ede4e8addf47c1bc449a764cec400962c7b22626173655661756c7441646472657373223a22222c22726563656976657241646472657373223a22227d7520fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2ac2030edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052ba201e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833ba529c21c0636e6671d0135074f83177c5e456191043de9bd54744423b88d6b1ab4751650f00000000" + msgTx, err := ParseTx(hexSignedTx) + if err != nil { + fmt.Printf("Err parse tx: %v", err) + return + } + + for _, txIn := range msgTx.TxIn { + fmt.Printf("txIn: %+v\n ", txIn) + } + + for _, txOut := range msgTx.TxOut { + fmt.Printf("txOut: %+v\n ", txOut) + } +} diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go new file mode 100644 index 00000000..b3a90407 --- /dev/null +++ b/utils/multisig/structure.go @@ -0,0 +1,33 @@ +package multisig + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/txscript" +) + +type MultisigInfo struct { + PubKeys [][]byte + EcPubKeys []*btcutil.AddressPubKey + NumberRequiredSigs int +} + +type MultisigWallet struct { + TapScriptTree *txscript.IndexedTapScriptTree + TapLeaves []txscript.TapLeaf + + PKScript []byte + SharedPublicKey *btcec.PublicKey +} + +type OutputTx struct { + ReceiverAddress string + Amount uint64 +} + +type UTXO struct { + WalletAddress string `bson:"wallet_address" json:"walletAddress"` + TxHash string `bson:"tx_hash" json:"txHash"` + OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` + OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` +} diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go new file mode 100644 index 00000000..c9029b56 --- /dev/null +++ b/utils/multisig/tx.go @@ -0,0 +1,226 @@ +package multisig + +import ( + "bytes" + "encoding/hex" + "errors" + "fmt" + "strings" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +// create unsigned multisig transaction +// input: UTXO, output, tx fee, chain config, change receiver +// output: unsigned tx message, previous output fetcher +func CreateMultisigTx( + inputs []*UTXO, + outputs []*OutputTx, + feePerOutput uint64, + chainParam *chaincfg.Params, + changeReceiverAddress string, + sourcePKScript []byte, +) (*wire.MsgTx, *txscript.MultiPrevOutFetcher, error) { + msgTx := wire.NewMsgTx(wire.TxVersion) + + // add TxIns into raw tx + // totalInputAmount in external unit + totalInputAmount := uint64(0) + prevOuts := txscript.NewMultiPrevOutFetcher(nil) + for _, in := range inputs { + utxoHash, err := chainhash.NewHashFromStr(in.TxHash) + if err != nil { + return nil, nil, err + } + outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + txIn := wire.NewTxIn(outPoint, nil, nil) + txIn.Sequence = uint32(feePerOutput) + msgTx.AddTxIn(txIn) + totalInputAmount += in.OutputAmount + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: sourcePKScript, + }) + } + + // add TxOuts into raw tx + // totalOutputAmount in external unit + totalOutputAmount := uint64(0) + for _, out := range outputs { + // adding the output to tx + decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) + if err != nil { + return nil, nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + } + destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) + if err != nil { + return nil, nil, err + } + + // adding the destination address and the amount to the transaction + if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { + return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + } + redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) + + msgTx.AddTxOut(redeemTxOut) + totalOutputAmount += out.Amount + } + + // check amount of input coins and output coins + if totalInputAmount < totalOutputAmount { + return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + } + + // calculate the change output + changeAmt := uint64(0) + if totalInputAmount > totalOutputAmount { + // adding the output to tx + decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) + if err != nil { + return nil, nil, err + } + destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) + if err != nil { + return nil, nil, err + } + + // adding the destination address and the amount to the transaction + changeAmt = totalInputAmount - totalOutputAmount + if changeAmt >= MIN_SAT { + redeemTxOut := wire.NewTxOut(int64(changeAmt), destinationAddrByte) + msgTx.AddTxOut(redeemTxOut) + } else { + changeAmt = 0 + } + } + + var rawTxBytes bytes.Buffer + err := msgTx.Serialize(&rawTxBytes) + if err != nil { + return nil, nil, err + } + + return msgTx, prevOuts, nil +} + +func PartSignOnRawExternalTx( + privKey string, + msgTx *wire.MsgTx, + inputs []*UTXO, + prevOuts *txscript.MultiPrevOutFetcher, + multisigWallet *MultisigWallet, + chainParam *chaincfg.Params, +) ([][]byte, string, error) { + wif, err := btcutil.DecodeWIF(privKey) + if err != nil { + return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) + } + + // sign on each TxIn + if len(inputs) != len(msgTx.TxIn) { + return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) + } + sigs := [][]byte{} + + txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + + for i := range msgTx.TxIn { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[0], txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } + fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) + + sigs = append(sigs, sig) + } + + return sigs, msgTx.TxHash().String(), nil +} + +// combine all the signatures to create the signed tx +// input: unsigned tx message, signatures, multisig struct +// output: signed tx message, tx hash +func CombineMultisigSigs( + multisigInfo *MultisigInfo, + multisigWallet *MultisigWallet, + msgTx *wire.MsgTx, + totalSigs [][][]byte, +) (*wire.MsgTx, error) { + // combine multisigs and finalize tx + numSig := uint(0) + sigs := make([][][]byte, len(msgTx.TxIn)) + for i := range sigs { + sigs[i] = [][]byte{} + } + + for _, sigsFromOneSigner := range totalSigs { + if numSig == uint(multisigInfo.NumberRequiredSigs) { + for indexInput := range sigsFromOneSigner { + if indexInput >= len(sigs) { + return nil, errors.New("invalid length of sigs") + } + sigs[indexInput] = append(sigs[indexInput], []byte{}) + } + } else { + for indexInput, sig := range sigsFromOneSigner { + if indexInput >= len(sigs) { + return nil, errors.New("invalid length of sigs") + } + + sigs[indexInput] = append(sigs[indexInput], sig) + } + numSig++ + } + } + + for idxInput, v := range sigs { + ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) + ctrlBlockBytes, err := ctrlBlock.ToBytes() + if err != nil { + return nil, fmt.Errorf("error including control block: %v", err) + } + + reverseV := [][]byte{} + for i := len(v) - 1; i >= 0; i-- { + reverseV = append(reverseV, v[i]) + } + witness := append([][]byte{}, reverseV...) + witness = append(witness, multisigWallet.TapLeaves[0].Script) + witness = append(witness, ctrlBlockBytes) + + witnessHexStr := []string{} + for _, w := range witness { + witnessHexStr = append(witnessHexStr, hex.EncodeToString(w)) + fmt.Printf("w idxInput %v - %v\n", idxInput, witnessHexStr) + + } + + fmt.Printf("Len witness %v: %v \n", idxInput, len(v)+len(multisigWallet.TapLeaves[0].Script)+len(ctrlBlockBytes)) + + msgTx.TxIn[idxInput].Witness = witness + } + + return msgTx, nil +} + +func ParseTx(data string) (*wire.MsgTx, error) { + fmt.Printf("ParseTx data: %v\n", string(data)) + dataBytes, err := hex.DecodeString(data) + if err != nil { + return nil, err + } + fmt.Printf("ParseTx dataBytes: %v\n", string(dataBytes)) + tx := &wire.MsgTx{} + err = tx.Deserialize(strings.NewReader(string(dataBytes))) + if err != nil { + return nil, err + } + return tx, nil +} diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go new file mode 100644 index 00000000..d550968f --- /dev/null +++ b/utils/multisig/utils.go @@ -0,0 +1,66 @@ +package multisig + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/btcutil/hdkeychain" + "github.com/btcsuite/btcd/chaincfg" +) + +func GeneratePrivateKeyFromSeed(seed []byte, chainParam *chaincfg.Params) *btcec.PrivateKey { + seedDigest := sha256.Sum256([]byte(seed)) + masterKey, _ := hdkeychain.NewMaster(seedDigest[:], chainParam) + for _, childNum := range []uint32{1, 1, 1} { + var err error + masterKey, err = masterKey.Derive(hdkeychain.HardenedKeyStart + childNum) + if err != nil { + panic(err) + } + } + privateKey, _ := masterKey.ECPrivKey() + return privateKey +} + +func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcutil.AddressPubKey) { + + privKeys := []string{} + pubKeys := [][]byte{} + ECPubKeys := []*btcutil.AddressPubKey{} + + for i := 0; i < n; i++ { + privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) + wif, _ := btcutil.NewWIF(privKey, chainParam, true) + + ECPubKey, _ := btcutil.NewAddressPubKey(wif.SerializePubKey(), chainParam) + + pubKey := privKey.PubKey().SerializeCompressed() + pubKey2 := wif.SerializePubKey() + + fmt.Printf("Account %v:\n%v\n%v\n%v\n", i, wif.String(), hex.EncodeToString(wif.SerializePubKey()), wif.PrivKey.Serialize()) + privKeys = append(privKeys, wif.String()) + pubKeys = append(pubKeys, wif.SerializePubKey()) + ECPubKeys = append(ECPubKeys, ECPubKey) + + fmt.Printf("randomKeys pubKey %v - pubKey 2 %v\n ", pubKey, pubKey2) + } + fmt.Printf("len privateKey: %v\n", len(privKeys)) + fmt.Printf("len publicKey: %v\n", len(pubKeys)) + + return privKeys, pubKeys, ECPubKeys +} + + +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params) ([]string, *MultisigInfo) { + privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam) + vaultInfo := MultisigInfo{ + PubKeys: pubKeys, + EcPubKeys: EcPubKeys, + NumberRequiredSigs: k, + } + + return privKeys, &vaultInfo + +} \ No newline at end of file diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go new file mode 100644 index 00000000..66e6b445 --- /dev/null +++ b/utils/multisig/wallet.go @@ -0,0 +1,171 @@ +package multisig + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "math/big" + + "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/txscript" +) + +// hardcode temporarily +const SharedRandomHex = "304575862a092eb80b87dcbafdaac720687694f451ef063b4fb109071f9252ee" + +func toXOnly(pubKey []byte) []byte { + if len(pubKey) == 33 { + return pubKey[1:33] + } + + return pubKey +} + +// use OP_CHECKSIGADD instead of OP_CHECKMULTISIG legacy +func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, string, error) { + builder := txscript.NewScriptBuilder() + + // the first pubkey + builder.AddData(toXOnly(pubKeys[0])) + builder.AddOp(txscript.OP_CHECKSIG) + + // the remaining pubkeys + for i := 1; i < len(pubKeys); i++ { + builder.AddData(toXOnly(pubKeys[i])) + builder.AddOp(txscript.OP_CHECKSIGADD) + } + + // add number of required sigs + builder.AddInt64(int64(numSigsRequired)) + builder.AddOp(txscript.OP_NUMEQUAL) + + redeemScript, err := builder.Script() + if err != nil { + return []byte{}, "", fmt.Errorf("could not build script - Error %v", err) + } + + scriptStr, err := txscript.DisasmString(redeemScript) + fmt.Printf("Script str: %v\n", scriptStr) + fmt.Printf("Script str err: %v\n", err) + + + return redeemScript, "", nil +} + +func computeYCoordinate(x *big.Int) *big.Int { + // secp256k1 curve parameters + params := btcec.S256() + + // Compute y^2 = x^3 + 7 (mod p) + xCubed := new(big.Int).Exp(x, big.NewInt(3), params.P) + ySquared := new(big.Int).Add(xCubed, big.NewInt(7)) + ySquared.Mod(ySquared, params.P) + + // Compute y-coordinate using square root modulo p + y := new(big.Int).ModSqrt(ySquared, params.P) + return y +} + +func genSharedInternalPubKey(sharedRandom *big.Int) (*btcec.PublicKey, []byte, error) { + + // P = H + rG + uncompressGBytes := []byte{4} + uncompressGBytes = append(uncompressGBytes, btcec.S256().CurveParams.Params().Gx.Bytes()...) + uncompressGBytes = append(uncompressGBytes, btcec.S256().CurveParams.Params().Gy.Bytes()...) + hashGBytes := sha256.Sum256(uncompressGBytes) + + xH := new(big.Int).SetBytes(hashGBytes[:]) + yH := computeYCoordinate(xH) + isValidPoint := btcec.S256().IsOnCurve(xH, yH) + if !isValidPoint { + return nil, nil, fmt.Errorf("can not generate H point from hash of G") + } + + xrG, yrG := btcec.S256().ScalarBaseMult(sharedRandom.Bytes()) + xP, yP := btcec.S256().Add(xH, yH, xrG, yrG) + isValidPoint = btcec.S256().IsOnCurve(xP, yP) + if !isValidPoint { + return nil, nil, fmt.Errorf("can not generate P point") + } + xField := &btcec.FieldVal{} + xField.SetBytes((*[32]byte)(xP.Bytes())) + + yField := &btcec.FieldVal{} + yField.SetBytes((*[32]byte)(yP.Bytes())) + + publicKey := btcec.NewPublicKey(xField, yField) + + return publicKey, toXOnly(publicKey.SerializeCompressed()), nil + +} + +// create multisig struct contain multisig wallet detail +// input: multisig info (public keys, number of sigs required) +// output: multisig struct +func GenerateMultisigWallet( + multisigInfo *MultisigInfo, +) (*MultisigWallet, error) { + + // Taptree structure: + // TapLeaf 1: + + script1, _, err := buildMultisigTapScript(multisigInfo.NumberRequiredSigs, multisigInfo.PubKeys) + if err != nil { + return nil, fmt.Errorf("build script 1 err %v", err) + } + + tapLeaf1 := txscript.NewBaseTapLeaf(script1) + tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf1) + + fmt.Printf("TapTree: %+v\n", tapScriptTree) + + tapScriptRootHash := tapScriptTree.RootNode.TapHash() + + sharedRandomBytes, _ := hex.DecodeString(SharedRandomHex) + sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) + + sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) + if err != nil { + return nil, err + } + + outputKey := txscript.ComputeTaprootOutputKey( + sharedPublicKey, tapScriptRootHash[:], + ) + + pkScript, err := txscript.PayToTaprootScript(outputKey) + if err != nil { + return nil, fmt.Errorf("build taproot pk script err %v", err) + } + + return &MultisigWallet{ + PKScript: pkScript, + SharedPublicKey: sharedPublicKey, + + TapScriptTree: tapScriptTree, + TapLeaves: []txscript.TapLeaf{tapLeaf1}, + }, nil + +} + +func AddressOnChain( + chainParam *chaincfg.Params, + multisigWallet *MultisigWallet, +) (*btcutil.AddressTaproot, error) { + tapScriptRootHash := multisigWallet.TapScriptTree.RootNode.TapHash() + + outputKey := txscript.ComputeTaprootOutputKey( + multisigWallet.SharedPublicKey, tapScriptRootHash[:], + ) + + address, err := btcutil.NewAddressTaproot( + schnorr.SerializePubKey(outputKey), chainParam) + if err != nil { + return nil, fmt.Errorf("build address from script err %v", err) + } + + return address, nil +} \ No newline at end of file From facb9b6409e10d5d08af896f5ede004396a01b07 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Thu, 27 Jun 2024 17:22:26 +0700 Subject: [PATCH 016/113] BB-105 update multisig code to allow signing tx through API --- utils/multisig/constants.go | 7 --- utils/multisig/multisig_test.go | 99 +++++++++++++++++++++++++-------- utils/multisig/test_utils.go | 79 ++++++++++++++++++++++++++ utils/multisig/tx.go | 29 +++++++--- utils/multisig/utils.go | 10 ---- utils/multisig/wallet.go | 7 --- 6 files changed, 175 insertions(+), 56 deletions(-) create mode 100644 utils/multisig/test_utils.go diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 35384f0e..40949478 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,10 +1,3 @@ package multisig const MIN_SAT = 546 - -const TEST_ACCOUNT_0_PRIVATE_KEY = "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy" -const TEST_ACCOUNT_0_PUBLIC_KEY = "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2" -const TEST_ACCOUNT_1_PRIVATE_KEY = "cRfK7N7cPZ1BZi6MpsNBuz7k3LiMMA7jreHMx3KUBjRV4KAQT9ou" -const TEST_ACCOUNT_1_PUBLIC_KEY = "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052" -const TEST_ACCOUNT_2_PRIVATE_KEY = "cU8TYnj3fp9t6hVcAz1rNm2GNLoLL2PFHpiCbkXmBCN6F1GZccxf" -const TEST_ACCOUNT_2_PUBLIC_KEY = "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833" diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 7392d198..2e058798 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -4,6 +4,7 @@ import ( "bytes" "crypto/rand" "encoding/hex" + "encoding/json" "fmt" "math/big" "testing" @@ -67,35 +68,17 @@ func TestCreateTx(t *testing.T) { privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) inputs := []*UTXO{ - // 2/3 - empty data - // { - // WalletAddress: "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz", - // TxHash: "1a532a1bd32b6be1140a3e1de414aa4d0d7a215066d62e8a27b96810a80de9ea", - // OutputIdx: 0, - // OutputAmount: 100000, - // }, // 2/3 - empty data { - WalletAddress: "bcrt1ptkwstjj0fm24qfm4whkamzxlnp902fpqk2w0ust0usfu9fcmsccs9zvh5n", TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", OutputIdx: 0, OutputAmount: 10000, }, - // 3/3 - // { - // WalletAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", - // TxHash: "18166fe8fe7ca9a9ea5632021d1173860af5ad2c332424a6d1f7d835c37ff347", - // OutputIdx: 0, - // OutputAmount: 100000, - // }, - - // // 2/3 - // { - // WalletAddress: "bcrt1pmq64qc50jnn89s9e2cqn03y83rvqx75r2c2nx0fqqfp8w9jrfktsfkdyjs", - // TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", - // OutputIdx: 0, - // OutputAmount: 10000, - // }, + { + TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", + OutputIdx: 0, + OutputAmount: 20000, + }, } outputs := []*OutputTx{ @@ -116,7 +99,7 @@ func TestCreateTx(t *testing.T) { // validators sign tx totalSigs := [][][]byte{} // index private key -> index input -> sig for _, privKey := range privKeys { - sigs, _, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, prevOuts, multisigWallet, chainParam) + sigs, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, multisigWallet, 0, chainParam) if err != nil { fmt.Println("err sign: ", err) } @@ -136,6 +119,74 @@ func TestCreateTx(t *testing.T) { fmt.Println("err sign: ", err) } +func TestMultiRelayers(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + + inputs := []*UTXO{ + { + TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + OutputIdx: 0, + OutputAmount: 10000, + }, + { + TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", + OutputIdx: 0, + OutputAmount: 20000, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", + Amount: 8000, + }, + } + + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" + msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + + totalSigs := [][][]byte{} + // MATSTER RELAYER SIGN TX + sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet, 0, chainParam) + if err != nil { + fmt.Println("err sign: ", err) + } + totalSigs = append(totalSigs, sigs) + + router := SetUpRouter() + // create post body using an instance of the requestSignInput struct + rsi := requestSignInput{ + MsgTx: msgTx, + Inputs: inputs, + } + requestJson, _ := json.Marshal(rsi) + + // SLAVE RELAYER 1 SIGN TX + sigs1 := requestSign("/requestSign1", requestJson, router) + fmt.Println("resp: ", sigs1) + totalSigs = append(totalSigs, sigs1) + + // SLAVE RELAYER 2 SIGN TX + sigs2 := requestSign("/requestSign2", requestJson, router) + fmt.Println("resp: ", sigs2) + totalSigs = append(totalSigs, sigs2) + + // MATSTER RELAYER COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} + func TestGenSharedInternalPubKey(t *testing.T) { b := make([]byte, 32) diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go new file mode 100644 index 00000000..ef84aecb --- /dev/null +++ b/utils/multisig/test_utils.go @@ -0,0 +1,79 @@ +package multisig + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/wire" + "github.com/gin-gonic/gin" +) + +func SetUpRouter() *gin.Engine{ + router := gin.Default() + router.POST("/requestSign1", postRequestSignSlaveRelayer1) + router.POST("/requestSign2", postRequestSignSlaveRelayer2) + + return router +} + +func requestSign(url string, requestJson []byte, router *gin.Engine) [][]byte{ + req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestJson)) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) + + responseData, _ := io.ReadAll(w.Body) + + sigs := [][]byte{} + err := json.Unmarshal(responseData, &sigs) + if err != nil { + fmt.Println("err Unmarshal: ", err) + } + + return sigs +} + +type requestSignInput struct { + MsgTx *wire.MsgTx `json:"msgTx"` + Inputs []*UTXO `json:"inputs"` +} + +func postRequestSignSlaveRelayer1(c *gin.Context) { + var input requestSignInput + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + c.IndentedJSON(http.StatusOK, sigs) +} + +func postRequestSignSlaveRelayer2(c *gin.Context) { + var input requestSignInput + + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } + + chainParam := &chaincfg.RegressionNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + c.IndentedJSON(http.StatusOK, sigs) +} \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index c9029b56..8a282a58 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -113,35 +113,48 @@ func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, inputs []*UTXO, - prevOuts *txscript.MultiPrevOutFetcher, multisigWallet *MultisigWallet, + indexTapLeaf int, chainParam *chaincfg.Params, -) ([][]byte, string, error) { +) ([][]byte, error) { wif, err := btcutil.DecodeWIF(privKey) if err != nil { - return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) } // sign on each TxIn if len(inputs) != len(msgTx.TxIn) { - return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) } - sigs := [][]byte{} + prevOuts := txscript.NewMultiPrevOutFetcher(nil) + for _, in := range inputs { + utxoHash, err := chainhash.NewHashFromStr(in.TxHash) + if err != nil { + return nil, err + } + outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: multisigWallet.PKScript, + }) + } txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + sigs := [][]byte{} for i := range msgTx.TxIn { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[0], txscript.SigHashAll, wif.PrivKey) + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) if err != nil { - return nil, "", fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) } fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) sigs = append(sigs, sig) } - return sigs, msgTx.TxHash().String(), nil + return sigs, nil } // combine all the signatures to create the signed tx diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index d550968f..51e233c6 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -2,8 +2,6 @@ package multisig import ( "crypto/sha256" - "encoding/hex" - "fmt" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/hdkeychain" @@ -36,18 +34,10 @@ func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcu ECPubKey, _ := btcutil.NewAddressPubKey(wif.SerializePubKey(), chainParam) - pubKey := privKey.PubKey().SerializeCompressed() - pubKey2 := wif.SerializePubKey() - - fmt.Printf("Account %v:\n%v\n%v\n%v\n", i, wif.String(), hex.EncodeToString(wif.SerializePubKey()), wif.PrivKey.Serialize()) privKeys = append(privKeys, wif.String()) pubKeys = append(pubKeys, wif.SerializePubKey()) ECPubKeys = append(ECPubKeys, ECPubKey) - - fmt.Printf("randomKeys pubKey %v - pubKey 2 %v\n ", pubKey, pubKey2) } - fmt.Printf("len privateKey: %v\n", len(privKeys)) - fmt.Printf("len publicKey: %v\n", len(pubKeys)) return privKeys, pubKeys, ECPubKeys } diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index 66e6b445..1d2dd9d9 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -47,11 +47,6 @@ func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, stri return []byte{}, "", fmt.Errorf("could not build script - Error %v", err) } - scriptStr, err := txscript.DisasmString(redeemScript) - fmt.Printf("Script str: %v\n", scriptStr) - fmt.Printf("Script str err: %v\n", err) - - return redeemScript, "", nil } @@ -120,8 +115,6 @@ func GenerateMultisigWallet( tapLeaf1 := txscript.NewBaseTapLeaf(script1) tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf1) - fmt.Printf("TapTree: %+v\n", tapScriptTree) - tapScriptRootHash := tapScriptTree.RootNode.TapHash() sharedRandomBytes, _ := hex.DecodeString(SharedRandomHex) From 95dd2d1b30585665348d0acfa683af649b9440fb Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 2 Jul 2024 21:25:11 +0700 Subject: [PATCH 017/113] update to allow using the UTXO of user multisig --- utils/multisig/multisig_test.go | 118 +++++++++++++++++++++++----- utils/multisig/structure.go | 8 +- utils/multisig/test_utils.go | 63 ++++++++++++++- utils/multisig/tx.go | 132 +++++++++++++++++--------------- utils/multisig/utils.go | 10 +-- 5 files changed, 236 insertions(+), 95 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 2e058798..6277af0c 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/txscript" ) func TestGenerateKeys(t *testing.T) { @@ -39,7 +40,7 @@ func TestLoadWalletFromPrivateKey(t *testing.T) { } func TestRandomKeys(t *testing.T) { - randomKeys(3, &chaincfg.RegressionNetParams) + randomKeys(3, &chaincfg.RegressionNetParams, []int{0, 1, 2}) } func TestBuildMultisigTapScript(t *testing.T) { @@ -49,7 +50,7 @@ func TestBuildMultisigTapScript(t *testing.T) { numSigsRequired := 2 chainParam := &chaincfg.RegressionNetParams // 3 for multisig vault, 1 for recovery key - _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam) + _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam, []int{0, 1, 2}) fmt.Printf("Len pub key: %v\n", len(pubKeys[0])) @@ -65,16 +66,17 @@ func TestBuildMultisigTapScript(t *testing.T) { func TestCreateTx(t *testing.T) { chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) inputs := []*UTXO{ // 2/3 - empty data { + IsRelayersMultisig: true, TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", OutputIdx: 0, OutputAmount: 10000, }, { + IsRelayersMultisig: true, TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", OutputIdx: 0, OutputAmount: 20000, @@ -88,26 +90,74 @@ func TestCreateTx(t *testing.T) { }, } + _, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) fmt.Println("msgTx: ", msgTx) fmt.Println("prevOuts: ", prevOuts) fmt.Println("err: ", err) +} - // validators sign tx - totalSigs := [][][]byte{} // index private key -> index input -> sig - for _, privKey := range privKeys { - sigs, err := PartSignOnRawExternalTx(privKey, msgTx, inputs, multisigWallet, 0, chainParam) - if err != nil { - fmt.Println("err sign: ", err) - } +func TestMultisigUserClaimLiquidity(t *testing.T) { + chainParam := &chaincfg.RegressionNetParams - totalSigs = append(totalSigs, sigs) + inputs := []*UTXO{ + { + IsRelayersMultisig: true, + TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + OutputIdx: 0, + OutputAmount: 10000, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", + Amount: 8000, + }, } - signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + + changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" + msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + + totalSigs := [][][]byte{} + // MATSTER RELAYER SIGN TX + sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, true) + if err != nil { + fmt.Println("err sign: ", err) + } + totalSigs = append(totalSigs, sigs) + + router := SetUpRouter() + // create post body using an instance of the requestSignInput struct + rsi := requestSignInput{ + MsgTx: msgTx, + Inputs: inputs, + } + requestJson, _ := json.Marshal(rsi) + + // SLAVE RELAYER 1 SIGN TX + sigs1 := requestSign("/requestSign1", requestJson, router) + fmt.Println("resp: ", sigs1) + totalSigs = append(totalSigs, sigs1) + + // SLAVE RELAYER 2 SIGN TX + sigs2 := requestSign("/requestSign2", requestJson, router) + fmt.Println("resp: ", sigs2) + totalSigs = append(totalSigs, sigs2) + + // MATSTER RELAYER COMBINE SIGNS + transposedSigs := TransposeSigs(totalSigs) + relayersMultisigTapLeafScript := multisigWallet.TapLeaves[0].Script + ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) + relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() + + signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, nil, nil, msgTx, inputs, transposedSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -119,17 +169,18 @@ func TestCreateTx(t *testing.T) { fmt.Println("err sign: ", err) } -func TestMultiRelayers(t *testing.T) { +func TestMultisigUserSwap(t *testing.T) { chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) inputs := []*UTXO{ { + IsRelayersMultisig: true, TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", OutputIdx: 0, OutputAmount: 10000, }, { + IsRelayersMultisig: false, TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", OutputIdx: 0, OutputAmount: 20000, @@ -141,16 +192,23 @@ func TestMultiRelayers(t *testing.T) { ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", Amount: 8000, }, + { + ReceiverAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", + Amount: 8000, + }, } - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) + userPrivKeys, _ := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) + userMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript) + msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet, 0, chainParam) + sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) if err != nil { fmt.Println("err sign: ", err) } @@ -174,8 +232,28 @@ func TestMultiRelayers(t *testing.T) { fmt.Println("resp: ", sigs2) totalSigs = append(totalSigs, sigs2) + // USER SIGN TX + userSigs, _ := UserSignTx(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0, chainParam) + // add user sign to total sigs + for i := range msgTx.TxIn { + if (!inputs[i].IsRelayersMultisig) { + totalSigs[1][i] = userSigs[i] + } + } + fmt.Println("--------totalSig: ", totalSigs) + // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(multisigInfo, multisigWallet, msgTx, totalSigs) + transposedSigs := TransposeSigs(totalSigs) + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script + ctrlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) + relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() + + userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script + userCtrlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) + userMultisigControlBlock, _ := userCtrlBlock.ToBytes() + + signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, userMultisigTapLeafScript, userMultisigControlBlock, msgTx, inputs, transposedSigs) + var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -188,7 +266,6 @@ func TestMultiRelayers(t *testing.T) { } func TestGenSharedInternalPubKey(t *testing.T) { - b := make([]byte, 32) rand.Read(b) bHex := hex.EncodeToString(b) @@ -199,7 +276,6 @@ func TestGenSharedInternalPubKey(t *testing.T) { func TestParseTx(t *testing.T) { // hexSignedTx := "02000000000104f6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0000000000ffffffffd9a54f6610fbc9b56cea421230b79edf5c48d92052c13c166656591f2d9ed1fd0000000000ffffffff7b02c2d6a2c8d14d3a1c717f4093306a2c485b4a0cff672ed26715555dff1fde0000000000fffffffff6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0100000000ffffffff05f82a000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd3c3d0900000000002251203cb3f6132189f271733e94476de372e022ea84dc2cb914c7ff691c453ddce563bcb1000000000000160014a355d136171b816b2b2f08d531cf94555d796751e803000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cda22d020000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd01401bdbfd310cbd31807024070825fc5a3fec6e7b37eb1d359dd3027727e5719c52e68b178f438d18c9218b13e3d95b8e3bd8efe1b422778fb88a59a8e5d4a7ba1601418f67cd9c4799e32ac9aed36c14a60e0a2442c4497cddb176ae118a9aeec099f0eaa68901681b0d6df6cdf45c062b70b73171d002d2c50345ea3c53bc51b6e8198301410315713b00ab6f47392e947e90aa4c67c37b77f9c76d1c5cb80a0df5f725dde2b883177dda0abe8dcbc7e06453c2720fa0eefea78e4b905a333929ee03e065bf830140430cc6f8e554c98930c7e67e9512bdc3c73a6944a60a58033607a9b195c857d0426ef570fb6640b07234ef33402a2ce22c66199ec57cbda27ce6028d3258f53100000000" - hexSignedTx := "01000000000101bcbbb24bd5953d424debb9a24c8009298771eecd3ac0d3c4b219d906a319dfa80000000000e803000002e803000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d53401f000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d530540f4085e4f85eb81b8bd6afd77f728ea75716108cb29cd02aa031def6be65e97e98db40430554669d7b64476d76fd9ae6646529b7abfeee1ac4ad67de0bce9608040f3fc057a9ad0e4a0132040826e2c8e3ca0678ebd515146b8825f527f31195e1966d8424cdf9e963b7335178cab820534e1bd4ede4e8addf47c1bc449a764cec400962c7b22626173655661756c7441646472657373223a22222c22726563656976657241646472657373223a22227d7520fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2ac2030edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052ba201e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833ba529c21c0636e6671d0135074f83177c5e456191043de9bd54744423b88d6b1ab4751650f00000000" msgTx, err := ParseTx(hexSignedTx) if err != nil { diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index b3a90407..19693d11 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -26,8 +26,8 @@ type OutputTx struct { } type UTXO struct { - WalletAddress string `bson:"wallet_address" json:"walletAddress"` - TxHash string `bson:"tx_hash" json:"txHash"` - OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` - OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` + IsRelayersMultisig bool `bson:"is_relayers_multisig" json:"isRelayersMultisig"` + TxHash string `bson:"tx_hash" json:"txHash"` + OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` + OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` } diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index ef84aecb..43c5f618 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -8,7 +8,10 @@ import ( "net/http" "net/http/httptest" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/gin-gonic/gin" ) @@ -53,10 +56,10 @@ func postRequestSignSlaveRelayer1(c *gin.Context) { } chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } @@ -71,9 +74,61 @@ func postRequestSignSlaveRelayer2(c *gin.Context) { } chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam) + privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet, 0, chainParam) + sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) +} + +func UserSignTx( + privKey string, + msgTx *wire.MsgTx, + inputs []*UTXO, + multisigWallet *MultisigWallet, + indexTapLeaf int, + chainParam *chaincfg.Params, +) ([][]byte, error) { + wif, err := btcutil.DecodeWIF(privKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) + } + + // sign on each TxIn + if len(inputs) != len(msgTx.TxIn) { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) + } + + prevOuts := txscript.NewMultiPrevOutFetcher(nil) + for _, in := range inputs { + utxoHash, err := chainhash.NewHashFromStr(in.TxHash) + if err != nil { + return nil, err + } + outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: multisigWallet.PKScript, + }) + } + txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + + sigs := [][]byte{} + for i := range msgTx.TxIn { + if (!inputs[i].IsRelayersMultisig) { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } + fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) + + sigs = append(sigs, sig) + } else { + sigs = append(sigs, []byte{}) + } + } + + return sigs, nil } \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 8a282a58..e5ccc355 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -3,7 +3,6 @@ package multisig import ( "bytes" "encoding/hex" - "errors" "fmt" "strings" @@ -23,7 +22,8 @@ func CreateMultisigTx( feePerOutput uint64, chainParam *chaincfg.Params, changeReceiverAddress string, - sourcePKScript []byte, + relayersPKScript []byte, + userPKScript []byte, ) (*wire.MsgTx, *txscript.MultiPrevOutFetcher, error) { msgTx := wire.NewMsgTx(wire.TxVersion) @@ -42,9 +42,16 @@ func CreateMultisigTx( msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount + var pkScript []byte + if (in.IsRelayersMultisig) { + pkScript = relayersPKScript + } else { + pkScript = userPKScript + } + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ Value: int64(in.OutputAmount), - PkScript: sourcePKScript, + PkScript: pkScript, }) } @@ -113,9 +120,12 @@ func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, inputs []*UTXO, - multisigWallet *MultisigWallet, - indexTapLeaf int, + relayersPKScript []byte, + relayersTapLeaf txscript.TapLeaf, + userPKScript []byte, + userTapLeaf txscript.TapLeaf, chainParam *chaincfg.Params, + isMasterRelayer bool, ) ([][]byte, error) { wif, err := btcutil.DecodeWIF(privKey) if err != nil { @@ -135,88 +145,90 @@ func PartSignOnRawExternalTx( } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + var pkScript []byte + if (in.IsRelayersMultisig) { + pkScript = relayersPKScript + } else { + pkScript = userPKScript + } + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ Value: int64(in.OutputAmount), - PkScript: multisigWallet.PKScript, + PkScript: pkScript, }) } txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) sigs := [][]byte{} for i := range msgTx.TxIn { - sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) - if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) - } - fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) + if (inputs[i].IsRelayersMultisig) { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } - sigs = append(sigs, sig) + sigs = append(sigs, sig) + } else if (isMasterRelayer) { + sig, err := txscript.RawTxInTapscriptSignature( + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashAll, wif.PrivKey) + if err != nil { + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + } + + sigs = append(sigs, sig) + } else { + sigs = append(sigs, []byte{}) + } } return sigs, nil } +func TransposeSigs(sigs [][][]byte) [][][]byte { + xl := len(sigs[0]) + yl := len(sigs) + result := make([][][]byte, xl) + + for i := range result { + result[i] = make([][]byte, yl) + } + for i := 0; i < xl; i++ { + for j := 0; j < yl; j++ { + result[i][j] = sigs[j][i] + } + } + return result +} + // combine all the signatures to create the signed tx // input: unsigned tx message, signatures, multisig struct // output: signed tx message, tx hash func CombineMultisigSigs( - multisigInfo *MultisigInfo, - multisigWallet *MultisigWallet, + relayersMultisigTapLeafScript []byte, + relayersMultisigControlBlock []byte, + userMultisigTapLeafScript []byte, + userMultisigControlBlock []byte, msgTx *wire.MsgTx, - totalSigs [][][]byte, + inputs []*UTXO, + transposedSigs [][][]byte, ) (*wire.MsgTx, error) { - // combine multisigs and finalize tx - numSig := uint(0) - sigs := make([][][]byte, len(msgTx.TxIn)) - for i := range sigs { - sigs[i] = [][]byte{} - } - - for _, sigsFromOneSigner := range totalSigs { - if numSig == uint(multisigInfo.NumberRequiredSigs) { - for indexInput := range sigsFromOneSigner { - if indexInput >= len(sigs) { - return nil, errors.New("invalid length of sigs") - } - sigs[indexInput] = append(sigs[indexInput], []byte{}) - } - } else { - for indexInput, sig := range sigsFromOneSigner { - if indexInput >= len(sigs) { - return nil, errors.New("invalid length of sigs") - } - - sigs[indexInput] = append(sigs[indexInput], sig) - } - numSig++ - } - } - - for idxInput, v := range sigs { - ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) - ctrlBlockBytes, err := ctrlBlock.ToBytes() - if err != nil { - return nil, fmt.Errorf("error including control block: %v", err) - } - + for idxInput, v := range transposedSigs { reverseV := [][]byte{} for i := len(v) - 1; i >= 0; i-- { - reverseV = append(reverseV, v[i]) + if (len(v[i]) != 0) { + reverseV = append(reverseV, v[i]) + } } - witness := append([][]byte{}, reverseV...) - witness = append(witness, multisigWallet.TapLeaves[0].Script) - witness = append(witness, ctrlBlockBytes) - witnessHexStr := []string{} - for _, w := range witness { - witnessHexStr = append(witnessHexStr, hex.EncodeToString(w)) - fmt.Printf("w idxInput %v - %v\n", idxInput, witnessHexStr) + witness := append([][]byte{}, reverseV...) + if (inputs[idxInput].IsRelayersMultisig) { + witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlock) + } else { + witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlock) } - fmt.Printf("Len witness %v: %v \n", idxInput, len(v)+len(multisigWallet.TapLeaves[0].Script)+len(ctrlBlockBytes)) - msgTx.TxIn[idxInput].Witness = witness } diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 51e233c6..59fdd17b 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -22,14 +22,14 @@ func GeneratePrivateKeyFromSeed(seed []byte, chainParam *chaincfg.Params) *btcec return privateKey } -func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcutil.AddressPubKey) { +func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][]byte, []*btcutil.AddressPubKey) { privKeys := []string{} pubKeys := [][]byte{} ECPubKeys := []*btcutil.AddressPubKey{} for i := 0; i < n; i++ { - privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) + privKey := GeneratePrivateKeyFromSeed([]byte{byte(seeds[i])}, chainParam) wif, _ := btcutil.NewWIF(privKey, chainParam, true) ECPubKey, _ := btcutil.NewAddressPubKey(wif.SerializePubKey(), chainParam) @@ -42,9 +42,8 @@ func randomKeys(n int, chainParam *chaincfg.Params) ([]string, [][]byte, []*btcu return privKeys, pubKeys, ECPubKeys } - -func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params) ([]string, *MultisigInfo) { - privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam) +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int) ([]string, *MultisigInfo) { + privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ PubKeys: pubKeys, EcPubKeys: EcPubKeys, @@ -52,5 +51,4 @@ func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params) ([]string, *M } return privKeys, &vaultInfo - } \ No newline at end of file From 897288c6dd8731a0d5fa54d074f396539eefaa77 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 3 Jul 2024 16:52:15 +0700 Subject: [PATCH 018/113] BB-106 remove redundant code and update comments --- utils/multisig/multisig_test.go | 7 +++--- utils/multisig/structure.go | 1 - utils/multisig/tx.go | 44 +++++++++++++-------------------- 3 files changed, 20 insertions(+), 32 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 6277af0c..bc319683 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -94,9 +94,8 @@ func TestCreateTx(t *testing.T) { multisigWallet, _ := GenerateMultisigWallet(multisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, prevOuts, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) fmt.Println("msgTx: ", msgTx) - fmt.Println("prevOuts: ", prevOuts) fmt.Println("err: ", err) } @@ -123,7 +122,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { multisigWallet, _ := GenerateMultisigWallet(multisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX @@ -204,7 +203,7 @@ func TestMultisigUserSwap(t *testing.T) { userMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) + msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 19693d11..f2e1df3f 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -15,7 +15,6 @@ type MultisigInfo struct { type MultisigWallet struct { TapScriptTree *txscript.IndexedTapScriptTree TapLeaves []txscript.TapLeaf - PKScript []byte SharedPublicKey *btcec.PublicKey } diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index e5ccc355..30bfb54f 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -14,8 +14,8 @@ import ( ) // create unsigned multisig transaction -// input: UTXO, output, tx fee, chain config, change receiver -// output: unsigned tx message, previous output fetcher +// input: UTXOs, output, tx fee, chain config, change receiver, PK scripts +// output: unsigned tx message func CreateMultisigTx( inputs []*UTXO, outputs []*OutputTx, @@ -24,35 +24,22 @@ func CreateMultisigTx( changeReceiverAddress string, relayersPKScript []byte, userPKScript []byte, -) (*wire.MsgTx, *txscript.MultiPrevOutFetcher, error) { +) (*wire.MsgTx, error) { msgTx := wire.NewMsgTx(wire.TxVersion) // add TxIns into raw tx // totalInputAmount in external unit totalInputAmount := uint64(0) - prevOuts := txscript.NewMultiPrevOutFetcher(nil) for _, in := range inputs { utxoHash, err := chainhash.NewHashFromStr(in.TxHash) if err != nil { - return nil, nil, err + return nil, err } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) txIn := wire.NewTxIn(outPoint, nil, nil) txIn.Sequence = uint32(feePerOutput) msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount - - var pkScript []byte - if (in.IsRelayersMultisig) { - pkScript = relayersPKScript - } else { - pkScript = userPKScript - } - - prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ - Value: int64(in.OutputAmount), - PkScript: pkScript, - }) } // add TxOuts into raw tx @@ -62,16 +49,16 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) if err != nil { - return nil, nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + return nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, nil, err + return nil, err } // adding the destination address and the amount to the transaction if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { - return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) } redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) @@ -81,7 +68,7 @@ func CreateMultisigTx( // check amount of input coins and output coins if totalInputAmount < totalOutputAmount { - return nil, nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) } // calculate the change output @@ -90,11 +77,11 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) if err != nil { - return nil, nil, err + return nil, err } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, nil, err + return nil, err } // adding the destination address and the amount to the transaction @@ -110,12 +97,15 @@ func CreateMultisigTx( var rawTxBytes bytes.Buffer err := msgTx.Serialize(&rawTxBytes) if err != nil { - return nil, nil, err + return nil, err } - return msgTx, prevOuts, nil + return msgTx, nil } +// sign the tx with 1 relayer multisig key +// input: private key, unsigned tx message, UTXOs, PK scripts, tap leave, chain config, relayer type +// output: signatures func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, @@ -202,8 +192,8 @@ func TransposeSigs(sigs [][][]byte) [][][]byte { } // combine all the signatures to create the signed tx -// input: unsigned tx message, signatures, multisig struct -// output: signed tx message, tx hash +// input: tap leave, control blocks, unsigned tx message, UTXOs, signatures collection +// output: signed tx func CombineMultisigSigs( relayersMultisigTapLeafScript []byte, relayersMultisigControlBlock []byte, From 1f8f83d937429add8dd6a8a5a16ea00ab827021e Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Sat, 6 Jul 2024 11:51:43 +0700 Subject: [PATCH 019/113] BB-107 update to test on signet --- utils/multisig/constants.go | 2 +- utils/multisig/multisig_test.go | 90 ++++++++++++++------------------- utils/multisig/test_utils.go | 60 ++-------------------- utils/multisig/tx.go | 14 ++--- 4 files changed, 50 insertions(+), 116 deletions(-) diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 40949478..7f7d3948 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,3 +1,3 @@ package multisig -const MIN_SAT = 546 +const MIN_SAT = 100 diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index bc319683..7edc4716 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -15,7 +15,7 @@ import ( ) func TestGenerateKeys(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams for i := 0; i < 3; i++ { privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) @@ -29,7 +29,7 @@ func TestGenerateKeys(t *testing.T) { } func TestLoadWalletFromPrivateKey(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams wif, _ := btcutil.DecodeWIF("cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy") pubKey := wif.SerializePubKey(); @@ -40,32 +40,23 @@ func TestLoadWalletFromPrivateKey(t *testing.T) { } func TestRandomKeys(t *testing.T) { - randomKeys(3, &chaincfg.RegressionNetParams, []int{0, 1, 2}) + randomKeys(3, &chaincfg.SigNetParams, []int{0, 1, 2}) } func TestBuildMultisigTapScript(t *testing.T) { - // 2/3: bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz - // 3/3: bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h - totalSigs := 3 + totalSigs := 2 numSigsRequired := 2 - chainParam := &chaincfg.RegressionNetParams - // 3 for multisig vault, 1 for recovery key - _, pubKeys, ECPubKeys := randomKeys(totalSigs, chainParam, []int{0, 1, 2}) + chainParam := &chaincfg.SigNetParams - fmt.Printf("Len pub key: %v\n", len(pubKeys[0])) - - multisigInfo := &MultisigInfo{ - PubKeys: pubKeys, - EcPubKeys: ECPubKeys, - NumberRequiredSigs: numSigsRequired, - } + _, multisigInfo := randomMultisigInfo(totalSigs, numSigsRequired, chainParam, []int{0, 3}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + multisigAddress, err := AddressOnChain(chainParam, multisigWallet) fmt.Println("address, err : ", multisigAddress, err) } func TestCreateTx(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ // 2/3 - empty data @@ -90,39 +81,36 @@ func TestCreateTx(t *testing.T) { }, } - _, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, 0) fmt.Println("msgTx: ", msgTx) fmt.Println("err: ", err) } func TestMultisigUserClaimLiquidity(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ { - IsRelayersMultisig: true, - TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + IsRelayersMultisig: false, + TxHash: "e16260c0de027d2f12ea8bbf6fa68fa57a26a3797d44bea27867cbfc6c1f0470", OutputIdx: 0, - OutputAmount: 10000, + OutputAmount: 778, }, } outputs := []*OutputTx{ { - ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", - Amount: 8000, + ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", + Amount: 556, }, } - privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + privKeys, multisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, multisigWallet.PKScript, nil) + changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + msgTx, _ := CreateMultisigTx(inputs, outputs, 222, chainParam, changeReceiverAddress, 0) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX @@ -169,41 +157,37 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { } func TestMultisigUserSwap(t *testing.T) { - chainParam := &chaincfg.RegressionNetParams + chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ { - IsRelayersMultisig: true, - TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", + IsRelayersMultisig: false, + TxHash: "63181e1932a78e0735ce04d0989b50a37decc8ed6f6db071688ac83c95df6cb4", OutputIdx: 0, - OutputAmount: 10000, + OutputAmount: 1168, }, { - IsRelayersMultisig: false, - TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", - OutputIdx: 0, - OutputAmount: 20000, + IsRelayersMultisig: true, + TxHash: "555a2bb0ed3587edf108c626d2a43a16fedb1ff7ff7ceb8e7dbcc98da29c5dce", + OutputIdx: 1, + OutputAmount: 4900, }, } outputs := []*OutputTx{ { - ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", - Amount: 8000, - }, - { - ReceiverAddress: "bcrt1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslstaag7h", - Amount: 8000, + ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", + Amount: 1834, }, } relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) - userPrivKeys, _ := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) - userMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) + userMultisigWallet, _ := GenerateMultisigWallet(userMultisigInfo) - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, _ := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, relayersMultisigWallet.PKScript, userMultisigWallet.PKScript) + changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + msgTx, _ := CreateMultisigTx(inputs, outputs, 333, chainParam, changeReceiverAddress, 0) totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX @@ -232,7 +216,7 @@ func TestMultisigUserSwap(t *testing.T) { totalSigs = append(totalSigs, sigs2) // USER SIGN TX - userSigs, _ := UserSignTx(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0, chainParam) + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) // add user sign to total sigs for i := range msgTx.TxIn { if (!inputs[i].IsRelayersMultisig) { @@ -243,16 +227,16 @@ func TestMultisigUserSwap(t *testing.T) { // MATSTER RELAYER COMBINE SIGNS transposedSigs := TransposeSigs(totalSigs) + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script ctrlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) - relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() + relayersMultisigControlBlockBytes, _ := ctrlBlock.ToBytes() userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script userCtrlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) - userMultisigControlBlock, _ := userCtrlBlock.ToBytes() - - signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, userMultisigTapLeafScript, userMultisigControlBlock, msgTx, inputs, transposedSigs) + userMultisigControlBlockBytes, _ := userCtrlBlock.ToBytes() + signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes, userMultisigTapLeafScript, userMultisigControlBlockBytes, msgTx, inputs, transposedSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index 43c5f618..a05c5005 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -55,8 +55,8 @@ func postRequestSignSlaveRelayer1(c *gin.Context) { return } - chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) + chainParam := &chaincfg.SigNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) @@ -73,62 +73,10 @@ func postRequestSignSlaveRelayer2(c *gin.Context) { return } - chainParam := &chaincfg.RegressionNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}) + chainParam := &chaincfg.SigNetParams + privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) multisigWallet, _ := GenerateMultisigWallet(multisigInfo) sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } - -func UserSignTx( - privKey string, - msgTx *wire.MsgTx, - inputs []*UTXO, - multisigWallet *MultisigWallet, - indexTapLeaf int, - chainParam *chaincfg.Params, -) ([][]byte, error) { - wif, err := btcutil.DecodeWIF(privKey) - if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) - } - - // sign on each TxIn - if len(inputs) != len(msgTx.TxIn) { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) - } - - prevOuts := txscript.NewMultiPrevOutFetcher(nil) - for _, in := range inputs { - utxoHash, err := chainhash.NewHashFromStr(in.TxHash) - if err != nil { - return nil, err - } - outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) - - prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ - Value: int64(in.OutputAmount), - PkScript: multisigWallet.PKScript, - }) - } - txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) - - sigs := [][]byte{} - for i := range msgTx.TxIn { - if (!inputs[i].IsRelayersMultisig) { - sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, multisigWallet.TapLeaves[indexTapLeaf], txscript.SigHashAll, wif.PrivKey) - if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) - } - fmt.Printf("PartSignOnRawExternalTx sig len : %v\n", len(sig)) - - sigs = append(sigs, sig) - } else { - sigs = append(sigs, []byte{}) - } - } - - return sigs, nil -} \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 30bfb54f..e7114a05 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -22,10 +22,12 @@ func CreateMultisigTx( feePerOutput uint64, chainParam *chaincfg.Params, changeReceiverAddress string, - relayersPKScript []byte, - userPKScript []byte, + lockTime uint32, ) (*wire.MsgTx, error) { msgTx := wire.NewMsgTx(wire.TxVersion) + if lockTime > 0 { + msgTx.LockTime = lockTime + } // add TxIns into raw tx // totalInputAmount in external unit @@ -153,17 +155,17 @@ func PartSignOnRawExternalTx( for i := range msgTx.TxIn { if (inputs[i].IsRelayersMultisig) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashAll, wif.PrivKey) + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when relayers-multisig key signing on raw btc tx: %v", err) } sigs = append(sigs, sig) } else if (isMasterRelayer) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashAll, wif.PrivKey) + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when signing on raw btc tx: %v", err) + return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when user-multisig key signing on raw btc tx: %v", err) } sigs = append(sigs, sig) From 013356e79782af375422abc7518e9bee7e9df319 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 8 Jul 2024 17:34:11 +0700 Subject: [PATCH 020/113] remove redundant import --- utils/multisig/test_utils.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index a05c5005..baedab95 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -8,9 +8,7 @@ import ( "net/http" "net/http/httptest" - "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/gin-gonic/gin" From e153bfa6dcd5d805fa54b1c40a50b07fc9f3724e Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 10 Jul 2024 10:02:57 +0700 Subject: [PATCH 021/113] BB-106 fix Invalid Schnorr signature for swap tx; optimize multisig code --- utils/multisig/constants.go | 1 + utils/multisig/multisig_test.go | 109 ++++++++++----------------- utils/multisig/structure.go | 8 ++ utils/multisig/test_utils.go | 59 ++++++++------- utils/multisig/tx.go | 128 ++++++++++++++++---------------- utils/multisig/wallet.go | 7 +- 6 files changed, 143 insertions(+), 169 deletions(-) diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 7f7d3948..7c17d056 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,3 +1,4 @@ package multisig const MIN_SAT = 100 +const SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" \ No newline at end of file diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 7edc4716..305daddf 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -55,66 +55,41 @@ func TestBuildMultisigTapScript(t *testing.T) { fmt.Println("address, err : ", multisigAddress, err) } -func TestCreateTx(t *testing.T) { - chainParam := &chaincfg.SigNetParams - - inputs := []*UTXO{ - // 2/3 - empty data - { - IsRelayersMultisig: true, - TxHash: "62d19039c9d0eec493f3a1440f0fab65c525b1426b675445b01f26ddf1d8fa42", - OutputIdx: 0, - OutputAmount: 10000, - }, - { - IsRelayersMultisig: true, - TxHash: "8f476a9a520f548e7b60512f5c14c5c6253a289dde02d146a02ca22892a2877a", - OutputIdx: 0, - OutputAmount: 20000, - }, - } - - outputs := []*OutputTx{ - { - ReceiverAddress: "bcrt1p65j57tzjufnjmt4fgx5xexfry6f3f87sggl02gl7fcxuky4x34fscyjejf", - Amount: 8000, - }, - } - - changeReceiverAddress := "bcrt1phdyt24adauupp7tawuu9ksl7gvtflr70raj3f2dzwzn06q5vhyhq0l43lz" - msgTx, err := CreateMultisigTx(inputs, outputs, 1000, chainParam, changeReceiverAddress, 0) - fmt.Println("msgTx: ", msgTx) - fmt.Println("err: ", err) -} - func TestMultisigUserClaimLiquidity(t *testing.T) { chainParam := &chaincfg.SigNetParams inputs := []*UTXO{ { - IsRelayersMultisig: false, - TxHash: "e16260c0de027d2f12ea8bbf6fa68fa57a26a3797d44bea27867cbfc6c1f0470", - OutputIdx: 0, - OutputAmount: 778, + IsRelayersMultisig: true, + TxHash: "9ed822adb7c3623fcc6776bc93dadb030bf3b887e36975521d540c2a49510e27", + OutputIdx: 1, + OutputAmount: 3901, }, } outputs := []*OutputTx{ { ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", - Amount: 556, + Amount: 1000, }, } - privKeys, multisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, _ := CreateMultisigTx(inputs, outputs, 222, chainParam, changeReceiverAddress, 0) + msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: relayersMultisigWallet.PKScript, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: []byte{}, + UserTapLeaf: txscript.TapLeaf{}, + } totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(privKeys[0], msgTx, inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, true) + sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) if err != nil { fmt.Println("err sign: ", err) } @@ -123,8 +98,9 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { router := SetUpRouter() // create post body using an instance of the requestSignInput struct rsi := requestSignInput{ - MsgTx: msgTx, - Inputs: inputs, + MsgTx: hexRawTx, + UTXOs: inputs, + TapSigInfo: tapSigParams, } requestJson, _ := json.Marshal(rsi) @@ -139,12 +115,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { totalSigs = append(totalSigs, sigs2) // MATSTER RELAYER COMBINE SIGNS - transposedSigs := TransposeSigs(totalSigs) - relayersMultisigTapLeafScript := multisigWallet.TapLeaves[0].Script - ctrlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(multisigWallet.SharedPublicKey) - relayersMultisigControlBlock, _ := ctrlBlock.ToBytes() - - signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlock, nil, nil, msgTx, inputs, transposedSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, relayersMultisigWallet, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -162,15 +133,15 @@ func TestMultisigUserSwap(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "63181e1932a78e0735ce04d0989b50a37decc8ed6f6db071688ac83c95df6cb4", + TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", OutputIdx: 0, - OutputAmount: 1168, + OutputAmount: 1501, }, { IsRelayersMultisig: true, - TxHash: "555a2bb0ed3587edf108c626d2a43a16fedb1ff7ff7ceb8e7dbcc98da29c5dce", + TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", OutputIdx: 1, - OutputAmount: 4900, + OutputAmount: 4234, }, } @@ -187,11 +158,18 @@ func TestMultisigUserSwap(t *testing.T) { userMultisigWallet, _ := GenerateMultisigWallet(userMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, _ := CreateMultisigTx(inputs, outputs, 333, chainParam, changeReceiverAddress, 0) + msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: relayersMultisigWallet.PKScript, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[0], + } totalSigs := [][][]byte{} // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) + sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) if err != nil { fmt.Println("err sign: ", err) } @@ -200,8 +178,9 @@ func TestMultisigUserSwap(t *testing.T) { router := SetUpRouter() // create post body using an instance of the requestSignInput struct rsi := requestSignInput{ - MsgTx: msgTx, - Inputs: inputs, + MsgTx: hexRawTx, + UTXOs: inputs, + TapSigInfo: tapSigParams, } requestJson, _ := json.Marshal(rsi) @@ -216,7 +195,8 @@ func TestMultisigUserSwap(t *testing.T) { totalSigs = append(totalSigs, sigs2) // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, relayersMultisigWallet.PKScript, relayersMultisigWallet.TapLeaves[0], userMultisigWallet.PKScript, userMultisigWallet.TapLeaves[0], chainParam, true) + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + // add user sign to total sigs for i := range msgTx.TxIn { if (!inputs[i].IsRelayersMultisig) { @@ -226,17 +206,7 @@ func TestMultisigUserSwap(t *testing.T) { fmt.Println("--------totalSig: ", totalSigs) // MATSTER RELAYER COMBINE SIGNS - transposedSigs := TransposeSigs(totalSigs) - - relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script - ctrlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) - relayersMultisigControlBlockBytes, _ := ctrlBlock.ToBytes() - - userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script - userCtrlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) - userMultisigControlBlockBytes, _ := userCtrlBlock.ToBytes() - - signedMsgTx, err := CombineMultisigSigs(relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes, userMultisigTapLeafScript, userMultisigControlBlockBytes, msgTx, inputs, transposedSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, userMultisigWallet, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -258,7 +228,6 @@ func TestGenSharedInternalPubKey(t *testing.T) { } func TestParseTx(t *testing.T) { - // hexSignedTx := "02000000000104f6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0000000000ffffffffd9a54f6610fbc9b56cea421230b79edf5c48d92052c13c166656591f2d9ed1fd0000000000ffffffff7b02c2d6a2c8d14d3a1c717f4093306a2c485b4a0cff672ed26715555dff1fde0000000000fffffffff6ce922d4b636e81b5fe301d541f14a07ca8b5ee9e7c9637479fbb77ae76ac9c0100000000ffffffff05f82a000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd3c3d0900000000002251203cb3f6132189f271733e94476de372e022ea84dc2cb914c7ff691c453ddce563bcb1000000000000160014a355d136171b816b2b2f08d531cf94555d796751e803000000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cda22d020000000000225120863583d69b5e4ce5edd053d72148074b6fe8968dc9175d9e1610282faf0ff3cd01401bdbfd310cbd31807024070825fc5a3fec6e7b37eb1d359dd3027727e5719c52e68b178f438d18c9218b13e3d95b8e3bd8efe1b422778fb88a59a8e5d4a7ba1601418f67cd9c4799e32ac9aed36c14a60e0a2442c4497cddb176ae118a9aeec099f0eaa68901681b0d6df6cdf45c062b70b73171d002d2c50345ea3c53bc51b6e8198301410315713b00ab6f47392e947e90aa4c67c37b77f9c76d1c5cb80a0df5f725dde2b883177dda0abe8dcbc7e06453c2720fa0eefea78e4b905a333929ee03e065bf830140430cc6f8e554c98930c7e67e9512bdc3c73a6944a60a58033607a9b195c857d0426ef570fb6640b07234ef33402a2ce22c66199ec57cbda27ce6028d3258f53100000000" hexSignedTx := "01000000000101bcbbb24bd5953d424debb9a24c8009298771eecd3ac0d3c4b219d906a319dfa80000000000e803000002e803000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d53401f000000000000225120d5254f2c52e2672daea941a86c99232693149fd0423ef523fe4e0dcb12a68d530540f4085e4f85eb81b8bd6afd77f728ea75716108cb29cd02aa031def6be65e97e98db40430554669d7b64476d76fd9ae6646529b7abfeee1ac4ad67de0bce9608040f3fc057a9ad0e4a0132040826e2c8e3ca0678ebd515146b8825f527f31195e1966d8424cdf9e963b7335178cab820534e1bd4ede4e8addf47c1bc449a764cec400962c7b22626173655661756c7441646472657373223a22222c22726563656976657241646472657373223a22227d7520fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2ac2030edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052ba201e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833ba529c21c0636e6671d0135074f83177c5e456191043de9bd54744423b88d6b1ab4751650f00000000" msgTx, err := ParseTx(hexSignedTx) if err != nil { diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index f2e1df3f..0ccb1ff5 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -30,3 +30,11 @@ type UTXO struct { OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` } + +type TapSigParams struct { + TxSigHashes *txscript.TxSigHashes `bson:"tx_sig_hashes" json:"txSigHashes"` + RelayersPKScript []byte `bson:"relayers_PK_script" json:"relayersPKScript"` + RelayersTapLeaf txscript.TapLeaf `bson:"relayers_tap_leaf" json:"relayersTapLeaf"` + UserPKScript []byte `bson:"user_PK_script" json:"userPKScript"` + UserTapLeaf txscript.TapLeaf `bson:"user_tap_leaf" json:"userTapLeaf"` +} diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index baedab95..3c0f6799 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -9,25 +9,23 @@ import ( "net/http/httptest" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" "github.com/gin-gonic/gin" ) func SetUpRouter() *gin.Engine{ - router := gin.Default() + router := gin.Default() router.POST("/requestSign1", postRequestSignSlaveRelayer1) router.POST("/requestSign2", postRequestSignSlaveRelayer2) - return router + return router } func requestSign(url string, requestJson []byte, router *gin.Engine) [][]byte{ req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestJson)) - w := httptest.NewRecorder() - router.ServeHTTP(w, req) + w := httptest.NewRecorder() + router.ServeHTTP(w, req) - responseData, _ := io.ReadAll(w.Body) + responseData, _ := io.ReadAll(w.Body) sigs := [][]byte{} err := json.Unmarshal(responseData, &sigs) @@ -39,42 +37,43 @@ func requestSign(url string, requestJson []byte, router *gin.Engine) [][]byte{ } type requestSignInput struct { - MsgTx *wire.MsgTx `json:"msgTx"` - Inputs []*UTXO `json:"inputs"` + MsgTx string `json:"msgTx"` + UTXOs []*UTXO `json:"UTXOs"` + TapSigInfo TapSigParams `json:"tapSigInfo"` } func postRequestSignSlaveRelayer1(c *gin.Context) { - var input requestSignInput + var input requestSignInput if err := c.ShouldBindJSON(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), - }) - return - } + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } chainParam := &chaincfg.SigNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + msgTx, _ := ParseTx(input.MsgTx) + sigs, _ := PartSignOnRawExternalTx(privKeys[1], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) - sigs, _ := PartSignOnRawExternalTx(privKeys[1], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) - c.IndentedJSON(http.StatusOK, sigs) + c.IndentedJSON(http.StatusOK, sigs) } func postRequestSignSlaveRelayer2(c *gin.Context) { - var input requestSignInput + var input requestSignInput - if err := c.ShouldBindJSON(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), - }) - return - } + if err := c.ShouldBindJSON(&input); err != nil { + c.JSON(http.StatusBadRequest, gin.H{ + "error": err.Error(), + }) + return + } chainParam := &chaincfg.SigNetParams - privKeys, multisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + msgTx, _ := ParseTx(input.MsgTx) + sigs, _ := PartSignOnRawExternalTx(privKeys[2], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) - sigs, _ := PartSignOnRawExternalTx(privKeys[2], input.MsgTx, input.Inputs, multisigWallet.PKScript, multisigWallet.TapLeaves[0], nil, txscript.TapLeaf{}, chainParam, false) - c.IndentedJSON(http.StatusOK, sigs) + c.IndentedJSON(http.StatusOK, sigs) } diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index e7114a05..428005f2 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -17,13 +17,15 @@ import ( // input: UTXOs, output, tx fee, chain config, change receiver, PK scripts // output: unsigned tx message func CreateMultisigTx( - inputs []*UTXO, - outputs []*OutputTx, - feePerOutput uint64, - chainParam *chaincfg.Params, - changeReceiverAddress string, + inputs []*UTXO, + outputs []*OutputTx, + feePerOutput uint64, + relayersMultisigWallet *MultisigWallet, + userMultisigWallet *MultisigWallet, + chainParam *chaincfg.Params, + changeReceiverAddress string, lockTime uint32, -) (*wire.MsgTx, error) { +) (*wire.MsgTx, string, *txscript.TxSigHashes, error) { msgTx := wire.NewMsgTx(wire.TxVersion) if lockTime > 0 { msgTx.LockTime = lockTime @@ -32,16 +34,29 @@ func CreateMultisigTx( // add TxIns into raw tx // totalInputAmount in external unit totalInputAmount := uint64(0) + prevOuts := txscript.NewMultiPrevOutFetcher(nil) for _, in := range inputs { utxoHash, err := chainhash.NewHashFromStr(in.TxHash) if err != nil { - return nil, err + return nil, "", nil, err } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) txIn := wire.NewTxIn(outPoint, nil, nil) txIn.Sequence = uint32(feePerOutput) msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount + + var pkScript []byte + if (in.IsRelayersMultisig) { + pkScript = relayersMultisigWallet.PKScript + } else { + pkScript = userMultisigWallet.PKScript + } + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: int64(in.OutputAmount), + PkScript: pkScript, + }) } // add TxOuts into raw tx @@ -51,16 +66,16 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) if err != nil { - return nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + return nil, "", nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, err + return nil, "", nil, err } // adding the destination address and the amount to the transaction if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { - return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) } redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) @@ -70,7 +85,7 @@ func CreateMultisigTx( // check amount of input coins and output coins if totalInputAmount < totalOutputAmount { - return nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) } // calculate the change output @@ -79,11 +94,11 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) if err != nil { - return nil, err + return nil, "", nil, err } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { - return nil, err + return nil, "", nil, err } // adding the destination address and the amount to the transaction @@ -99,10 +114,13 @@ func CreateMultisigTx( var rawTxBytes bytes.Buffer err := msgTx.Serialize(&rawTxBytes) if err != nil { - return nil, err + return nil, "", nil, err } + hexRawTx := hex.EncodeToString(rawTxBytes.Bytes()) - return msgTx, nil + txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + + return msgTx, hexRawTx, txSigHashes, nil } // sign the tx with 1 relayer multisig key @@ -112,10 +130,7 @@ func PartSignOnRawExternalTx( privKey string, msgTx *wire.MsgTx, inputs []*UTXO, - relayersPKScript []byte, - relayersTapLeaf txscript.TapLeaf, - userPKScript []byte, - userTapLeaf txscript.TapLeaf, + tapSigParams TapSigParams, chainParam *chaincfg.Params, isMasterRelayer bool, ) ([][]byte, error) { @@ -129,33 +144,11 @@ func PartSignOnRawExternalTx( return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) } - prevOuts := txscript.NewMultiPrevOutFetcher(nil) - for _, in := range inputs { - utxoHash, err := chainhash.NewHashFromStr(in.TxHash) - if err != nil { - return nil, err - } - outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) - - var pkScript []byte - if (in.IsRelayersMultisig) { - pkScript = relayersPKScript - } else { - pkScript = userPKScript - } - - prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ - Value: int64(in.OutputAmount), - PkScript: pkScript, - }) - } - txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) - sigs := [][]byte{} for i := range msgTx.TxIn { if (inputs[i].IsRelayersMultisig) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), relayersPKScript, relayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) + msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.RelayersPKScript, tapSigParams.RelayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when relayers-multisig key signing on raw btc tx: %v", err) } @@ -163,7 +156,7 @@ func PartSignOnRawExternalTx( sigs = append(sigs, sig) } else if (isMasterRelayer) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), userPKScript, userTapLeaf, txscript.SigHashDefault, wif.PrivKey) + msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.UserPKScript, tapSigParams.UserTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when user-multisig key signing on raw btc tx: %v", err) } @@ -179,32 +172,40 @@ func PartSignOnRawExternalTx( func TransposeSigs(sigs [][][]byte) [][][]byte { xl := len(sigs[0]) - yl := len(sigs) - result := make([][][]byte, xl) - - for i := range result { - result[i] = make([][]byte, yl) - } - for i := 0; i < xl; i++ { - for j := 0; j < yl; j++ { - result[i][j] = sigs[j][i] - } - } - return result + yl := len(sigs) + result := make([][][]byte, xl) + + for i := range result { + result[i] = make([][]byte, yl) + } + for i := 0; i < xl; i++ { + for j := 0; j < yl; j++ { + result[i][j] = sigs[j][i] + } + } + + return result } // combine all the signatures to create the signed tx // input: tap leave, control blocks, unsigned tx message, UTXOs, signatures collection // output: signed tx func CombineMultisigSigs( - relayersMultisigTapLeafScript []byte, - relayersMultisigControlBlock []byte, - userMultisigTapLeafScript []byte, - userMultisigControlBlock []byte, - msgTx *wire.MsgTx, + msgTx *wire.MsgTx, inputs []*UTXO, - transposedSigs [][][]byte, + relayersMultisigWallet *MultisigWallet, + userMultisigWallet *MultisigWallet, + totalSigs [][][]byte, ) (*wire.MsgTx, error) { + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script + relayersMultisigControlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) + relayersMultisigControlBlockBytes, _ := relayersMultisigControlBlock.ToBytes() + + userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script + userMultisigControlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) + userMultisigControlBlockBytes, _ := userMultisigControlBlock.ToBytes() + + transposedSigs := TransposeSigs(totalSigs) for idxInput, v := range transposedSigs { reverseV := [][]byte{} for i := len(v) - 1; i >= 0; i-- { @@ -214,11 +215,10 @@ func CombineMultisigSigs( } witness := append([][]byte{}, reverseV...) - if (inputs[idxInput].IsRelayersMultisig) { - witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlock) + witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes) } else { - witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlock) + witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlockBytes) } msgTx.TxIn[idxInput].Witness = witness diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index 1d2dd9d9..9a17d54f 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -13,9 +13,6 @@ import ( "github.com/btcsuite/btcd/txscript" ) -// hardcode temporarily -const SharedRandomHex = "304575862a092eb80b87dcbafdaac720687694f451ef063b4fb109071f9252ee" - func toXOnly(pubKey []byte) []byte { if len(pubKey) == 33 { return pubKey[1:33] @@ -101,7 +98,7 @@ func genSharedInternalPubKey(sharedRandom *big.Int) (*btcec.PublicKey, []byte, e // input: multisig info (public keys, number of sigs required) // output: multisig struct func GenerateMultisigWallet( - multisigInfo *MultisigInfo, + multisigInfo *MultisigInfo, ) (*MultisigWallet, error) { // Taptree structure: @@ -117,7 +114,7 @@ func GenerateMultisigWallet( tapScriptRootHash := tapScriptTree.RootNode.TapHash() - sharedRandomBytes, _ := hex.DecodeString(SharedRandomHex) + sharedRandomBytes, _ := hex.DecodeString(SHARED_RANDOM_HEX) sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) From fae6147822528c32f70aa7cbe3e16ece63c38a9f Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 10 Jul 2024 16:48:49 +0700 Subject: [PATCH 022/113] BB-104 update lock time tap-leaf to the multisig --- utils/multisig/multisig_test.go | 27 +++++---- utils/multisig/structure.go | 2 + utils/multisig/test_utils.go | 8 +-- utils/multisig/utils.go | 10 +-- utils/multisig/wallet.go | 104 ++++++++++++++++++++++---------- 5 files changed, 99 insertions(+), 52 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 305daddf..9b359b40 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -44,15 +44,18 @@ func TestRandomKeys(t *testing.T) { } func TestBuildMultisigTapScript(t *testing.T) { - totalSigs := 2 - numSigsRequired := 2 chainParam := &chaincfg.SigNetParams - _, multisigInfo := randomMultisigInfo(totalSigs, numSigsRequired, chainParam, []int{0, 3}) - multisigWallet, _ := GenerateMultisigWallet(multisigInfo) + _, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) + _, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - multisigAddress, err := AddressOnChain(chainParam, multisigWallet) - fmt.Println("address, err : ", multisigAddress, err) + relayersMultisigAddress, err := AddressOnChain(chainParam, relayersMultisigWallet) + fmt.Println("relayersMultisigAddress, err : ", relayersMultisigAddress, err) + + userMultisigAddress, err := AddressOnChain(chainParam, userMultisigWallet) + fmt.Println("userMultisigAddress, err : ", userMultisigAddress, err) } func TestMultisigUserClaimLiquidity(t *testing.T) { @@ -74,8 +77,8 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { }, } - relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) @@ -152,10 +155,10 @@ func TestMultisigUserSwap(t *testing.T) { }, } - relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) - relayersMultisigWallet, _ := GenerateMultisigWallet(relayersMultisigInfo) - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}) - userMultisigWallet, _ := GenerateMultisigWallet(userMultisigInfo) + relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 0ccb1ff5..1f7d4893 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -10,6 +10,8 @@ type MultisigInfo struct { PubKeys [][]byte EcPubKeys []*btcutil.AddressPubKey NumberRequiredSigs int + RecoveryPubKey []byte + RecoveryBlockHeight uint64 } type MultisigWallet struct { diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go index 3c0f6799..bb453723 100644 --- a/utils/multisig/test_utils.go +++ b/utils/multisig/test_utils.go @@ -53,9 +53,9 @@ func postRequestSignSlaveRelayer1(c *gin.Context) { } chainParam := &chaincfg.SigNetParams - privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + privKeys, _, _ := randomKeys(1, chainParam, []int{1}) msgTx, _ := ParseTx(input.MsgTx) - sigs, _ := PartSignOnRawExternalTx(privKeys[1], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) + sigs, _ := PartSignOnRawExternalTx(privKeys[0], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } @@ -71,9 +71,9 @@ func postRequestSignSlaveRelayer2(c *gin.Context) { } chainParam := &chaincfg.SigNetParams - privKeys, _ := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}) + privKeys, _, _ := randomKeys(1, chainParam, []int{2}) msgTx, _ := ParseTx(input.MsgTx) - sigs, _ := PartSignOnRawExternalTx(privKeys[2], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) + sigs, _ := PartSignOnRawExternalTx(privKeys[0], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) c.IndentedJSON(http.StatusOK, sigs) } diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 59fdd17b..65d43f9d 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -42,12 +42,14 @@ func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][] return privKeys, pubKeys, ECPubKeys } -func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int) ([]string, *MultisigInfo) { +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryBlockHeight uint64) ([]string, *MultisigInfo) { privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ - PubKeys: pubKeys, - EcPubKeys: EcPubKeys, - NumberRequiredSigs: k, + PubKeys: pubKeys, + EcPubKeys: EcPubKeys, + NumberRequiredSigs: k, + RecoveryPubKey: pubKeys[recoveryKeyIdx], + RecoveryBlockHeight: recoveryBlockHeight, } return privKeys, &vaultInfo diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index 9a17d54f..a40ca465 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -47,6 +47,67 @@ func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, stri return redeemScript, "", nil } +// Point time lock contract script +// use OP_CHECKLOCKTIMEVERIFY +func buildPTLCTapScript( + expiredBlkHeight uint64, + pubKey []byte, +) ([]byte, string, error) { + + // OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG + + builder := txscript.NewScriptBuilder() + // builder.AddData(new(big.Int).SetUint64(expiredBlkHeight).Bytes()) // TODO: need to fixed length? + builder.AddInt64(int64(expiredBlkHeight)) + builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY) + builder.AddOp(txscript.OP_DROP) + builder.AddData(toXOnly(pubKey)) + builder.AddOp(txscript.OP_CHECKSIG) + + scriptBytes, err := builder.Script() + if err != nil { + return []byte{}, "", fmt.Errorf("buildPTLCTapScript could not build script - Error %v", err) + } + + return scriptBytes, "", nil +} + +func buildMultisigWalletFromScripts(scripts [][]byte) (*MultisigWallet, error) { + tapLeaves := []txscript.TapLeaf{} + for _, script := range scripts { + tapLeaf := txscript.NewBaseTapLeaf(script) + tapLeaves = append(tapLeaves, tapLeaf) + } + + tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaves...) + tapScriptRootHash := tapScriptTree.RootNode.TapHash() + + sharedRandomBytes, _ := hex.DecodeString(SHARED_RANDOM_HEX) + sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) + + sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) + if err != nil { + return nil, err + } + + outputKey := txscript.ComputeTaprootOutputKey( + sharedPublicKey, tapScriptRootHash[:], + ) + + pkScript, err := txscript.PayToTaprootScript(outputKey) + if err != nil { + return nil, fmt.Errorf("build taproot PK script err %v", err) + } + + return &MultisigWallet{ + PKScript: pkScript, + SharedPublicKey: sharedPublicKey, + + TapScriptTree: tapScriptTree, + TapLeaves: tapLeaves, + }, nil +} + func computeYCoordinate(x *big.Int) *big.Int { // secp256k1 curve parameters params := btcec.S256() @@ -97,48 +158,27 @@ func genSharedInternalPubKey(sharedRandom *big.Int) (*btcec.PublicKey, []byte, e // create multisig struct contain multisig wallet detail // input: multisig info (public keys, number of sigs required) // output: multisig struct -func GenerateMultisigWallet( +func BuildMultisigWallet( multisigInfo *MultisigInfo, ) (*MultisigWallet, error) { - // Taptree structure: // TapLeaf 1: - + // TapLeaf 2: script1, _, err := buildMultisigTapScript(multisigInfo.NumberRequiredSigs, multisigInfo.PubKeys) if err != nil { - return nil, fmt.Errorf("build script 1 err %v", err) - } - - tapLeaf1 := txscript.NewBaseTapLeaf(script1) - tapScriptTree := txscript.AssembleTaprootScriptTree(tapLeaf1) - - tapScriptRootHash := tapScriptTree.RootNode.TapHash() - - sharedRandomBytes, _ := hex.DecodeString(SHARED_RANDOM_HEX) - sharedRandom := new(big.Int).SetBytes(sharedRandomBytes) - - sharedPublicKey, _, err := genSharedInternalPubKey(sharedRandom) - if err != nil { - return nil, err + return nil, fmt.Errorf("build script multisig err %v", err) } - outputKey := txscript.ComputeTaprootOutputKey( - sharedPublicKey, tapScriptRootHash[:], - ) + if multisigInfo.RecoveryBlockHeight == 0 { + return buildMultisigWalletFromScripts([][]byte{script1}) + } else { + script2, _, err := buildPTLCTapScript(multisigInfo.RecoveryBlockHeight, multisigInfo.RecoveryPubKey) + if err != nil { + return nil, fmt.Errorf("build script PTLC err %v", err) + } - pkScript, err := txscript.PayToTaprootScript(outputKey) - if err != nil { - return nil, fmt.Errorf("build taproot pk script err %v", err) + return buildMultisigWalletFromScripts([][]byte{script1, script2}) } - - return &MultisigWallet{ - PKScript: pkScript, - SharedPublicKey: sharedPublicKey, - - TapScriptTree: tapScriptTree, - TapLeaves: []txscript.TapLeaf{tapLeaf1}, - }, nil - } func AddressOnChain( From e81d9f310f1d8c39191e9ab5c4b7f714a7f1f274 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 12 Jul 2024 21:05:07 +0700 Subject: [PATCH 023/113] BB-106 update multisig time lock recovery test --- utils/multisig/multisig_test.go | 55 +++++++++++++++++++++++++++++++-- utils/multisig/tx.go | 12 ++++--- 2 files changed, 60 insertions(+), 7 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 9b359b40..f1181cec 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -118,7 +118,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { totalSigs = append(totalSigs, sigs2) // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, relayersMultisigWallet, totalSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, relayersMultisigWallet, 0, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -209,7 +209,7 @@ func TestMultisigUserSwap(t *testing.T) { fmt.Println("--------totalSig: ", totalSigs) // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, userMultisigWallet, totalSigs) + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, userMultisigWallet, 0, totalSigs) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -246,3 +246,54 @@ func TestParseTx(t *testing.T) { fmt.Printf("txOut: %+v\n ", txOut) } } + +func TestUserRecoveryTimeLock(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "69c88fa67f3c5aad9b4494618046969f4a8e0dfccaa10def6dbbb5ff192c9924", + OutputIdx: 1, + OutputAmount: 7308, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pnlfh96hs3sc0tvanxhqlcfnwz32shff726f8yt6vay4tk62y4c9sluydah", + Amount: 1500, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1p2u4dx80df4xa87fxzw8wrqh698xxa2deu9nyfkjkrfd3fgk3l8dqc0tg3t" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} \ No newline at end of file diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 428005f2..5aa8f926 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -183,7 +183,7 @@ func TransposeSigs(sigs [][][]byte) [][][]byte { result[i][j] = sigs[j][i] } } - + return result } @@ -194,15 +194,17 @@ func CombineMultisigSigs( msgTx *wire.MsgTx, inputs []*UTXO, relayersMultisigWallet *MultisigWallet, + relayersIndexTapLeaf int, userMultisigWallet *MultisigWallet, + userIndexTapLeaf int, totalSigs [][][]byte, ) (*wire.MsgTx, error) { - relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[0].Script - relayersMultisigControlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(relayersMultisigWallet.SharedPublicKey) + relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[relayersIndexTapLeaf].Script + relayersMultisigControlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[relayersIndexTapLeaf].ToControlBlock(relayersMultisigWallet.SharedPublicKey) relayersMultisigControlBlockBytes, _ := relayersMultisigControlBlock.ToBytes() - userMultisigTapLeafScript := userMultisigWallet.TapLeaves[0].Script - userMultisigControlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[0].ToControlBlock(userMultisigWallet.SharedPublicKey) + userMultisigTapLeafScript := userMultisigWallet.TapLeaves[userIndexTapLeaf].Script + userMultisigControlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[userIndexTapLeaf].ToControlBlock(userMultisigWallet.SharedPublicKey) userMultisigControlBlockBytes, _ := userMultisigControlBlock.ToBytes() transposedSigs := TransposeSigs(totalSigs) From 5386d09feca352c1f7c95cb84f8ee31f12c1d91e Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 15 Jul 2024 21:14:31 +0700 Subject: [PATCH 024/113] BB-106 update multisig recovery to relative timelock --- go.work.sum | 359 ++++++++++++++++++++++++++++---- utils/multisig/multisig_test.go | 12 +- utils/multisig/structure.go | 2 +- utils/multisig/tx.go | 10 +- utils/multisig/utils.go | 4 +- utils/multisig/wallet.go | 16 +- 6 files changed, 338 insertions(+), 65 deletions(-) diff --git a/go.work.sum b/go.work.sum index 73d3c1cd..20099db4 100644 --- a/go.work.sum +++ b/go.work.sum @@ -3,143 +3,271 @@ cloud.google.com/go v0.0.0-20170206221025-ce650573d812/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= cloud.google.com/go v0.112.2/go.mod h1:iEqjp//KquGIJV/m+Pk3xecgKNhV+ry+vVTsy4TbDms= +cloud.google.com/go/accessapproval v1.7.5/go.mod h1:g88i1ok5dvQ9XJsxpUInWWvUBrIZhyPDPbk4T01OoJ0= cloud.google.com/go/accessapproval v1.7.7/go.mod h1:10ZDPYiTm8tgxuMPid8s2DL93BfCt6xBh/Vg0Xd8pU0= +cloud.google.com/go/accesscontextmanager v1.8.5/go.mod h1:TInEhcZ7V9jptGNqN3EzZ5XMhT6ijWxTGjzyETwmL0Q= cloud.google.com/go/accesscontextmanager v1.8.7/go.mod h1:jSvChL1NBQ+uLY9zUBdPy9VIlozPoHptdBnRYeWuQoM= +cloud.google.com/go/aiplatform v1.60.0/go.mod h1:eTlGuHOahHprZw3Hio5VKmtThIOak5/qy6pzdsqcQnM= cloud.google.com/go/aiplatform v1.67.0/go.mod h1:s/sJ6btBEr6bKnrNWdK9ZgHCvwbZNdP90b3DDtxxw+Y= +cloud.google.com/go/analytics v0.23.0/go.mod h1:YPd7Bvik3WS95KBok2gPXDqQPHy08TsCQG6CdUCb+u0= cloud.google.com/go/analytics v0.23.2/go.mod h1:vtE3olAXZ6edJYk1UOndEs6EfaEc9T2B28Y4G5/a7Fo= +cloud.google.com/go/apigateway v1.6.5/go.mod h1:6wCwvYRckRQogyDDltpANi3zsCDl6kWi0b4Je+w2UiI= cloud.google.com/go/apigateway v1.6.7/go.mod h1:7wAMb/33Rzln+PrGK16GbGOfA1zAO5Pq6wp19jtIt7c= +cloud.google.com/go/apigeeconnect v1.6.5/go.mod h1:MEKm3AiT7s11PqTfKE3KZluZA9O91FNysvd3E6SJ6Ow= cloud.google.com/go/apigeeconnect v1.6.7/go.mod h1:hZxCKvAvDdKX8+eT0g5eEAbRSS9Gkzi+MPWbgAMAy5U= +cloud.google.com/go/apigeeregistry v0.8.3/go.mod h1:aInOWnqF4yMQx8kTjDqHNXjZGh/mxeNlAf52YqtASUs= cloud.google.com/go/apigeeregistry v0.8.5/go.mod h1:ZMg60hq2K35tlqZ1VVywb9yjFzk9AJ7zqxrysOxLi3o= +cloud.google.com/go/apikeys v0.5.0/go.mod h1:5aQfwY4D+ewMMWScd3hm2en3hCj+BROlyrt3ytS7KLI= +cloud.google.com/go/appengine v1.8.5/go.mod h1:uHBgNoGLTS5di7BvU25NFDuKa82v0qQLjyMJLuPQrVo= cloud.google.com/go/appengine v1.8.7/go.mod h1:1Fwg2+QTgkmN6Y+ALGwV8INLbdkI7+vIvhcKPZCML0g= +cloud.google.com/go/area120 v0.8.5/go.mod h1:BcoFCbDLZjsfe4EkCnEq1LKvHSK0Ew/zk5UFu6GMyA0= cloud.google.com/go/area120 v0.8.7/go.mod h1:L/xTq4NLP9mmxiGdcsVz7y1JLc9DI8pfaXRXbnjkR6w= +cloud.google.com/go/artifactregistry v1.14.7/go.mod h1:0AUKhzWQzfmeTvT4SjfI4zjot72EMfrkvL9g9aRjnnM= cloud.google.com/go/artifactregistry v1.14.9/go.mod h1:n2OsUqbYoUI2KxpzQZumm6TtBgtRf++QulEohdnlsvI= +cloud.google.com/go/asset v1.17.2/go.mod h1:SVbzde67ehddSoKf5uebOD1sYw8Ab/jD/9EIeWg99q4= cloud.google.com/go/asset v1.19.1/go.mod h1:kGOS8DiCXv6wU/JWmHWCgaErtSZ6uN5noCy0YwVaGfs= +cloud.google.com/go/assuredworkloads v1.11.5/go.mod h1:FKJ3g3ZvkL2D7qtqIGnDufFkHxwIpNM9vtmhvt+6wqk= cloud.google.com/go/assuredworkloads v1.11.7/go.mod h1:CqXcRH9N0KCDtHhFisv7kk+cl//lyV+pYXGi1h8rCEU= cloud.google.com/go/auth v0.3.0/go.mod h1:lBv6NKTWp8E3LPzmO1TbiiRKc4drLOfHsgmlH9ogv5w= +cloud.google.com/go/automl v1.13.5/go.mod h1:MDw3vLem3yh+SvmSgeYUmUKqyls6NzSumDm9OJ3xJ1Y= cloud.google.com/go/automl v1.13.7/go.mod h1:E+s0VOsYXUdXpq0y4gNZpi0A/s6y9+lAarmV5Eqlg40= +cloud.google.com/go/baremetalsolution v1.2.4/go.mod h1:BHCmxgpevw9IEryE99HbYEfxXkAEA3hkMJbYYsHtIuY= cloud.google.com/go/baremetalsolution v1.2.6/go.mod h1:KkS2BtYXC7YGbr42067nzFr+ABFMs6cxEcA1F+cedIw= +cloud.google.com/go/batch v1.8.0/go.mod h1:k8V7f6VE2Suc0zUM4WtoibNrA6D3dqBpB+++e3vSGYc= cloud.google.com/go/batch v1.8.5/go.mod h1:YSWU2RTIeoHWVwieZJDTLEfWWUsuk10uhAr5K1dTMiw= +cloud.google.com/go/beyondcorp v1.0.4/go.mod h1:Gx8/Rk2MxrvWfn4WIhHIG1NV7IBfg14pTKv1+EArVcc= cloud.google.com/go/beyondcorp v1.0.6/go.mod h1:wRkenqrVRtnGFfnyvIg0zBFUdN2jIfeojFF9JJDwVIA= +cloud.google.com/go/bigquery v1.59.1/go.mod h1:VP1UJYgevyTwsV7desjzNzDND5p6hZB+Z8gZJN1GQUc= cloud.google.com/go/bigquery v1.61.0/go.mod h1:PjZUje0IocbuTOdq4DBOJLNYB0WF3pAKBHzAYyxCwFo= +cloud.google.com/go/billing v1.18.2/go.mod h1:PPIwVsOOQ7xzbADCwNe8nvK776QpfrOAUkvKjCUcpSE= cloud.google.com/go/billing v1.18.5/go.mod h1:lHw7fxS6p7hLWEPzdIolMtOd0ahLwlokW06BzbleKP8= +cloud.google.com/go/binaryauthorization v1.8.1/go.mod h1:1HVRyBerREA/nhI7yLang4Zn7vfNVA3okoAR9qYQJAQ= cloud.google.com/go/binaryauthorization v1.8.3/go.mod h1:Cul4SsGlbzEsWPOz2sH8m+g2Xergb6ikspUyQ7iOThE= +cloud.google.com/go/certificatemanager v1.7.5/go.mod h1:uX+v7kWqy0Y3NG/ZhNvffh0kuqkKZIXdvlZRO7z0VtM= cloud.google.com/go/certificatemanager v1.8.1/go.mod h1:hDQzr50Vx2gDB+dOfmDSsQzJy/UPrYRdzBdJ5gAVFIc= +cloud.google.com/go/channel v1.17.5/go.mod h1:FlpaOSINDAXgEext0KMaBq/vwpLMkkPAw9b2mApQeHc= cloud.google.com/go/channel v1.17.7/go.mod h1:b+FkgBrhMKM3GOqKUvqHFY/vwgp+rwsAuaMd54wCdN4= +cloud.google.com/go/cloudbuild v1.15.1/go.mod h1:gIofXZSu+XD2Uy+qkOrGKEx45zd7s28u/k8f99qKals= cloud.google.com/go/cloudbuild v1.16.1/go.mod h1:c2KUANTtCBD8AsRavpPout6Vx8W+fsn5zTsWxCpWgq4= +cloud.google.com/go/clouddms v1.7.4/go.mod h1:RdrVqoFG9RWI5AvZ81SxJ/xvxPdtcRhFotwdE79DieY= cloud.google.com/go/clouddms v1.7.6/go.mod h1:8HWZ2tznZ0mNAtTpfnRNT0QOThqn9MBUqTj0Lx8npIs= +cloud.google.com/go/cloudtasks v1.12.6/go.mod h1:b7c7fe4+TJsFZfDyzO51F7cjq7HLUlRi/KZQLQjDsaY= cloud.google.com/go/cloudtasks v1.12.8/go.mod h1:aX8qWCtmVf4H4SDYUbeZth9C0n9dBj4dwiTYi4Or/P4= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.23.4/go.mod h1:/EJMj55asU6kAFnuZET8zqgwgJ9FvXWXOkkfQZa4ioI= cloud.google.com/go/compute v1.25.1/go.mod h1:oopOIR53ly6viBYxaDhBfJwzUAxf1zE//uf3IB011ls= cloud.google.com/go/compute v1.26.0 h1:uHf0NN2nvxl1Gh4QO83yRCOdMK4zivtMS5gv0dEX0hg= cloud.google.com/go/compute v1.26.0/go.mod h1:T9RIRap4pVHCGUkVFRJ9hygT3KCXjip41X1GgWtBBII= +cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI= cloud.google.com/go/contactcenterinsights v1.13.2/go.mod h1:AfkSB8t7mt2sIY6WpfO61nD9J9fcidIchtxm9FqJVXk= +cloud.google.com/go/container v1.31.0/go.mod h1:7yABn5s3Iv3lmw7oMmyGbeV6tQj86njcTijkkGuvdZA= cloud.google.com/go/container v1.35.1/go.mod h1:udm8fgLm3TtpnjFN4QLLjZezAIIp/VnMo316yIRVRQU= +cloud.google.com/go/containeranalysis v0.11.4/go.mod h1:cVZT7rXYBS9NG1rhQbWL9pWbXCKHWJPYraE8/FTSYPE= cloud.google.com/go/containeranalysis v0.11.6/go.mod h1:YRf7nxcTcN63/Kz9f86efzvrV33g/UV8JDdudRbYEUI= +cloud.google.com/go/datacatalog v1.19.3/go.mod h1:ra8V3UAsciBpJKQ+z9Whkxzxv7jmQg1hfODr3N3YPJ4= cloud.google.com/go/datacatalog v1.20.1/go.mod h1:Jzc2CoHudhuZhpv78UBAjMEg3w7I9jHA11SbRshWUjk= +cloud.google.com/go/dataflow v0.9.5/go.mod h1:udl6oi8pfUHnL0z6UN9Lf9chGqzDMVqcYTcZ1aPnCZQ= cloud.google.com/go/dataflow v0.9.7/go.mod h1:3BjkOxANrm1G3+/EBnEsTEEgJu1f79mFqoOOZfz3v+E= +cloud.google.com/go/dataform v0.9.2/go.mod h1:S8cQUwPNWXo7m/g3DhWHsLBoufRNn9EgFrMgne2j7cI= cloud.google.com/go/dataform v0.9.4/go.mod h1:jjo4XY+56UrNE0wsEQsfAw4caUs4DLJVSyFBDelRDtQ= +cloud.google.com/go/datafusion v1.7.5/go.mod h1:bYH53Oa5UiqahfbNK9YuYKteeD4RbQSNMx7JF7peGHc= cloud.google.com/go/datafusion v1.7.7/go.mod h1:qGTtQcUs8l51lFA9ywuxmZJhS4ozxsBSus6ItqCUWMU= +cloud.google.com/go/datalabeling v0.8.5/go.mod h1:IABB2lxQnkdUbMnQaOl2prCOfms20mcPxDBm36lps+s= cloud.google.com/go/datalabeling v0.8.7/go.mod h1:/PPncW5gxrU15UzJEGQoOT3IobeudHGvoExrtZ8ZBwo= +cloud.google.com/go/dataplex v1.14.2/go.mod h1:0oGOSFlEKef1cQeAHXy4GZPB/Ife0fz/PxBf+ZymA2U= cloud.google.com/go/dataplex v1.16.0/go.mod h1:OlBoytuQ56+7aUCC03D34CtoF/4TJ5SiIrLsBdDu87Q= +cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataproc/v2 v2.4.0/go.mod h1:3B1Ht2aRB8VZIteGxQS/iNSJGzt9+CA0WGnDVMEm7Z4= cloud.google.com/go/dataproc/v2 v2.4.2/go.mod h1:smGSj1LZP3wtnsM9eyRuDYftNAroAl6gvKp/Wk64XDE= +cloud.google.com/go/dataqna v0.8.5/go.mod h1:vgihg1mz6n7pb5q2YJF7KlXve6tCglInd6XO0JGOlWM= cloud.google.com/go/dataqna v0.8.7/go.mod h1:hvxGaSvINAVH5EJJsONIwT1y+B7OQogjHPjizOFoWOo= +cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= cloud.google.com/go/datastore v1.17.0/go.mod h1:RiRZU0G6VVlIVlv1HRo3vSAPFHULV0ddBNsXO+Sony4= +cloud.google.com/go/datastream v1.10.4/go.mod h1:7kRxPdxZxhPg3MFeCSulmAJnil8NJGGvSNdn4p1sRZo= cloud.google.com/go/datastream v1.10.6/go.mod h1:lPeXWNbQ1rfRPjBFBLUdi+5r7XrniabdIiEaCaAU55o= +cloud.google.com/go/deploy v1.17.1/go.mod h1:SXQyfsXrk0fBmgBHRzBjQbZhMfKZ3hMQBw5ym7MN/50= cloud.google.com/go/deploy v1.18.1/go.mod h1:uyUQPHkz695IbRyyCtmU+jypWZlbd69Le55hhAqEx4A= +cloud.google.com/go/dialogflow v1.49.0/go.mod h1:dhVrXKETtdPlpPhE7+2/k4Z8FRNUp6kMV3EW3oz/fe0= cloud.google.com/go/dialogflow v1.53.0/go.mod h1:LqAvxq7bXiiGC3/DWIz9XXCxth2z2qpSnBAAmlNOj6U= +cloud.google.com/go/dlp v1.11.2/go.mod h1:9Czi+8Y/FegpWzgSfkRlyz+jwW6Te9Rv26P3UfU/h/w= cloud.google.com/go/dlp v1.13.0/go.mod h1:5T/dFtKOn2Q3QLnaKjjir7nEGA8K00WaqoKodLkbF/c= +cloud.google.com/go/documentai v1.25.0/go.mod h1:ftLnzw5VcXkLItp6pw1mFic91tMRyfv6hHEY5br4KzY= cloud.google.com/go/documentai v1.28.0/go.mod h1:ZTt9RkTRmqOn5GQgU4JxHJxbobemOoo6FSy0byEQHqY= +cloud.google.com/go/domains v0.9.5/go.mod h1:dBzlxgepazdFhvG7u23XMhmMKBjrkoUNaw0A8AQB55Y= cloud.google.com/go/domains v0.9.7/go.mod h1:u/yVf3BgfPJW3QDZl51qTJcDXo9PLqnEIxfGmGgbHEc= +cloud.google.com/go/edgecontainer v1.1.5/go.mod h1:rgcjrba3DEDEQAidT4yuzaKWTbkTI5zAMu3yy6ZWS0M= cloud.google.com/go/edgecontainer v1.2.1/go.mod h1:OE2D0lbkmGDVYLCvpj8Y0M4a4K076QB7E2JupqOR/qU= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= +cloud.google.com/go/essentialcontacts v1.6.6/go.mod h1:XbqHJGaiH0v2UvtuucfOzFXN+rpL/aU5BCZLn4DYl1Q= cloud.google.com/go/essentialcontacts v1.6.8/go.mod h1:EHONVDSum2xxG2p+myyVda/FwwvGbY58ZYC4XqI/lDQ= +cloud.google.com/go/eventarc v1.13.4/go.mod h1:zV5sFVoAa9orc/52Q+OuYUG9xL2IIZTbbuTHC6JSY8s= cloud.google.com/go/eventarc v1.13.6/go.mod h1:QReOaYnDNdjwAQQWNC7nfr63WnaKFUw7MSdQ9PXJYj0= +cloud.google.com/go/filestore v1.8.1/go.mod h1:MbN9KcaM47DRTIuLfQhJEsjaocVebNtNQhSLhKCF5GM= cloud.google.com/go/filestore v1.8.3/go.mod h1:QTpkYpKBF6jlPRmJwhLqXfJQjVrQisplyb4e2CwfJWc= +cloud.google.com/go/firestore v1.14.0/go.mod h1:96MVaHLsEhbvkBEdZgfN+AS/GIkco1LRpH9Xp9YZfzQ= cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= +cloud.google.com/go/functions v1.16.0/go.mod h1:nbNpfAG7SG7Duw/o1iZ6ohvL7mc6MapWQVpqtM29n8k= cloud.google.com/go/functions v1.16.2/go.mod h1:+gMvV5E3nMb9EPqX6XwRb646jTyVz8q4yk3DD6xxHpg= +cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= +cloud.google.com/go/gkebackup v1.3.5/go.mod h1:KJ77KkNN7Wm1LdMopOelV6OodM01pMuK2/5Zt1t4Tvc= cloud.google.com/go/gkebackup v1.4.1/go.mod h1:tVwSKC1/UxEA011ijRG8vlXaZThzTSy6vReO9fTOlX8= +cloud.google.com/go/gkeconnect v0.8.5/go.mod h1:LC/rS7+CuJ5fgIbXv8tCD/mdfnlAadTaUufgOkmijuk= cloud.google.com/go/gkeconnect v0.8.7/go.mod h1:iUH1jgQpTyNFMK5LgXEq2o0beIJ2p7KKUUFerkf/eGc= +cloud.google.com/go/gkehub v0.14.5/go.mod h1:6bzqxM+a+vEH/h8W8ec4OJl4r36laxTs3A/fMNHJ0wA= cloud.google.com/go/gkehub v0.14.7/go.mod h1:NLORJVTQeCdxyAjDgUwUp0A6BLEaNLq84mCiulsM4OE= +cloud.google.com/go/gkemulticloud v1.1.1/go.mod h1:C+a4vcHlWeEIf45IB5FFR5XGjTeYhF83+AYIpTy4i2Q= cloud.google.com/go/gkemulticloud v1.1.3/go.mod h1:4WzfPnsOfdCIj6weekE5FIGCaeQKZ1HzGNUVZ1PpIxw= +cloud.google.com/go/grafeas v0.3.4/go.mod h1:A5m316hcG+AulafjAbPKXBO/+I5itU4LOdKO2R/uDIc= +cloud.google.com/go/grafeas v0.3.5/go.mod h1:y54iTBcI+lgUdI+kAPKb8jtPqeTkA2dsYzWSrQtpc5s= +cloud.google.com/go/gsuiteaddons v1.6.5/go.mod h1:Lo4P2IvO8uZ9W+RaC6s1JVxo42vgy+TX5a6hfBZ0ubs= cloud.google.com/go/gsuiteaddons v1.6.7/go.mod h1:u+sGBvr07OKNnOnQiB/Co1q4U2cjo50ERQwvnlcpNis= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/iam v1.1.7/go.mod h1:J4PMPg8TtyurAUvSmPj8FF3EDgY1SPRZxcUGrn7WXGA= +cloud.google.com/go/iap v1.9.4/go.mod h1:vO4mSq0xNf/Pu6E5paORLASBwEmphXEjgCFg7aeNu1w= cloud.google.com/go/iap v1.9.6/go.mod h1:YiK+tbhDszhaVifvzt2zTEF2ch9duHtp6xzxj9a0sQk= +cloud.google.com/go/ids v1.4.5/go.mod h1:p0ZnyzjMWxww6d2DvMGnFwCsSxDJM666Iir1bK1UuBo= cloud.google.com/go/ids v1.4.7/go.mod h1:yUkDC71u73lJoTaoONy0dsA0T7foekvg6ZRg9IJL0AA= +cloud.google.com/go/iot v1.7.5/go.mod h1:nq3/sqTz3HGaWJi1xNiX7F41ThOzpud67vwk0YsSsqs= cloud.google.com/go/iot v1.7.7/go.mod h1:tr0bCOSPXtsg64TwwZ/1x+ReTWKlQRVXbM+DnrE54yM= +cloud.google.com/go/kms v1.15.7/go.mod h1:ub54lbsa6tDkUwnu4W7Yt1aAIFLnspgh0kPGToDukeI= cloud.google.com/go/kms v1.16.0/go.mod h1:olQUXy2Xud+1GzYfiBO9N0RhjsJk5IJLU6n/ethLXVc= +cloud.google.com/go/language v1.12.3/go.mod h1:evFX9wECX6mksEva8RbRnr/4wi/vKGYnAJrTRXU8+f8= cloud.google.com/go/language v1.12.5/go.mod h1:w/6a7+Rhg6Bc2Uzw6thRdKKNjnOzfKTJuxzD0JZZ0nM= +cloud.google.com/go/lifesciences v0.9.5/go.mod h1:OdBm0n7C0Osh5yZB7j9BXyrMnTRGBJIZonUMxo5CzPw= cloud.google.com/go/lifesciences v0.9.7/go.mod h1:FQ713PhjAOHqUVnuwsCe1KPi9oAdaTfh58h1xPiW13g= cloud.google.com/go/logging v1.9.0/go.mod h1:1Io0vnZv4onoUnsVUQY3HZ3Igb1nBchky0A0y7BBBhE= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= cloud.google.com/go/longrunning v0.5.5/go.mod h1:WV2LAxD8/rg5Z1cNW6FJ/ZpX4E4VnDnoTk0yawPBB7s= cloud.google.com/go/longrunning v0.5.6/go.mod h1:vUaDrWYOMKRuhiv6JBnn49YxCPz2Ayn9GqyjaBT8/mA= cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= +cloud.google.com/go/managedidentities v1.6.5/go.mod h1:fkFI2PwwyRQbjLxlm5bQ8SjtObFMW3ChBGNqaMcgZjI= cloud.google.com/go/managedidentities v1.6.7/go.mod h1:UzslJgHnc6luoyx2JV19cTCi2Fni/7UtlcLeSYRzTV8= +cloud.google.com/go/maps v1.6.4/go.mod h1:rhjqRy8NWmDJ53saCfsXQ0LKwBHfi6OSh5wkq6BaMhI= cloud.google.com/go/maps v1.8.0/go.mod h1:b/O9YYxiySNN0N/9swc9SHIM4b4phuoGORN2/H965Ek= +cloud.google.com/go/mediatranslation v0.8.5/go.mod h1:y7kTHYIPCIfgyLbKncgqouXJtLsU+26hZhHEEy80fSs= cloud.google.com/go/mediatranslation v0.8.7/go.mod h1:6eJbPj1QJwiCP8R4K413qMx6ZHZJUi9QFpApqY88xWU= +cloud.google.com/go/memcache v1.10.5/go.mod h1:/FcblbNd0FdMsx4natdj+2GWzTq+cjZvMa1I+9QsuMA= cloud.google.com/go/memcache v1.10.7/go.mod h1:SrU6+QBhvXJV0TA59+B3oCHtLkPx37eqdKmRUlmSE1k= +cloud.google.com/go/metastore v1.13.4/go.mod h1:FMv9bvPInEfX9Ac1cVcRXp8EBBQnBcqH6gz3KvJ9BAE= cloud.google.com/go/metastore v1.13.6/go.mod h1:OBCVMCP7X9vA4KKD+5J4Q3d+tiyKxalQZnksQMq5MKY= +cloud.google.com/go/monitoring v1.18.0/go.mod h1:c92vVBCeq/OB4Ioyo+NbN2U7tlg5ZH41PZcdvfc+Lcg= cloud.google.com/go/monitoring v1.19.0/go.mod h1:25IeMR5cQ5BoZ8j1eogHE5VPJLlReQ7zFp5OiLgiGZw= +cloud.google.com/go/networkconnectivity v1.14.4/go.mod h1:PU12q++/IMnDJAB+3r+tJtuCXCfwfN+C6Niyj6ji1Po= cloud.google.com/go/networkconnectivity v1.14.6/go.mod h1:/azB7+oCSmyBs74Z26EogZ2N3UcXxdCHkCPcz8G32bU= +cloud.google.com/go/networkmanagement v1.9.4/go.mod h1:daWJAl0KTFytFL7ar33I6R/oNBH8eEOX/rBNHrC/8TA= cloud.google.com/go/networkmanagement v1.13.2/go.mod h1:24VrV/5HFIOXMEtVQEUoB4m/w8UWvUPAYjfnYZcBc4c= +cloud.google.com/go/networksecurity v0.9.5/go.mod h1:KNkjH/RsylSGyyZ8wXpue8xpCEK+bTtvof8SBfIhMG8= cloud.google.com/go/networksecurity v0.9.7/go.mod h1:aB6UiPnh/l32+TRvgTeOxVRVAHAFFqvK+ll3idU5BoY= +cloud.google.com/go/notebooks v1.11.3/go.mod h1:0wQyI2dQC3AZyQqWnRsp+yA+kY4gC7ZIVP4Qg3AQcgo= cloud.google.com/go/notebooks v1.11.5/go.mod h1:pz6P8l2TvhWqAW3sysIsS0g2IUJKOzEklsjWJfi8sd4= +cloud.google.com/go/optimization v1.6.3/go.mod h1:8ve3svp3W6NFcAEFr4SfJxrldzhUl4VMUJmhrqVKtYA= cloud.google.com/go/optimization v1.6.5/go.mod h1:eiJjNge1NqqLYyY75AtIGeQWKO0cvzD1ct/moCFaP2Q= +cloud.google.com/go/orchestration v1.8.5/go.mod h1:C1J7HesE96Ba8/hZ71ISTV2UAat0bwN+pi85ky38Yq8= cloud.google.com/go/orchestration v1.9.2/go.mod h1:8bGNigqCQb/O1kK7PeStSNlyi58rQvZqDiuXT9KAcbg= +cloud.google.com/go/orgpolicy v1.12.1/go.mod h1:aibX78RDl5pcK3jA8ysDQCFkVxLj3aOQqrbBaUL2V5I= cloud.google.com/go/orgpolicy v1.12.3/go.mod h1:6BOgIgFjWfJzTsVcib/4QNHOAeOjCdaBj69aJVs//MA= +cloud.google.com/go/osconfig v1.12.5/go.mod h1:D9QFdxzfjgw3h/+ZaAb5NypM8bhOMqBzgmbhzWViiW8= cloud.google.com/go/osconfig v1.12.7/go.mod h1:ID7Lbqr0fiihKMwAOoPomWRqsZYKWxfiuafNZ9j1Y1M= +cloud.google.com/go/oslogin v1.13.1/go.mod h1:vS8Sr/jR7QvPWpCjNqy6LYZr5Zs1e8ZGW/KPn9gmhws= cloud.google.com/go/oslogin v1.13.3/go.mod h1:WW7Rs1OJQ1iSUckZDilvNBSNPE8on740zF+4ZDR4o8U= +cloud.google.com/go/phishingprotection v0.8.5/go.mod h1:g1smd68F7mF1hgQPuYn3z8HDbNre8L6Z0b7XMYFmX7I= cloud.google.com/go/phishingprotection v0.8.7/go.mod h1:FtYaOyGc/HQQU7wY4sfwYZBFDKAL+YtVBjUj8E3A3/I= +cloud.google.com/go/policytroubleshooter v1.10.3/go.mod h1:+ZqG3agHT7WPb4EBIRqUv4OyIwRTZvsVDHZ8GlZaoxk= cloud.google.com/go/policytroubleshooter v1.10.5/go.mod h1:bpOf94YxjWUqsVKokzPBibMSAx937Jp2UNGVoMAtGYI= +cloud.google.com/go/privatecatalog v0.9.5/go.mod h1:fVWeBOVe7uj2n3kWRGlUQqR/pOd450J9yZoOECcQqJk= cloud.google.com/go/privatecatalog v0.9.7/go.mod h1:NWLa8MCL6NkRSt8jhL8Goy2A/oHkvkeAxiA0gv0rIXI= +cloud.google.com/go/pubsub v1.36.1/go.mod h1:iYjCa9EzWOoBiTdd4ps7QoMtMln5NwaZQpK1hbRfBDE= cloud.google.com/go/pubsub v1.38.0/go.mod h1:IPMJSWSus/cu57UyR01Jqa/bNOQA+XnPF6Z4dKW4fAA= cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= +cloud.google.com/go/recaptchaenterprise/v2 v2.9.2/go.mod h1:trwwGkfhCmp05Ll5MSJPXY7yvnO0p4v3orGANAFHAuU= cloud.google.com/go/recaptchaenterprise/v2 v2.13.0/go.mod h1:jNYyn2ScR4DTg+VNhjhv/vJQdaU8qz+NpmpIzEE7HFQ= +cloud.google.com/go/recommendationengine v0.8.5/go.mod h1:A38rIXHGFvoPvmy6pZLozr0g59NRNREz4cx7F58HAsQ= cloud.google.com/go/recommendationengine v0.8.7/go.mod h1:YsUIbweUcpm46OzpVEsV5/z+kjuV6GzMxl7OAKIGgKE= +cloud.google.com/go/recommender v1.12.1/go.mod h1:gf95SInWNND5aPas3yjwl0I572dtudMhMIG4ni8nr+0= cloud.google.com/go/recommender v1.12.3/go.mod h1:OgN0MjV7/6FZUUPgF2QPQtYErtZdZc4u+5onvurcGEI= +cloud.google.com/go/redis v1.14.2/go.mod h1:g0Lu7RRRz46ENdFKQ2EcQZBAJ2PtJHJLuiiRuEXwyQw= cloud.google.com/go/redis v1.14.4/go.mod h1:EnHDflqTNQmCBPCN4FQPZdM28vLdweAgxe6avAZpqug= +cloud.google.com/go/resourcemanager v1.9.5/go.mod h1:hep6KjelHA+ToEjOfO3garMKi/CLYwTqeAw7YiEI9x8= cloud.google.com/go/resourcemanager v1.9.7/go.mod h1:cQH6lJwESufxEu6KepsoNAsjrUtYYNXRwxm4QFE5g8A= +cloud.google.com/go/resourcesettings v1.6.5/go.mod h1:WBOIWZraXZOGAgoR4ukNj0o0HiSMO62H9RpFi9WjP9I= cloud.google.com/go/resourcesettings v1.6.7/go.mod h1:zwRL5ZoNszs1W6+eJYMk6ILzgfnTj13qfU4Wvfupuqk= +cloud.google.com/go/retail v1.16.0/go.mod h1:LW7tllVveZo4ReWt68VnldZFWJRzsh9np+01J9dYWzE= cloud.google.com/go/retail v1.16.2/go.mod h1:T7UcBh4/eoxRBpP3vwZCoa+PYA9/qWRTmOCsV8DRdZ0= +cloud.google.com/go/run v1.3.4/go.mod h1:FGieuZvQ3tj1e9GnzXqrMABSuir38AJg5xhiYq+SF3o= cloud.google.com/go/run v1.3.7/go.mod h1:iEUflDx4Js+wK0NzF5o7hE9Dj7QqJKnRj0/b6rhVq20= +cloud.google.com/go/scheduler v1.10.6/go.mod h1:pe2pNCtJ+R01E06XCDOJs1XvAMbv28ZsQEbqknxGOuE= cloud.google.com/go/scheduler v1.10.8/go.mod h1:0YXHjROF1f5qTMvGTm4o7GH1PGAcmu/H/7J7cHOiHl0= +cloud.google.com/go/secretmanager v1.11.5/go.mod h1:eAGv+DaCHkeVyQi0BeXgAHOU0RdrMeZIASKc+S7VqH4= cloud.google.com/go/secretmanager v1.13.0/go.mod h1:yWdfNmM2sLIiyv6RM6VqWKeBV7CdS0SO3ybxJJRhBEs= +cloud.google.com/go/security v1.15.5/go.mod h1:KS6X2eG3ynWjqcIX976fuToN5juVkF6Ra6c7MPnldtc= cloud.google.com/go/security v1.16.1/go.mod h1:UoF8QXvvJlV9ORs4YW/izW5GmDQtFUoq2P6TJgPlif8= +cloud.google.com/go/securitycenter v1.24.4/go.mod h1:PSccin+o1EMYKcFQzz9HMMnZ2r9+7jbc+LvPjXhpwcU= cloud.google.com/go/securitycenter v1.30.0/go.mod h1:/tmosjS/dfTnzJxOzZhTXdX3MXWsCmPWfcYOgkJmaJk= +cloud.google.com/go/servicecontrol v1.10.0/go.mod h1:pQvyvSRh7YzUF2efw7H87V92mxU8FnFDawMClGCNuAA= +cloud.google.com/go/servicedirectory v1.11.4/go.mod h1:Bz2T9t+/Ehg6x+Y7Ycq5xiShYLD96NfEsWNHyitj1qM= cloud.google.com/go/servicedirectory v1.11.6/go.mod h1:peVGYNc1xArhcqSuhPP+NXp8kdl22XhB5E8IiNBNfZY= +cloud.google.com/go/servicemanagement v1.6.0/go.mod h1:aWns7EeeCOtGEX4OvZUWCCJONRZeFKiptqKf1D0l/Jc= +cloud.google.com/go/serviceusage v1.5.0/go.mod h1:w8U1JvqUqwJNPEOTQjrMHkw3IaIFLoLsPLvsE3xueec= +cloud.google.com/go/shell v1.7.5/go.mod h1:hL2++7F47/IfpfTO53KYf1EC+F56k3ThfNEXd4zcuiE= cloud.google.com/go/shell v1.7.7/go.mod h1:7OYaMm3TFMSZBh8+QYw6Qef+fdklp7CjjpxYAoJpZbQ= +cloud.google.com/go/spanner v1.57.0/go.mod h1:aXQ5QDdhPRIqVhYmnkAdwPYvj/DRN0FguclhEWw+jOo= cloud.google.com/go/spanner v1.61.0/go.mod h1:+hdNE+zL7EWNfOWRetw01jxz8H5qsE/ayZvF/pfrAl8= +cloud.google.com/go/speech v1.21.1/go.mod h1:E5GHZXYQlkqWQwY5xRSLHw2ci5NMQNG52FfMU1aZrIA= cloud.google.com/go/speech v1.23.1/go.mod h1:UNgzNxhNBuo/OxpF1rMhA/U2rdai7ILL6PBXFs70wq0= cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= +cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= cloud.google.com/go/storage v1.40.0/go.mod h1:Rrj7/hKlG87BLqDJYtwR0fbPld8uJPbQ2ucUMY7Ir0g= +cloud.google.com/go/storagetransfer v1.10.4/go.mod h1:vef30rZKu5HSEf/x1tK3WfWrL0XVoUQN/EPDRGPzjZs= cloud.google.com/go/storagetransfer v1.10.6/go.mod h1:3sAgY1bx1TpIzfSzdvNGHrGYldeCTyGI/Rzk6Lc6A7w= +cloud.google.com/go/talent v1.6.6/go.mod h1:y/WQDKrhVz12WagoarpAIyKKMeKGKHWPoReZ0g8tseQ= cloud.google.com/go/talent v1.6.8/go.mod h1:kqPAJvhxmhoUTuqxjjk2KqA8zUEeTDmH+qKztVubGlQ= +cloud.google.com/go/texttospeech v1.7.5/go.mod h1:tzpCuNWPwrNJnEa4Pu5taALuZL4QRRLcb+K9pbhXT6M= cloud.google.com/go/texttospeech v1.7.7/go.mod h1:XO4Wr2VzWHjzQpMe3gS58Oj68nmtXMyuuH+4t0wy9eA= +cloud.google.com/go/tpu v1.6.5/go.mod h1:P9DFOEBIBhuEcZhXi+wPoVy/cji+0ICFi4TtTkMHSSs= cloud.google.com/go/tpu v1.6.7/go.mod h1:o8qxg7/Jgt7TCgZc3jNkd4kTsDwuYD3c4JTMqXZ36hU= +cloud.google.com/go/trace v1.10.5/go.mod h1:9hjCV1nGBCtXbAE4YK7OqJ8pmPYSxPA0I67JwRd5s3M= cloud.google.com/go/trace v1.10.7/go.mod h1:qk3eiKmZX0ar2dzIJN/3QhY2PIFh1eqcIdaN5uEjQPM= +cloud.google.com/go/translate v1.10.1/go.mod h1:adGZcQNom/3ogU65N9UXHOnnSvjPwA/jKQUMnsYXOyk= cloud.google.com/go/translate v1.10.3/go.mod h1:GW0vC1qvPtd3pgtypCv4k4U8B7EdgK9/QEF2aJEUovs= +cloud.google.com/go/video v1.20.4/go.mod h1:LyUVjyW+Bwj7dh3UJnUGZfyqjEto9DnrvTe1f/+QrW0= cloud.google.com/go/video v1.20.6/go.mod h1:d5AOlIfWXpDg15wvztHmjFvKTTImWJU7EnMVWkoiEAk= +cloud.google.com/go/videointelligence v1.11.5/go.mod h1:/PkeQjpRponmOerPeJxNPuxvi12HlW7Em0lJO14FC3I= cloud.google.com/go/videointelligence v1.11.7/go.mod h1:iMCXbfjurmBVgKuyLedTzv90kcnppOJ6ttb0+rLDID0= +cloud.google.com/go/vision/v2 v2.8.0/go.mod h1:ocqDiA2j97pvgogdyhoxiQp2ZkDCyr0HWpicywGGRhU= cloud.google.com/go/vision/v2 v2.8.2/go.mod h1:BHZA1LC7dcHjSr9U9OVhxMtLKd5l2jKPzLRALEJvuaw= +cloud.google.com/go/vmmigration v1.7.5/go.mod h1:pkvO6huVnVWzkFioxSghZxIGcsstDvYiVCxQ9ZH3eYI= cloud.google.com/go/vmmigration v1.7.7/go.mod h1:qYIK5caZY3IDMXQK+A09dy81QU8qBW0/JDTc39OaKRw= +cloud.google.com/go/vmwareengine v1.1.1/go.mod h1:nMpdsIVkUrSaX8UvmnBhzVzG7PPvNYc5BszcvIVudYs= cloud.google.com/go/vmwareengine v1.1.3/go.mod h1:UoyF6LTdrIJRvDN8uUB8d0yimP5A5Ehkr1SRzL1APZw= +cloud.google.com/go/vpcaccess v1.7.5/go.mod h1:slc5ZRvvjP78c2dnL7m4l4R9GwL3wDLcpIWz6P/ziig= cloud.google.com/go/vpcaccess v1.7.7/go.mod h1:EzfSlgkoAnFWEMznZW0dVNvdjFjEW97vFlKk4VNBhwY= +cloud.google.com/go/webrisk v1.9.5/go.mod h1:aako0Fzep1Q714cPEM5E+mtYX8/jsfegAuS8aivxy3U= cloud.google.com/go/webrisk v1.9.7/go.mod h1:7FkQtqcKLeNwXCdhthdXHIQNcFWPF/OubrlyRcLHNuQ= +cloud.google.com/go/websecurityscanner v1.6.5/go.mod h1:QR+DWaxAz2pWooylsBF854/Ijvuoa3FCyS1zBa1rAVQ= cloud.google.com/go/websecurityscanner v1.6.7/go.mod h1:EpiW84G5KXxsjtFKK7fSMQNt8JcuLA8tQp7j0cyV458= +cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= cloud.google.com/go/workflows v1.12.6/go.mod h1:oDbEHKa4otYg4abwdw2Z094jB0TLLiFGAPA78EDAKag= cosmossdk.io/api v0.7.2/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.3/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/errors v1.0.0/go.mod h1:+hJZLuhdDE0pYN8HkOrVNwrIOYvUGnn6+4fjnJs/oV0= cosmossdk.io/log v1.2.0/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= cosmossdk.io/log v1.2.1/go.mod h1:GNSCc/6+DhFIj1aLn/j7Id7PaO8DzNylUZoOYBL9+I4= +cosmossdk.io/log v1.3.0/go.mod h1:HIDyvWLqZe2ovlWabsDN4aPMpY/nUEquAhgfTf2ZzB8= cosmossdk.io/math v1.2.0/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0= cosmossdk.io/store v1.0.0/go.mod h1:ABMprwjvx6IpMp8l06TwuMrj6694/QP5NIW+X6jaTYc= +cosmossdk.io/store v1.0.2/go.mod h1:EFtENTqVTuWwitGW1VwaBct+yDagk7oG/axBMPH+FXs= cosmossdk.io/tools/confix v0.1.0/go.mod h1:TdXKVYs4gEayav5wM+JHT+kTU2J7fozFNqoVaN+8CdY= -cosmossdk.io/tools/confix v0.1.1/go.mod h1:nQVvP1tHsGXS83PonPVWJtSbddIqyjEw99L4M3rPJyQ= cosmossdk.io/x/tx v0.12.0/go.mod h1:qTth2coAGkwCwOCjqQ8EAQg+9udXNRzcnSbMgGKGEI0= +cosmossdk.io/x/tx v0.13.0/go.mod h1:CpNQtmoqbXa33/DVxWQNx5Dcnbkv2xGUhL7tYQ5wUsY= cosmossdk.io/x/upgrade v0.1.0/go.mod h1:/6jjNGbiPCNtmA1N+rBtP601sr0g4ZXuj3yC6ClPCGY= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= @@ -149,17 +277,21 @@ github.com/Abirdcfly/dupword v0.0.11/go.mod h1:wH8mVGuf3CP5fsBTkfWwwwKTjDnVVCxtU github.com/Antonboom/errname v0.1.9/go.mod h1:nLTcJzevREuAsgTbG85UsuiWpMpAqbKD1HNZ29OzE58= github.com/Antonboom/nilnil v0.1.3/go.mod h1:iOov/7gRcXkeEU+EMGpBu2ORih3iyVEiWjeste1SJm8= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0/go.mod h1:OQeznEEkTZ9OrhHJoDD8ZDq51FHgXjqtP9z6bEwBq9U= github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0/go.mod h1:okt5dMMTOFjX/aovMlrjvvXoPMBVSPzk9185BT0+eZM= +github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0/go.mod h1:c+Lifp3EDEamAkPVzMooRNOK6CZjNSdEnf1A7jsI9u4= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0/go.mod h1:+6KLcKIVgxoBDMqMO/Nvy7bZ9a0nbU3I1DtFQK3YvB4= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/CloudyKit/fastprinter v0.0.0-20170127035650-74b38d55f37a/go.mod h1:EFZQ978U7x8IRnstaskI3IysnWY5Ao3QgZUKOXlsAdw= github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno= github.com/CloudyKit/jet v2.1.3-0.20180809161101-62edd43e4f88+incompatible/go.mod h1:HPYO+50pSWkPoj9Q/eq0aRGByCL6ScRlUmiEX5Zgm+w= github.com/CloudyKit/jet/v6 v6.2.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4= -github.com/CosmWasm/wasmvm v1.4.0 h1:84I3MlvvzcOo2z+ed0ztPi7eeDNk6/sYuK76uyXP1nI= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GaijinEntertainment/go-exhaustruct/v2 v2.3.0/go.mod h1:b3g59n2Y+T5xmcxJL+UEG2f8cQploZm1mR/v6BW0mU0= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20190129172621-c8b1d7a94ddf/go.mod h1:aJ4qN3TfrelA6NZ6AXsXRfmEVaYin3EDbSPJrKS8OXo= +github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.0/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= @@ -174,6 +306,7 @@ github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqR github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06/go.mod h1:7erjKLwalezA0k99cWs5L11HWOAPNjdUZ6RxH1BXbbM= github.com/aclements/go-gg v0.0.0-20170118225347-6dbb4e4fefb0/go.mod h1:55qNq4vcpkIuHowELi5C8e+1yUHtoLoOUR9QU5j7Tes= github.com/aclements/go-moremath v0.0.0-20210112150236-f10218a38794/go.mod h1:7e+I0LQFUI9AXWxOfsQROs9xPhoJtbsyWcjJqDd4KPY= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= @@ -184,10 +317,15 @@ github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cv github.com/alingse/asasalint v0.0.11/go.mod h1:nCaoMhw7a9kSJObvQyVzNTPBDbNpdocqrSP7t/cW5+I= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= +github.com/apache/arrow/go/v14 v14.0.2/go.mod h1:u3fgh3EdgN/YQ8cVQRguVW3R+seMybFg8QBQ5LU+eBY= +github.com/apache/arrow/go/v15 v15.0.2/go.mod h1:DGXsR3ajT524njufqf95822i+KTh+yea1jass9YXgjA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/ashanbrown/forbidigo v1.5.1/go.mod h1:Y8j9jy9ZYAEHXdu723cUlraTqbzjKF1MUyfOKL+AjcU= github.com/ashanbrown/makezero v1.1.1/go.mod h1:i1bJLCRSCHOcOa9Y6MyF2FTfMZMFdHvxKHxgO5Z1axI= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aws/aws-sdk-go-v2 v1.21.2/go.mod h1:ErQhvNuEMhJjweavOYhxVkn2RUx7kQXVATHrjKtxIpM= github.com/aws/aws-sdk-go-v2/config v1.18.45/go.mod h1:ZwDUgFnQgsazQTnWfeLWk5GjeqTQTL8lMkoE1UXzxdE= github.com/aws/aws-sdk-go-v2/credentials v1.13.43/go.mod h1:zWJBz1Yf1ZtX5NGax9ZdNjhhI4rgjfgsyk6vTY1yfVg= @@ -195,6 +333,7 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.13/go.mod h1:f/Ib/qYjhV2/qds github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.43/go.mod h1:auo+PiyLl0n1l8A0e8RIeR8tOzYPfZZH/JNlrJ8igTQ= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.37/go.mod h1:Qe+2KtKml+FEsQF/DHmDV+xjtche/hwoF75EG4UlHW8= github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62Mb/iSdSlCNuj6H5ci7tW7OsE= +github.com/aws/aws-sdk-go-v2/service/cloudwatch v1.8.1/go.mod h1:CM+19rL1+4dFWnOQKwDc7H1KwXTz+h61oUSHyhV0b3o= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.37/go.mod h1:vBmDnwWXWxNPFRMmG2m/3MKOe+xEcMDo1tanpaWCcck= github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2/go.mod h1:TQZBt/WaQy+zTHoW++rnl8JBrmZ0VO6EUbVua1+foCA= github.com/aws/aws-sdk-go-v2/service/sso v1.15.2/go.mod h1:gsL4keucRCgW+xA85ALBpRFfdSLH4kHOVSnLMSuBECo= @@ -203,8 +342,10 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.23.2/go.mod h1:Eows6e1uQEsc4ZaHANmsP github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/bits-and-blooms/bitset v1.8.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/blizzy78/varnamelen v0.8.0/go.mod h1:V9TzQZ4fLJ1DSrjVDfl89H7aMnTvKkApdHeyESmyR7k= github.com/bombsimon/wsl/v3 v3.4.0/go.mod h1:KkIB+TXkqy6MvK9BDZVbZxKNYsE1/oLRJbIFtf14qqo= github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= @@ -213,24 +354,33 @@ github.com/breml/bidichk v0.2.4/go.mod h1:7Zk0kRFt1LIZxtQdl9W9JwGAcLTTkOs+tN7wuE github.com/breml/errchkjson v0.3.1/go.mod h1:XroxrzKjdiutFyW3nWhw34VGg7kiMsDQox73yWCGI2U= github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= github.com/bufbuild/buf v1.15.1/go.mod h1:TQeGKam1QMfHy/xsSnnMpxN3JK5HBb6aNvZj4m52gkE= github.com/bufbuild/connect-go v1.5.2/go.mod h1:GmMJYR6orFqD0Y6ZgX8pwQ8j9baizDrIQMm1/a6LnHk= github.com/bufbuild/protocompile v0.5.1/go.mod h1:G5iLmavmF4NsYtpZFvE3B/zFch2GIY8+wjsYLR/lc40= github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/casbin/casbin/v2 v2.37.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/charithe/durationcheck v0.0.10/go.mod h1:bCWXb7gYRysD1CU3C+u4ceO49LoGOY1C1L6uouGNreQ= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= github.com/chigopher/pathlib v0.12.0/go.mod h1:EJ5UtJ/sK8Nt6q3VWN+EwZLZ3g0afJiG8NegYiQQ/gQ= +github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs= +github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs= +github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic= github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= +github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cloudflare/cloudflare-go v0.79.0/go.mod h1:gkHQf9xEubaQPEuerBuoinR9P8bf8a05Lq0X6WKy1Oc= +github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= github.com/cockroachdb/datadriven v1.0.0/go.mod h1:5Ib8Meh+jk1RlHIXej6Pzevx/NLlNvQB9pmSBZErGA4= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= @@ -239,36 +389,42 @@ github.com/cockroachdb/errors v1.8.1/go.mod h1:qGwQn6JmZ+oMjuLwjWzUNqblqk0xl4CVV github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/cockroachdb/pebble v0.0.0-20220817183557-09c6e030a677/go.mod h1:890yq1fUb9b6dGNwssgeUO5vQV9qfXnCPxAJhBQfXw0= github.com/cockroachdb/pebble v0.0.0-20231101195458-481da04154d6/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= +github.com/cockroachdb/pebble v0.0.0-20231102162011-844f0582c2eb/go.mod h1:acMRUGd/BK8AUmQNK3spUCCGzFLZU2bSST3NMXSq2Kc= github.com/cockroachdb/redact v1.0.8/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZZ2lK+dpvRg= github.com/cockroachdb/sentry-go v0.6.1-cockroachdb.2/go.mod h1:8BT+cPK6xvFOcRlk0R8eg+OTkcqI6baNH4xAkpiYVvQ= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM= github.com/cometbft/cometbft v0.38.2/go.mod h1:PIi48BpzwlHqtV3mzwPyQgOyOnU94BNBimLS2ebBHOg= -github.com/cometbft/cometbft v0.38.7/go.mod h1:HIyf811dFMI73IE0F7RrnY/Fr+d1+HuJAgtkEpQjCMY= -github.com/cometbft/cometbft v0.38.9/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= github.com/cometbft/cometbft-db v0.7.0/go.mod h1:yiKJIm2WKrt6x8Cyxtq9YTEcIMPcEe4XPxhgX59Fzf0= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= +github.com/containerd/stargz-snapshotter/estargz v0.12.1/go.mod h1:12VUuCq3qPq4y8yUW+l5w3+oXV3cx2Po3KSe/SmPGqw= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U= github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= +github.com/cosmos/cosmos-proto v1.0.0-beta.4/go.mod h1:oeB+FyVzG3XrQJbJng0EnV8Vljfk9XvTIpGILNU/9Co= github.com/cosmos/cosmos-sdk v0.50.1/go.mod h1:fsLSPGstCwn6MMsFDMAQWGJj8E4sYsN9Gnu1bGE5imA= -github.com/cosmos/cosmos-sdk v0.50.7/go.mod h1:84xDDJEHttRT7NDGwBaUOLVOMN0JNE9x7NbsYIxXs1s= +github.com/cosmos/cosmos-sdk v0.50.3/go.mod h1:tlrkY1sntOt1q0OX/rqF0zRJtmXNoffAS6VFTcky+w8= github.com/cosmos/gogoproto v1.4.3/go.mod h1:0hLIG5TR7IvV1fme1HCFKjfzW9X2x0Mo+RooWXCnOWU= github.com/cosmos/gogoproto v1.4.11/go.mod h1:/g39Mh8m17X8Q/GDEs5zYTSNaNnInBSohtaxzQnYq1Y= github.com/cosmos/iavl v1.0.0/go.mod h1:CmTGqMnRnucjxbjduneZXT+0vPgNElYvdefjX2q9tYc= github.com/cosmos/iavl v1.1.1/go.mod h1:jLeUvm6bGT1YutCaL2fIar/8vGUE8cPZvh/gXEWDaDM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creachadair/atomicfile v0.3.1/go.mod h1:mwfrkRxFKwpNAflYZzytbSwxvbK6fdGRRlp0KEQc0qU= +github.com/creachadair/command v0.0.0-20220916173946-56a74cdd66b6/go.mod h1:jN7ZJM5YSVtD3SHmkAdN/cOC1dXiqg2Y9K5Sr5a8Nxw= github.com/creachadair/tomledit v0.0.24/go.mod h1:9qHbShRWQzSCcn617cMzg4eab1vbLCOjOshAWSzWr8U= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/cristalhq/acmd v0.11.1/go.mod h1:LG5oa43pE/BbxtfMoImHCQN++0Su7dzipdgBjMCBVDQ= github.com/curioswitch/go-reassign v0.2.0/go.mod h1:x6OpXuWvgfQaMGks2BZybTngWjT84hqJfKoO8Tt/Roc= github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/daixiang0/gci v0.10.1/go.mod h1:xtHP9N7AHdNvtRNfcx9gwTDfw7FRJx4bZUsiEfiNNAI= -github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= github.com/denis-tingaikin/go-header v0.4.3/go.mod h1:0wOCWuN71D5qIgE2nz9KrKmuYBAC2Mra5RassOIQ2/c= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v23.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v23.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -280,11 +436,11 @@ github.com/dop251/goja v0.0.0-20230605162241-28ee0ee714f3/go.mod h1:QMWlm50DNe14 github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM= github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emicklei/dot v1.4.2/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/emicklei/dot v1.6.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= -github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/esimonov/ifshort v1.0.4/go.mod h1:Pe8zjlRrJ80+q2CxHLfEOfTwxCZ4O+MuhcHcfgNWTk0= github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= @@ -309,11 +465,14 @@ github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbS github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA= github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell/v2 v2.7.4/go.mod h1:dSXtXTSK0VsW1biw65DZLZ2NKr7j0qP/0J7ONmsraWg= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghemawat/stream v0.0.0-20171120220530-696b145b53b9/go.mod h1:106OIgooyS7OzLDOpUGgm9fA3bQENb/cFSyyBmMoJDs= github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-critic/go-critic v0.7.0/go.mod h1:moYzd7GdVXE2C2hYTwd7h0CPcqlUeclsyBRwMa38v64= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= @@ -323,6 +482,7 @@ github.com/go-fonts/liberation v0.2.0/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2H github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81/go.mod h1:SX0U8uGpxhq9o2S/CELCSUxEWWAuoCUcVCQWv7G2OCk= @@ -332,6 +492,9 @@ github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AE github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0/go.mod h1:hXM6gan18VA1T/daUEHCFcYiW8Ai1tIwIzHY6srfEAw= @@ -339,15 +502,19 @@ github.com/go-toolsmith/astequal v1.0.3/go.mod h1:9Ai4UglvtR+4up+bAD4+hCj7iTo4m/ github.com/go-toolsmith/astequal v1.1.0/go.mod h1:sedf7VIdCL22LD8qIvv7Nn9MuWJruQA/ysswh64lffQ= github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= github.com/go-toolsmith/typep v1.1.0/go.mod h1:fVIw+7zjdsMxDA3ITWnH1yOiw1rnTQKCsF/sk2H/qig= github.com/go-xmlfmt/xmlfmt v1.1.2/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= +github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe/go.mod h1:gjqyPShc/m8pEMpk0a3SeagVb0kaqvhscv+i9jI5ZhQ= @@ -361,67 +528,91 @@ github.com/gonum/floats v0.0.0-20181209220543-c233463c7e82/go.mod h1:PxC8OnwL11+ github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhSyOzRwuXkOgAvijx4o+4YMUJJo9OvPYMkks= github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A= github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw= +github.com/google/flatbuffers v23.5.26+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-containerregistry v0.13.0/go.mod h1:J9FQ+eSS4a1aC2GNZxvNpbWhgp0487v+cgiilB4FqDo= +github.com/google/go-github/v43 v43.0.0/go.mod h1:ZkTvvmCXBvsfPpTHXnH/d2hP9Y0cTbvN9kr5xqyXOIc= +github.com/google/go-pkcs11 v0.2.1-0.20230907215043-c6f79328ddf9/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg= github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go v2.0.0+incompatible h1:j0GKcs05QVmm7yesiZq2+9cxHkNK9YM6zKx4D2qucQU= +github.com/googleapis/gax-go/v2 v2.12.1/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/googleapis/google-cloud-go-testing v0.0.0-20210719221736-1c9a4c676720/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= +github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= github.com/gordonklaus/ineffassign v0.0.0-20230107090616-13ace0543b28/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gostaticanalysis/analysisutil v0.7.1/go.mod h1:v21E3hY37WKMGSnbsw2S/ojApNWb6C1//mXO48CXbVc= github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= github.com/gostaticanalysis/forcetypeassert v0.1.0/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w= github.com/guptarohit/asciigraph v0.5.5/go.mod h1:dYl5wwK4gNsnFf9Zp+l06rFiDZ5YtXM6x7SRWZ3KGag= -github.com/hashicorp/consul/api v1.28.2/go.mod h1:KyzqzgMEya+IZPcD65YFoOVAgPpbfERu4I/tzG6/ueE= +github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g= +github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-getter v1.7.1/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= -github.com/hashicorp/go-getter v1.7.4/go.mod h1:W7TalhMmbPmsSMdNjD0ZskARur/9GJ17cfHTRtXV744= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-metrics v0.5.1/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-metrics v0.5.2/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/hudl/fargo v1.4.0/go.mod h1:9Ai6uvFy5fQNq6VPKtg+Ceq1+eTY4nKUlR2JElEOcDo= github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/hydrogen18/memlistener v1.0.0/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= -github.com/ianlancetaylor/demangle v0.0.0-20220517205856-0058ec4f073c/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/ianlancetaylor/demangle v0.0.0-20240312041847-bd984b5ce465/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/informalsystems/tm-load-test v1.3.0/go.mod h1:OQ5AQ9TbT5hKWBNIwsMjn6Bf4O0U4b1kRc+0qZlQJKw= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= +github.com/iris-contrib/httpexpect/v2 v2.12.1/go.mod h1:7+RB6W5oNClX7PTwJgJnsQP3ZuUUYB3u61KCqeSgZ88= github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI= +github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= github.com/iris-contrib/schema v0.0.6/go.mod h1:iYszG0IOsuIsfzjymw1kMzTL8YQcCWlm65f3wX8J5iA= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jdxcode/netrc v0.0.0-20221124155335-4616370d1a84/go.mod h1:Zi/ZFkEqFHTm7qkjyNJjaWH4LQA9LQhGJyF0lTYGpxw= github.com/jedisct1/go-minisign v0.0.0-20230811132847-661be99b8267/go.mod h1:h1nSAbGFqGVzn6Jyl1R/iCcBUHN4g+gW1u9CoBTrb9E= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= +github.com/jhump/gopoet v0.1.0/go.mod h1:me9yfT6IJSlOL3FCfrg+L6yzUEZ+5jW6WHt4Sk+UPUI= +github.com/jhump/goprotoc v0.5.0/go.mod h1:VrbvcYrQOrTi3i0Vf+m+oqQWk9l72mjkJCYo7UvLHRQ= github.com/jingyugao/rowserrcheck v1.1.1/go.mod h1:4yvlZSDb3IyDTUZJUmpZfm2Hwok+Dtp+nu2qOq+er9c= github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q= github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U= @@ -436,11 +627,14 @@ github.com/kataras/golog v0.0.9/go.mod h1:12HJgwBIZFNGL0EJnMRhmvGA0PQGx8VFwrZtM4 github.com/kataras/golog v0.1.8/go.mod h1:rGPAin4hYROfk1qT9wZP6VY2rsb4zzc37QpdPjdkqVw= github.com/kataras/iris/v12 v12.0.1/go.mod h1:udK4vLQKkdDqMGJJVd/msuMtN6hpYJhg/lSzuxjhO+U= github.com/kataras/iris/v12 v12.2.0/go.mod h1:BLzBpEunc41GbE68OUaQlqX4jzi791mx5HU04uPb90Y= +github.com/kataras/jwt v0.1.8/go.mod h1:Q5j2IkcIHnfwy+oNY3TVWuEBJNw0ADgCcXK9CaZwV4o= github.com/kataras/neffos v0.0.10/go.mod h1:ZYmJC07hQPW67eKuzlfY7SO3bC0mw83A3j6im82hfqw= +github.com/kataras/neffos v0.0.21/go.mod h1:FeGka8lu8cjD2H+0OpBvW8c6xXawy3fj5VX6xcIJ1Fg= github.com/kataras/pio v0.0.0-20190103105442-ea782b38602d/go.mod h1:NV88laa9UiiDuX9AhMbDPkGYSPugBOV6yTZB1l2K9Z0= github.com/kataras/pio v0.0.11/go.mod h1:38hH6SWH6m4DKSYmRhlrCJ5WItwWgCVrTNU62XZyUvI= github.com/kataras/sitemap v0.0.6/go.mod h1:dW4dOCNs896OR1HmG+dMLdT7JjDk7mYBzoIRwuj5jA4= github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwfnHGpYw= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kilic/bls12-381 v0.1.0/go.mod h1:vDTTHJONJ6G+P2R74EhnyotQDTliQDnFEwhdmfzw1ig= github.com/kisielk/errcheck v1.6.3/go.mod h1:nXw/i/MfnvRHqXa7XXmQMUB0oNFGuBrNI8d8NLy0LPw= @@ -452,13 +646,11 @@ github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHU github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= -github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= @@ -468,11 +660,16 @@ github.com/kyoh86/exportloopref v0.1.11/go.mod h1:qkV4UF1zGl6EkF1ox8L5t9SwyeBAZ3 github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/ldez/gomoddirectives v0.2.3/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.4.0/go.mod h1:mNtTfrHy2haaBAw+VT7IBV6VXBThS7TCreYWbBcJ87I= +github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/leonklingele/grouper v1.1.1/go.mod h1:uk3I3uDfi9B6PeUjsCKi6ndcf63Uy7snXgR4yDYQVDY= github.com/linxGnu/grocksdb v1.7.15/go.mod h1:pY55D0o+r8yUYLq70QmhdudxYvoDb9F+9puf4m3/W+U= github.com/linxGnu/grocksdb v1.8.6/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/linxGnu/grocksdb v1.8.12/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lufeee/execinquery v1.2.1/go.mod h1:EC7DrEKView09ocscGHC+apXMIaorh4xqSxS/dy8SbM= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lyft/protoc-gen-star/v2 v2.0.3/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= +github.com/magefile/mage v1.14.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/maratori/testableexamples v1.0.0/go.mod h1:4rhjL1n20TUTT4vdh3RDqSizKLyXp7K2u6HgraZCGzE= @@ -491,57 +688,75 @@ github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQth github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= github.com/mediocregopher/mediocre-go-lib v0.0.0-20181029021733-cb65787f37ed/go.mod h1:dSsfyI2zABAdhcbvkXqgxOxrCsbYeHCPgrZkku60dSg= github.com/mediocregopher/radix/v3 v3.3.0/go.mod h1:EmfVyvspXz1uZEyPBMyGK+kjWiKQGvsUt6O3Pj+LDCQ= +github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= github.com/mgechev/revive v1.3.1/go.mod h1:YlD6TTWl2B8A103R9KWJSPVI9DrEf+oqr15q21Ld+5I= github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4= github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM= -github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/mmcloughlin/avo v0.5.0/go.mod h1:ChHFdoV7ql95Wi7vuq2YT1bwCJqiWdZrQ1im3VujLYM= github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moricho/tparallel v0.3.0/go.mod h1:leENX2cUv7Sv2qDgdi0D0fCftN8fRC67Bcn8pqzeYNI= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= +github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1:FUqVoUPHSEdDR0MnFM3Dh8AU0pZHLXUD127SAJGER/s= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= +github.com/nats-io/jwt/v2 v2.3.0/go.mod h1:0tqz9Hlu6bCBFLWAASKhE5vUA4c24L9KPUUgvwumE/k= +github.com/nats-io/nats-server/v2 v2.5.0/go.mod h1:Kj86UtrXAL6LwYRA6H4RqzkHhK0Vcv2ZnKD5WbQ1t3g= github.com/nats-io/nats.go v1.8.1/go.mod h1:BrFz9vVn0fU3AcH9Vn4Kd7W0NpJ651tD5omQ3M8LwxM= -github.com/nats-io/nats.go v1.34.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= +github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= github.com/nats-io/nkeys v0.0.2/go.mod h1:dab7URMsZm6Z/jp9Z5UGa87Uutgc2mVpXLC4B7TDb/4= -github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= +github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= github.com/nishanths/exhaustive v0.9.5/go.mod h1:IbwrGdVMizvDcIxPYGVdQn5BqWJaOwpCvg4RGb8r/TA= github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c= github.com/nunnatsa/ginkgolinter v0.9.0/go.mod h1:FHaMLURXP7qImeH6bvxWJUpyH+2tuqe5j4rW1gxJRmI= github.com/oasisprotocol/curve25519-voi v0.0.0-20220708102147-0a8a51822cae/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= +github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0= +github.com/ory/dockertest/v3 v3.9.1/go.mod h1:42Ir9hmvaAPm0Mgibk6mBPi7SFvTXxEcnztDYOJ//uM= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= -github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= +github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= github.com/petermattis/goid v0.0.0-20221215004737-a150e88a970d/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= github.com/petermattis/goid v0.0.0-20230904192822-1876fd5063bc/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/phpdave11/gofpdi v1.0.13/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk= +github.com/pointlander/compress v1.1.1-0.20190518213731-ff44bd196cc3/go.mod h1:q5NXNGzqj5uPnVuhGkZfmgHqNUhf15VLi6L9kW0VEc0= +github.com/pointlander/jetset v1.0.1-0.20190518214125-eee7eff80bd4/go.mod h1:RdR1j20Aj5pB6+fw6Y9Ur7lMHpegTEjY1vc19hEZL40= +github.com/pointlander/peg v1.0.1/go.mod h1:5hsGDQR2oZI4QoWz0/Kdg3VSVEC31iJw/b7WjqCBGRI= github.com/polyfloyd/go-errorlint v1.4.5/go.mod h1:sIZEbFoDOCnTYYZoVkjc4hTnM459tuWA9H/EkdXwsKk= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v1.12.0/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= @@ -557,12 +772,20 @@ github.com/prometheus/exporter-toolkit v0.10.0/go.mod h1:+sVFzuvV5JDyw+Ih6p3zFxZ github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/protolambda/bls12-381-util v0.1.0/go.mod h1:cdkysJTRpeFeuUVx/TXGDQNMTiRAalk1vQw3TYTHcE4= +github.com/protolambda/messagediff v1.4.0/go.mod h1:LboJp0EwIbJsePYpzh5Op/9G1/4mIztMRYzzwR0dR2M= github.com/protolambda/zrnt v0.32.2/go.mod h1:A0fezkp9Tt3GBLATSPIbuY4ywYESyAuc/FFmPKg8Lqs= github.com/protolambda/ztyp v0.2.2/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU= +github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk= github.com/quasilyte/go-ruleguard v0.4.0/go.mod h1:Eu76Z/R8IXtViWUIHkE3p8gdH3/PKk1eh3YGfaEof10= +github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20211022131956-028d6511ab71/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/gogrep v0.5.0/go.mod h1:Cm9lpz9NZjEoL1tgZ2OgeUKPIxL1meE7eo60Z6Sk+Ng= github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567/go.mod h1:DWNGW8A4Y+GyBgPuaQJuWiy0XYftx4Xm/y5Jqk9I6VQ= +github.com/remyoudompheng/go-dbus v0.0.0-20121104212943-b7232d34b1d5/go.mod h1:+u151txRmLpwxBmpYn9z3d1sdJdjRPQpsXuYeY9jNls= +github.com/remyoudompheng/go-liblzma v0.0.0-20190506200333-81bf2d431b96/go.mod h1:90HvCY7+oHHUKkbeMCiHt1WuFR2/hPJ9QrljDG+v6ls= +github.com/remyoudompheng/go-misc v0.0.0-20190427085024-2d6ac652a50e/go.mod h1:80FQABjoFzZ2M5uEa6FUaJYEmqU2UOKojlFVak1UAwI= +github.com/rivo/tview v0.0.0-20220307222120-9994674d60a8/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= @@ -571,12 +794,14 @@ github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ruudk/golang-pdf417 v0.0.0-20201230142125-a7e3863a1245/go.mod h1:pQAZKsJ8yyVxGRWYNEm9oFB8ieLgKFnamEyDmSA0BRk= github.com/ryancurrah/gomodguard v1.3.0/go.mod h1:ggBxb3luypPEzqVtq33ee7YSN35V28XeGnid8dnni50= github.com/ryanrolds/sqlclosecheck v0.4.0/go.mod h1:TBRRjzL31JONc9i4XMinicuo+s+E8yKZ5FN8X3G6CKQ= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78= +github.com/sagikazarmark/crypt v0.17.0/go.mod h1:SMtHTvdmsZMuY/bpZoqokSoChIrcJ/epOxZN58PbZDg= +github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/sanposhiho/wastedassign/v2 v2.0.7/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/sashamelentyev/interfacebloat v1.1.0/go.mod h1:+Y9yU5YdTkrNvoX0xHc84dxiN1iBi9+G8zZIhPVoNjQ= github.com/sashamelentyev/usestdlibvars v1.23.0/go.mod h1:YPwr/Y1LATzHI93CqoPUN/2BzGQ/6N/cl/KwgR0B/aU= @@ -587,6 +812,7 @@ github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod github.com/securego/gosec/v2 v2.15.0/go.mod h1:VOjTrZOkUtSDt2QLSJmQBMWnvwiQPEjg0l+5juIqGk8= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= +github.com/shirou/gopsutil/v3 v3.23.2/go.mod h1:gv0aQw33GLo3pG8SiWKiQrbDzbRY1K80RyZJ7V4Th1M= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= @@ -611,9 +837,13 @@ github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1Fof github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stbenjam/no-sprintf-host-port v0.1.1/go.mod h1:TLhvtIvONRzdmkFiio4O8LHsN9N74I+PhRquPsxpL0I= +github.com/strangelove-ventures/cometbft-client v0.1.0/go.mod h1:QzThgjzvsGgUNVNpGPitmxOWMIhp6a0oqf80nCRNt/0= +github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20200128134331-0f66f006fb2e/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -630,6 +860,7 @@ github.com/timakin/bodyclose v0.0.0-20221125081123-e39cf3fc478e/go.mod h1:27bSVN github.com/timonwong/loggercheck v0.9.4/go.mod h1:caz4zlPcgvpEkXgVnAJGowHAMW2NwHaNlpS8xDbVhTg= github.com/tomarrell/wrapcheck/v2 v2.8.1/go.mod h1:/n2Q3NZ4XFT50ho6Hbxg+RV1uyo2Uow/Vdm9NQcl5SE= github.com/tommy-muehle/go-mnd/v2 v2.5.1/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= +github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= @@ -638,7 +869,9 @@ github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn github.com/uudashr/gocognit v1.0.6/go.mod h1:nAIUuVBnYU7pcninia3BHOvQkpQCeO76Uscky5BOwcY= github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w= github.com/valyala/fasthttp v1.40.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/vbatts/tar-split v0.11.2/go.mod h1:vV3ZuO2yWSVsz+pfFzDG/upWH1JhjOiEaWq6kXyQ3VI= github.com/vektra/mockery/v2 v2.23.1/go.mod h1:Zh3Kv1ckKs6FokhlVLcCu6UTyzfS3M8mpROz1lBNp+w= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= @@ -646,9 +879,12 @@ github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xhit/go-str2duration v1.2.0/go.mod h1:3cPSlfZlUHVlneIVfePFWcJZsuwf+P1v2SRTV4cUmp4= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsTACwgXLk= github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= @@ -657,24 +893,35 @@ github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FB github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= gitlab.com/bosi/decorder v0.2.3/go.mod h1:9K1RB5+VPNQYtXtTDAzd2OEftsZb1oV0IrJrzChSdGE= +go.einride.tech/aip v0.66.0/go.mod h1:qAhMsfT7plxBX+Oy7Huol6YUvZ0ZzdUz26yZsQwfl1M= +go.einride.tech/aip v0.67.1/go.mod h1:ZGX4/zKw8dcgzdLsrvpOOGxfxI2QSk12SlP7d6c0/XI= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= -go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= -go.etcd.io/etcd/client/v2 v2.305.12/go.mod h1:aQ/yhsxMu+Oht1FOupSr60oBvcS9cKXHrzBpDsPTf9E= -go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw= +go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI= +go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U= +go.etcd.io/etcd/client/v2 v2.305.10/go.mod h1:m3CKZi69HzilhVqtPDcjhSGp+kA1OmbNn0qamH80xjA= +go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7P1VkOKc= go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU= go.opentelemetry.io/otel v1.22.0/go.mod h1:eoV4iAi3Ea8LkAEI9+GFT44O6T/D0GWAVFyZVCC6pMI= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/metric v1.22.0/go.mod h1:evJGjVpZv0mQ5QBRJoBF64yMuOf4xCWdXjK8pzFvliY= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM= +go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8= go.opentelemetry.io/otel/trace v1.22.0/go.mod h1:RbbHXVqKES9QhzZq/fE5UnOSILqRt40a21sPw2He1xo= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= @@ -689,6 +936,7 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -696,11 +944,12 @@ golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20200513190911-00229845015e/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= @@ -733,7 +982,6 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -745,6 +993,7 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= @@ -752,14 +1001,16 @@ golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/oauth2 v0.0.0-20170207211851-4464e7848382/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8= golang.org/x/perf v0.0.0-20230113213139-801c7ef9e5c5/go.mod h1:UBKtEnL8aqnd+0JHqZ+2qoMDwtuy6cYhhKNoHLBiTQc= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= @@ -788,21 +1039,20 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= +golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= @@ -810,7 +1060,6 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -836,11 +1085,8 @@ golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= -golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= @@ -849,38 +1095,60 @@ gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= gonum.org/v1/plot v0.10.0/go.mod h1:JWIHJ7U20drSQb/aDpTetJzfC1KlAPldJLpkSy88dvQ= gonum.org/v1/plot v0.10.1/go.mod h1:VZW5OlhkL1mysU9vaqNHnsy86inf6Ot+jB3r+BczCEo= google.golang.org/api v0.0.0-20170206182103-3d017632ea10/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= -google.golang.org/api v0.171.0/go.mod h1:Hnq5AHm4OTMt2BUVjael2CWZFD6vksJdWCWiUAmjC9o= +google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.160.0/go.mod h1:0mu0TpK33qnydLvWqbImq2b1eQ5FHRSDCBzAxX9ZHyw= +google.golang.org/api v0.164.0/go.mod h1:2OatzO7ZDQsoS7IFf3rvsE17/TldiU3F/zxFHeqUB5o= +google.golang.org/api v0.166.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= google.golang.org/api v0.176.1/go.mod h1:j2MaSDYcvYV1lkZ1+SMW4IeF90SrEyFA+tluDYWRrFg= google.golang.org/api v0.177.0/go.mod h1:srbhue4MLjkjbkux5p3dw/ocYOSZTaIEvf7bCOnFQDw= google.golang.org/api v0.178.0/go.mod h1:84/k2v8DFpDRebpGcooklv/lais3MEfqpaBLA12gl2U= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= +google.golang.org/genproto v0.0.0-20230227214838-9b19f0bdc514/go.mod h1:TvhZT5f700eVlTNwND1xoEZQeWTB2RY/65kplwl/bFA= google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97/go.mod h1:t1VqOqqvce95G3hIDCT5FeO3YUc6Q4Oe24L/+rNMxRk= google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k= +google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto v0.0.0-20240205150955-31a09d347014/go.mod h1:xEgQu1e4stdSSsxPDK8Azkrk/ECl5HvdPf6nbZrTS5M= google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= google.golang.org/genproto v0.0.0-20240401170217-c3f982113cda/go.mod h1:g2LLCvCeCSir/JJSWosk19BR4NVxGqHUC6rxIRsd7Aw= google.golang.org/genproto/googleapis/api v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:RdyHbowztCGQySiCvQPgWQWgWhGnouTdCflKoDBt32U= google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= -google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= +google.golang.org/genproto/googleapis/api v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/api v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:PVreiBMirk8ypES6aw9d4p6iiBNSIfZEBqr3UGoAi2E= +google.golang.org/genproto/googleapis/api v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8= +google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237/go.mod h1:Z5Iiy3jtmioajWHDGFk7CeugTyHtPvMHA4UTmUkyalE= google.golang.org/genproto/googleapis/api v0.0.0-20240415180920-8c6c420018be/go.mod h1:dvdCTIoAGbkWbcIKBniID56/7XHTt6WfxXNMxuziJ+w= google.golang.org/genproto/googleapis/api v0.0.0-20240429193739-8cf5692501f6/go.mod h1:10yRODfgim2/T8csjQsMPgZOMvtytXKTDRzH6HRGzRw= google.golang.org/genproto/googleapis/api v0.0.0-20240506185236-b8a5c65736ae/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= google.golang.org/genproto/googleapis/api v0.0.0-20240509183442-62759503f434/go.mod h1:FfiGhwUm6CJviekPrc0oJ+7h29e+DmWU6UtjX0ZvI7Y= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:om8Bj876Z0v9ei+RD1LnEWig7vpHQ371PUqsgjmLQEA= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240429193739-8cf5692501f6/go.mod h1:ULqtoQMxDLNRfW+pJbKA68wtIy1OiYjdIsJs3PMpzh8= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:YUWgXUFRPfoYK1IHMuxH5K6nPEXSCzIMljnQ59lLRCk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240228201840-1f18d85a4ec2/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240415180920-8c6c420018be/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= google.golang.org/genproto/googleapis/rpc v0.0.0-20240429193739-8cf5692501f6/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= @@ -888,12 +1156,15 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240506185236-b8a5c65736ae/go. google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/grpc v0.0.0-20170208002647-2a6bf6142e96/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= -google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= @@ -904,6 +1175,10 @@ gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/R gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= honnef.co/go/tools v0.4.3/go.mod h1:36ZgoUOrqOk1GxwHhyryEkq8FQWkUO2xGuSMhUCcdvA= +lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/ccgo/v3 v3.17.0/go.mod h1:Sg3fwVpmLvCUTaqEUjiBDAvshIaKDB0RXaf+zgqFu8I= +moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= mvdan.cc/gofumpt v0.4.0/go.mod h1:PljLOHDeZqgS8opHRKLzp2It2VBuSdteAgqUfzMTxlQ= mvdan.cc/unparam v0.0.0-20221223090309-7455f1af531d/go.mod h1:IeHQjmn6TOD+e4Z3RFiZMMsLVL+A96Nvptar8Fj71is= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index f1181cec..eb96ab4a 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -253,24 +253,24 @@ func TestUserRecoveryTimeLock(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "69c88fa67f3c5aad9b4494618046969f4a8e0dfccaa10def6dbbb5ff192c9924", + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", OutputIdx: 1, - OutputAmount: 7308, + OutputAmount: 3808, }, } outputs := []*OutputTx{ { - ReceiverAddress: "tb1pnlfh96hs3sc0tvanxhqlcfnwz32shff726f8yt6vay4tk62y4c9sluydah", - Amount: 1500, + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, }, } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1p2u4dx80df4xa87fxzw8wrqh698xxa2deu9nyfkjkrfd3fgk3l8dqc0tg3t" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 1f7d4893..6c102102 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -11,7 +11,7 @@ type MultisigInfo struct { EcPubKeys []*btcutil.AddressPubKey NumberRequiredSigs int RecoveryPubKey []byte - RecoveryBlockHeight uint64 + RecoveryLockTime uint64 } type MultisigWallet struct { diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 5aa8f926..3a694229 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -26,10 +26,10 @@ func CreateMultisigTx( changeReceiverAddress string, lockTime uint32, ) (*wire.MsgTx, string, *txscript.TxSigHashes, error) { - msgTx := wire.NewMsgTx(wire.TxVersion) - if lockTime > 0 { - msgTx.LockTime = lockTime - } + msgTx := wire.NewMsgTx(2) + // if lockTime > 0 { + // msgTx.LockTime = lockTime + // } // add TxIns into raw tx // totalInputAmount in external unit @@ -42,7 +42,7 @@ func CreateMultisigTx( } outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) txIn := wire.NewTxIn(outPoint, nil, nil) - txIn.Sequence = uint32(feePerOutput) + txIn.Sequence = lockTime msgTx.AddTxIn(txIn) totalInputAmount += in.OutputAmount diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 65d43f9d..2d6ea113 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -42,14 +42,14 @@ func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][] return privKeys, pubKeys, ECPubKeys } -func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryBlockHeight uint64) ([]string, *MultisigInfo) { +func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryLockTime uint64) ([]string, *MultisigInfo) { privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ PubKeys: pubKeys, EcPubKeys: EcPubKeys, NumberRequiredSigs: k, RecoveryPubKey: pubKeys[recoveryKeyIdx], - RecoveryBlockHeight: recoveryBlockHeight, + RecoveryLockTime: recoveryLockTime, } return privKeys, &vaultInfo diff --git a/utils/multisig/wallet.go b/utils/multisig/wallet.go index a40ca465..3a4f64e3 100644 --- a/utils/multisig/wallet.go +++ b/utils/multisig/wallet.go @@ -48,18 +48,16 @@ func buildMultisigTapScript(numSigsRequired int, pubKeys [][]byte) ([]byte, stri } // Point time lock contract script -// use OP_CHECKLOCKTIMEVERIFY +// use OP_CHECKLOCKTIMEVERIFY or OP_CHECKSEQUENCEVERIFY func buildPTLCTapScript( - expiredBlkHeight uint64, + lockTime uint64, pubKey []byte, ) ([]byte, string, error) { - // OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG - builder := txscript.NewScriptBuilder() - // builder.AddData(new(big.Int).SetUint64(expiredBlkHeight).Bytes()) // TODO: need to fixed length? - builder.AddInt64(int64(expiredBlkHeight)) - builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY) + builder.AddInt64(int64(lockTime)) + // builder.AddOp(txscript.OP_CHECKLOCKTIMEVERIFY) + builder.AddOp(txscript.OP_CHECKSEQUENCEVERIFY) builder.AddOp(txscript.OP_DROP) builder.AddData(toXOnly(pubKey)) builder.AddOp(txscript.OP_CHECKSIG) @@ -169,10 +167,10 @@ func BuildMultisigWallet( return nil, fmt.Errorf("build script multisig err %v", err) } - if multisigInfo.RecoveryBlockHeight == 0 { + if multisigInfo.RecoveryLockTime == 0 { return buildMultisigWalletFromScripts([][]byte{script1}) } else { - script2, _, err := buildPTLCTapScript(multisigInfo.RecoveryBlockHeight, multisigInfo.RecoveryPubKey) + script2, _, err := buildPTLCTapScript(multisigInfo.RecoveryLockTime, multisigInfo.RecoveryPubKey) if err != nil { return nil, fmt.Errorf("build script PTLC err %v", err) } From e54d6e4eb6af95422e8025126084dbe1445bc9d8 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 17 Jul 2024 17:44:05 +0700 Subject: [PATCH 025/113] BB-160 update rune transfering lib --- go.mod | 1 + go.sum | 2 ++ utils/multisig/multisig_test.go | 57 +++++++++++++++++++++++++++++++++ utils/multisig/rune.go | 45 ++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 utils/multisig/rune.go diff --git a/go.mod b/go.mod index 4248b0a1..c752d8eb 100644 --- a/go.mod +++ b/go.mod @@ -234,6 +234,7 @@ require ( github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mtibben/percent v0.2.1 // indirect + github.com/multiformats/go-varint v0.0.7 github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect github.com/oklog/run v1.1.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect diff --git a/go.sum b/go.sum index e946c286..fd531a65 100644 --- a/go.sum +++ b/go.sum @@ -963,6 +963,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= +github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index eb96ab4a..90bba098 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -12,6 +12,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" ) func TestGenerateKeys(t *testing.T) { @@ -293,6 +294,62 @@ func TestUserRecoveryTimeLock(t *testing.T) { hexSignedTx := hex.EncodeToString(signedTx.Bytes()) signedMsgTxID := signedMsgTx.TxHash().String() + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) +} + +func TestTransferRune(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + // Add Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 0 + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + msgTx.AddTxOut(wire.NewTxOut(0, script1)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + fmt.Println("hexSignedTx: ", hexSignedTx) fmt.Println("signedMsgTxID: ", signedMsgTxID) fmt.Println("err sign: ", err) diff --git a/utils/multisig/rune.go b/utils/multisig/rune.go new file mode 100644 index 00000000..9cd276db --- /dev/null +++ b/utils/multisig/rune.go @@ -0,0 +1,45 @@ +package multisig + +import ( + "math/big" + + "github.com/btcsuite/btcd/txscript" + "github.com/multiformats/go-varint" +) + +type Rune struct { + BlockNumber uint64 + TxIndex uint32 +} + +// Varint encoder, ported from +// https://github.com/ordinals/ord/blob/1e6cb641faf3b1eb0aba501a7a2822d7a3dc8643/crates/ordinals/src/varint.rs#L3-L39 +// Using big.Int since go doesn't support u128 +func encodeToSlice(n *big.Int) []byte { + var result []byte + var oneTwentyEight = big.NewInt(128) + + for n.Cmp(oneTwentyEight) >= 0 { + temp := new(big.Int).Mod(n, oneTwentyEight) + tempByte := byte(temp.Uint64()) | 0x80 + result = append(result, tempByte) + n.Div(n, oneTwentyEight) + } + result = append(result, byte(n.Uint64())) + return result +} + +func CreateRuneTransferScript(rune Rune, amount *big.Int, output uint64) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(txscript.OP_13) + + data := varint.ToUvarint(0) + data = append(data, encodeToSlice(big.NewInt(int64(rune.BlockNumber)))...) + data = append(data, encodeToSlice(big.NewInt(int64(rune.TxIndex)))...) + data = append(data, encodeToSlice(amount)...) + data = append(data, encodeToSlice(big.NewInt(int64(output)))...) + + return builder.AddData(data).Script() +} \ No newline at end of file From ea58766819e0b1cfe9b9b21052fd2744ebae49b6 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 19 Jul 2024 10:50:26 +0700 Subject: [PATCH 026/113] BB-160 update runestone decipher --- go.mod | 10 ++++++---- go.sum | 7 +++++++ utils/multisig/multisig_test.go | 13 ++++++++++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index c752d8eb..3a6fcdbc 100644 --- a/go.mod +++ b/go.mod @@ -42,13 +42,14 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bshuster-repo/logrus-logstash-hook v0.4.1 // indirect - github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd // indirect + github.com/btcsuite/btcd v0.24.0 // indirect github.com/btcsuite/btcd/btcutil v1.1.5 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9 // indirect github.com/cespare/cp v1.1.1 // indirect - github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect - github.com/cosmos/ibc-go/v8 v8.3.2 // indirect - github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect + github.com/cosmos/ibc-go/v8 v8.0.0 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 // indirect github.com/evalphobia/logrus_fluent v0.5.4 // indirect @@ -105,6 +106,7 @@ require ( gopkg.in/go-playground/validator.v9 v9.31.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + lukechampine.com/uint128 v1.3.0 // indirect ) require ( diff --git a/go.sum b/go.sum index fd531a65..56f5cc87 100644 --- a/go.sum +++ b/go.sum @@ -324,6 +324,8 @@ github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13P github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd h1:js1gPwhcFflTZ7Nzl7WHaOTlTr5hIrR4n1NM4v9n4Kw= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= +github.com/btcsuite/btcd v0.24.0/go.mod h1:K4IDc1593s8jKXIF7yS7yCTSxrknB9z0STzc2j6XgE4= github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= github.com/btcsuite/btcd/btcec/v2 v2.3.3 h1:6+iXlDKE8RMtKsvK0gshlXIuPbyWM/h84Ensb7o3sC0= @@ -336,6 +338,7 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= @@ -347,6 +350,8 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= +github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9 h1:vQzL9/RqazAbUe0o5OwVCMIQllDl1Nfzvx2JYcwGurI= +github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9/go.mod h1:pieyLaoNj2JsfnMzZm9McEZmGU804aTBsRQNTwqeqVk= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -1944,6 +1949,8 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 90bba098..8c10873a 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/bxelab/runestone" ) func TestGenerateKeys(t *testing.T) { @@ -353,4 +354,14 @@ func TestTransferRune(t *testing.T) { fmt.Println("hexSignedTx: ", hexSignedTx) fmt.Println("signedMsgTxID: ", signedMsgTxID) fmt.Println("err sign: ", err) -} \ No newline at end of file + + // Decipher runestone + r := &runestone.Runestone{} + artifact, err := r.Decipher(signedMsgTx) + if err != nil { + fmt.Println(err) + return + } + a, _ := json.Marshal(artifact) + fmt.Printf("Artifact: %s\n", string(a)) +} From 0e618140e6b5ad82c18b3615f2fdbb397ed559ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=C3=A2n=20Nguy=E1=BB=85n?= <30438379+quankori@users.noreply.github.com> Date: Tue, 30 Jul 2024 11:39:57 +0700 Subject: [PATCH 027/113] Bb 158 relayer btc support init connection between shard of multisig wallet (#2) * feat: add transmission and bitcoin module --------- Co-authored-by: k0r1 --- README.md | 21 +++++ cmd/bitcoin.go | 18 +++++ cmd/root.go | 1 + relayer/chains/bitcoin/client.go | 14 ++++ relayer/chains/bitcoin/master.go | 114 +++++++++++++++++++++++++++ relayer/chains/bitcoin/slave.go | 36 +++++++++ relayer/chains/evm/event_parse.go | 6 +- relayer/chains/icon/query.go | 6 +- relayer/transmission/transmission.go | 38 +++++++++ 9 files changed, 252 insertions(+), 2 deletions(-) create mode 100644 cmd/bitcoin.go create mode 100644 relayer/chains/bitcoin/client.go create mode 100644 relayer/chains/bitcoin/master.go create mode 100644 relayer/chains/bitcoin/slave.go create mode 100644 relayer/transmission/transmission.go diff --git a/README.md b/README.md index cb1df404..9b9d1535 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,24 @@ The following chains are supported: ## How to use ? Refer to the [WIKI](). + +## Bitcoin Relay + +How to run Slave server + +### Prerequisites + +Go 1.x installed +Set up your environment variables as required + +### Start Slave + +```bash +GO_ENV=master MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin +``` + +### Start Master + +```bash +GO_ENV=slave MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin +``` diff --git a/cmd/bitcoin.go b/cmd/bitcoin.go new file mode 100644 index 00000000..c9d56a88 --- /dev/null +++ b/cmd/bitcoin.go @@ -0,0 +1,18 @@ +package cmd + +import ( + "github.com/icon-project/centralized-relay/relayer/chains/bitcoin" + "github.com/spf13/cobra" +) + +func bitcoinCmd(a *appState) *cobra.Command { + bitcoinCmd := &cobra.Command{ + Use: "bitcoin", + Short: "Run Bitcoin Relayer", + Run: func(cmd *cobra.Command, args []string) { + bitcoin.RunApp() + }, + } + + return bitcoinCmd +} diff --git a/cmd/root.go b/cmd/root.go index 6c59a737..1c9dbdd9 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -159,6 +159,7 @@ func NewRootCmd(log *zap.Logger) *cobra.Command { dbCmd(a), keystoreCmd(a), contractCMD(a), + bitcoinCmd(a), ) return rootCmd } diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go new file mode 100644 index 00000000..6cd16abd --- /dev/null +++ b/relayer/chains/bitcoin/client.go @@ -0,0 +1,14 @@ +package bitcoin + +import ( + "os" +) + +func RunApp() { + goEnv := os.Getenv("GO_ENV") + if goEnv == "master" { + startMaster() + } else { + startSlave() + } +} diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go new file mode 100644 index 00000000..754d7a5b --- /dev/null +++ b/relayer/chains/bitcoin/master.go @@ -0,0 +1,114 @@ +package bitcoin + +import ( + "encoding/json" + "fmt" + "io" + "log" + "net/http" + "os" + "sync" +) + +func startMaster() { + go callSlaves() + http.HandleFunc("/execute", handleExecute) + server := &http.Server{ + Addr: "8080", + Handler: nil, + } + + log.Printf("Master starting on port %s", "8080") + log.Fatal(server.ListenAndServe()) +} + +func handleExecute(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) + return + } + + apiKey := r.Header.Get("x-api-key") + if apiKey == "" { + http.Error(w, "Missing API Key", http.StatusUnauthorized) + return + } + apiKeyHeader := os.Getenv("API_KEY") + if apiKey != apiKeyHeader { + http.Error(w, "Invalid API Key", http.StatusForbidden) + return + } + + var msg string + + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Failed to read request body", http.StatusBadRequest) + return + } + defer r.Body.Close() + + err = json.Unmarshal(body, &msg) + if err != nil { + http.Error(w, "Failed to parse JSON", http.StatusBadRequest) + return + } + + // Process the message as needed + fmt.Printf("Received message: %v\n", msg) + + // Send a response + w.WriteHeader(http.StatusOK) + w.Header().Set("Content-Type", "application/json") + response := map[string]string{"status": "success", "msg": msg} + fmt.Println(response) + json.NewEncoder(w).Encode(response) +} + +func callSlaves() { + fmt.Printf("Master request slave") + slavePort := os.Getenv("SLAVE_SERVER") + + // Call slave to get more data + var wg sync.WaitGroup + responses := make(chan string, 2) + + wg.Add(1) + go requestPartialSign(slavePort, responses, &wg) + + go func() { + wg.Wait() + close(responses) + }() + + for res := range responses { + fmt.Println("Received response from slave:", res) + } +} + +func requestPartialSign(url string, responses chan<- string, wg *sync.WaitGroup) { + defer wg.Done() + + client := &http.Client{} + apiKeyHeader := os.Getenv("API_KEY") + + req, err := http.NewRequest("GET", url, nil) + if err != nil { + log.Fatalf("Failed to create request: %v", err) + } + + req.Header.Add("x-api-key", apiKeyHeader) + + resp, err := client.Do(req) + + if err != nil { + log.Fatalf("Failed to send request: %v", err) + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Error reading response: %v", err) + } + + responses <- string(body) +} diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go new file mode 100644 index 00000000..d536b9bf --- /dev/null +++ b/relayer/chains/bitcoin/slave.go @@ -0,0 +1,36 @@ +package bitcoin + +import ( + "log" + "net/http" + "os" +) + +func startSlave() { + http.HandleFunc("/", handleRoot) + server := &http.Server{ + Addr: "8080", + Handler: nil, + } + + log.Printf("Slave starting on port %s", "8080") + log.Fatal(server.ListenAndServe()) +} + +func handleRoot(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodGet { + apiKey := r.Header.Get("x-api-key") + if apiKey == "" { + http.Error(w, "Missing API Key", http.StatusUnauthorized) + return + } + apiKeyHeader := os.Getenv("API_KEY") + if apiKey != apiKeyHeader { + http.Error(w, "Invalid API Key", http.StatusForbidden) + return + } + w.Write([]byte("hello world")) + } else { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + } +} diff --git a/relayer/chains/evm/event_parse.go b/relayer/chains/evm/event_parse.go index 538ae86c..4ee7ee25 100644 --- a/relayer/chains/evm/event_parse.go +++ b/relayer/chains/evm/event_parse.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/ethereum/go-ethereum/core/types" + "github.com/icon-project/centralized-relay/relayer/transmission" providerTypes "github.com/icon-project/centralized-relay/relayer/types" ) @@ -12,7 +13,10 @@ func (p *Provider) getRelayMessageFromLog(log types.Log) (*providerTypes.Message return nil, fmt.Errorf("topic length mismatch") } topic := log.Topics[0] - + // TODO: Bitcoin + if len(topic) != 0 { + transmission.CallBitcoinRelay(topic.Hex()) + } switch topic { case EmitMessageHash: msg, err := p.client.ParseConnectionMessage(log) diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 03123b47..77a010a1 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/icon-project/centralized-relay/relayer/chains/icon/types" + "github.com/icon-project/centralized-relay/relayer/transmission" providerTypes "github.com/icon-project/centralized-relay/relayer/types" "go.uber.org/zap" ) @@ -86,7 +87,10 @@ func (p *Provider) GenerateMessages(ctx context.Context, key *providerTypes.Mess if err != nil { return nil, fmt.Errorf("GenerateMessage:GetTransactionResult %v", err) } - + // TODO: Bitcoin + if err == nil { + transmission.CallBitcoinRelay(string(txResult.BlockHeight)) + } for _, el := range txResult.EventLogs { var ( dst string diff --git a/relayer/transmission/transmission.go b/relayer/transmission/transmission.go new file mode 100644 index 00000000..80ddea00 --- /dev/null +++ b/relayer/transmission/transmission.go @@ -0,0 +1,38 @@ +package transmission + +import ( + "bytes" + "fmt" + "io" + "log" + "net/http" + "os" +) + +func CallBitcoinRelay(message string) []byte { + fmt.Printf("Call Bitcoin Relayer") + masterServer := os.Getenv("MASTER_SERVER") + + client := &http.Client{} + apiKeyHeader := os.Getenv("API_KEY") + + req, err := http.NewRequest("POST", masterServer+"/execute", bytes.NewBuffer([]byte(message))) + if err != nil { + log.Fatalf("Failed to create request: %v", err) + } + + req.Header.Add("x-api-key", apiKeyHeader) + req.Header.Set("Content-Type", "application/json") + + resp, err := client.Do(req) + if err != nil { + log.Fatalf("Failed to send request: %v", err) + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + log.Fatalf("Error reading response: %v", err) + } + return body +} From 178b5fb3944a35a1f339f59e8487d1cb07cf4055 Mon Sep 17 00:00:00 2001 From: Shall Date: Wed, 31 Jul 2024 14:27:08 +0700 Subject: [PATCH 028/113] feat: update master and slave bitcoin relayer --- README.md | 32 +++++++++++++++++++----------- relayer/chains/bitcoin/master.go | 34 ++++++++++++++++++++------------ relayer/chains/bitcoin/slave.go | 17 ++++++++++++---- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 9b9d1535..840aa33b 100644 --- a/README.md +++ b/README.md @@ -9,34 +9,44 @@ The following chains are supported: ## Contract Addresses -| Chain | xCall Address | Connection Address | Networks | Wallets | -|-----------|---------------------------------------------|--------------------------------------------|----------| -------- | -| ICON | cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 | cxb2b31a5252bfcc9be29441c626b8b918d578a58b | lisbon | hxb6b5791be0b5ef67063b3c10b840fb81514db2fd | -| AVALANCHE | 0xAF180CDFE82578dB128088C4D8aa60a38E5CF505 | 0x2500986cCD5e804B206925780e66628e88fE49f3 | fuji | 0xB89596d95b2183722F16d4C30B347dadbf8C941a | -| ICON | cxa07f426062a1384bdd762afa6a87d123fbc81c75 | cxdada6921d08fbf37c6f228816852e58b219cc589 | mainnet | hxda27114a959a3351f3613b055ca96f8f8cb34cbe | -| AVALANCHE | 0xfc83a3f252090b26f92f91dfb9dc3eb710adaf1b | 0xCC7936eA419516635fC6fEb8AD2d4341b5D0C2B3 | mainnet | 0xebA66Ad34CCEB70669eddbaA8c9Fb927d41fE2d7 | +| Chain | xCall Address | Connection Address | Networks | Wallets | +| --------- | ------------------------------------------ | ------------------------------------------ | -------- | ------------------------------------------ | +| ICON | cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 | cxb2b31a5252bfcc9be29441c626b8b918d578a58b | lisbon | hxb6b5791be0b5ef67063b3c10b840fb81514db2fd | +| AVALANCHE | 0xAF180CDFE82578dB128088C4D8aa60a38E5CF505 | 0x2500986cCD5e804B206925780e66628e88fE49f3 | fuji | 0xB89596d95b2183722F16d4C30B347dadbf8C941a | +| ICON | cxa07f426062a1384bdd762afa6a87d123fbc81c75 | cxdada6921d08fbf37c6f228816852e58b219cc589 | mainnet | hxda27114a959a3351f3613b055ca96f8f8cb34cbe | +| AVALANCHE | 0xfc83a3f252090b26f92f91dfb9dc3eb710adaf1b | 0xCC7936eA419516635fC6fEb8AD2d4341b5D0C2B3 | mainnet | 0xebA66Ad34CCEB70669eddbaA8c9Fb927d41fE2d7 | ## How to use ? -Refer to the [WIKI](). +Refer to the [WIKI](https://github.com/icon-project/centralized-relay/wiki). ## Bitcoin Relay -How to run Slave server +How to run Slave server ### Prerequisites Go 1.x installed Set up your environment variables as required -### Start Slave +### Start Slave 1 ```bash -GO_ENV=master MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin +GO_ENV=slave PORT=8081 API_KEY=your_api_key go run main.go bitcoin +``` + +### Start Slave 2 + +```bash +GO_ENV=slave PORT=8082 API_KEY=your_api_key go run main.go bitcoin ``` ### Start Master ```bash -GO_ENV=slave MASTER_SERVER=http://localhost:8080 SLAVE_SERVER=http://localhost:8081 API_KEY=your_api_key go run main.go bitcoin + GO_ENV=master PORT=8080 SLAVE_SERVER_1=http://localhost:8081 SLAVE_SERVER_2=http://localhost:8082 API_KEY=your_api_key go run main.go bitcoin IS_PROCESS=1 ``` + +This env to trigger call the slaves + +- IS_PROCESS=1 diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index 754d7a5b..ef3fe8a9 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -1,6 +1,7 @@ package bitcoin import ( + "bytes" "encoding/json" "fmt" "io" @@ -11,14 +12,19 @@ import ( ) func startMaster() { - go callSlaves() http.HandleFunc("/execute", handleExecute) + port := os.Getenv("PORT") server := &http.Server{ - Addr: "8080", + Addr: ":" + port, Handler: nil, } - log.Printf("Master starting on port %s", "8080") + log.Printf("Master starting on port %s", port) + + isProcess := os.Getenv("IS_PROCESS") + if isProcess == "1" { + callSlaves("test") + } log.Fatal(server.ListenAndServe()) } @@ -55,7 +61,7 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { } // Process the message as needed - fmt.Printf("Received message: %v\n", msg) + fmt.Println("Received message: ", msg) // Send a response w.WriteHeader(http.StatusOK) @@ -65,16 +71,17 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(response) } -func callSlaves() { - fmt.Printf("Master request slave") - slavePort := os.Getenv("SLAVE_SERVER") - +func callSlaves(txId string) { + fmt.Println("Master request slave") + slavePort1 := os.Getenv("SLAVE_SERVER_1") + slavePort2 := os.Getenv("SLAVE_SERVER_2") // Call slave to get more data var wg sync.WaitGroup responses := make(chan string, 2) - wg.Add(1) - go requestPartialSign(slavePort, responses, &wg) + wg.Add(2) + go requestPartialSign(slavePort1, txId, responses, &wg) + go requestPartialSign(slavePort2, txId, responses, &wg) go func() { wg.Wait() @@ -82,17 +89,18 @@ func callSlaves() { }() for res := range responses { - fmt.Println("Received response from slave:", res) + fmt.Println("Received response from slave: ", res) } } -func requestPartialSign(url string, responses chan<- string, wg *sync.WaitGroup) { +func requestPartialSign(url string, txId string, responses chan<- string, wg *sync.WaitGroup) { defer wg.Done() client := &http.Client{} apiKeyHeader := os.Getenv("API_KEY") + payload := bytes.NewBuffer([]byte(txId)) + req, err := http.NewRequest("POST", url, payload) - req, err := http.NewRequest("GET", url, nil) if err != nil { log.Fatalf("Failed to create request: %v", err) } diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index d536b9bf..02b3bf08 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -1,6 +1,7 @@ package bitcoin import ( + "io" "log" "net/http" "os" @@ -8,17 +9,18 @@ import ( func startSlave() { http.HandleFunc("/", handleRoot) + port := os.Getenv("PORT") server := &http.Server{ - Addr: "8080", + Addr: ":" + port, Handler: nil, } - log.Printf("Slave starting on port %s", "8080") + log.Printf("Slave starting on port %s", port) log.Fatal(server.ListenAndServe()) } func handleRoot(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodGet { + if r.Method == http.MethodPost { apiKey := r.Header.Get("x-api-key") if apiKey == "" { http.Error(w, "Missing API Key", http.StatusUnauthorized) @@ -29,7 +31,14 @@ func handleRoot(w http.ResponseWriter, r *http.Request) { http.Error(w, "Invalid API Key", http.StatusForbidden) return } - w.Write([]byte("hello world")) + body, err := io.ReadAll(r.Body) + if err != nil { + http.Error(w, "Error reading request body", http.StatusInternalServerError) + return + } + + log.Printf("Received payload: %s", string(body)) + w.Write([]byte("Payload received" + string(body))) } else { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } From 82b064633c36df481aeac6eba37125b9978f124a Mon Sep 17 00:00:00 2001 From: homelander Date: Fri, 2 Aug 2024 16:46:01 +0700 Subject: [PATCH 029/113] init provide for btc --- relayer/chains/bitcoin/provide.go | 644 ++++++++++++++++++++++++++++++ 1 file changed, 644 insertions(+) create mode 100644 relayer/chains/bitcoin/provide.go diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provide.go new file mode 100644 index 00000000..f8ed0161 --- /dev/null +++ b/relayer/chains/bitcoin/provide.go @@ -0,0 +1,644 @@ +package bitcoin + +import ( + "context" + "fmt" + "math/big" + "runtime" + "strings" + "sync" + "time" + + wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" + coreTypes "github.com/cometbft/cometbft/rpc/core/types" + sdkTypes "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/errors" + "github.com/icon-project/centralized-relay/relayer/chains/wasm/types" + "github.com/icon-project/centralized-relay/relayer/events" + "github.com/icon-project/centralized-relay/relayer/kms" + "github.com/icon-project/centralized-relay/relayer/provider" + relayTypes "github.com/icon-project/centralized-relay/relayer/types" + jsoniter "github.com/json-iterator/go" + "go.uber.org/zap" +) + +//var _ provider.ChainProvider = (*Provider)(nil) + +type Provider struct { + logger *zap.Logger + //cfg *Config + //client IClient + kms kms.KMS + wallet sdkTypes.AccountI + contracts map[string]relayTypes.EventMap + eventList []sdkTypes.Event + LastSavedHeightFunc func() uint64 +} + +func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { + //return p.client.GetLatestBlockHeight(ctx) + return 0, nil +} + +func (p *Provider) QueryTransactionReceipt(ctx context.Context, txHash string) (*relayTypes.Receipt, error) { + //res, err := p.client.GetTransactionReceipt(ctx, txHash) + //if err != nil { + // return nil, err + //} + //return &relayTypes.Receipt{ + // TxHash: txHash, + // Height: uint64(res.TxResponse.Height), + // Status: types.CodeTypeOK == res.TxResponse.Code, + //}, nil + + return nil, nil +} + +func (p *Provider) NID() string { + //return p.cfg.NID + return "" +} + +func (p *Provider) Name() string { + //return p.cfg.ChainName + return "" +} + +func (p *Provider) Init(ctx context.Context, homePath string, kms kms.KMS) error { + //if err := p.cfg.Contracts.Validate(); err != nil { + // return err + //} + //p.kms = kms + return nil +} + +// Wallet returns the wallet of the provider +func (p *Provider) Wallet() sdkTypes.AccAddress { + return nil +} + +func (p *Provider) Type() string { + return types.ChainType +} + +func (p *Provider) Config() provider.Config { + return nil +} + +func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockInfoChan chan *relayTypes.BlockInfo) error { + latestHeight, err := p.QueryLatestHeight(ctx) + if err != nil { + p.logger.Error("failed to get latest block height", zap.Error(err)) + return err + } + + startHeight, err := p.getStartHeight(latestHeight, lastSavedHeight) + if err != nil { + p.logger.Error("failed to determine start height", zap.Error(err)) + return err + } + + subscribeStarter := time.NewTicker(time.Second * 1) + pollHeightTicker := time.NewTicker(time.Second * 1) + pollHeightTicker.Stop() + + resetFunc := func() { + subscribeStarter.Reset(time.Second * 3) + pollHeightTicker.Reset(time.Second * 3) + } + + p.logger.Info("Start from height", zap.Uint64("height", startHeight), zap.Uint64("finality block", p.FinalityBlock(ctx))) + + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-subscribeStarter.C: + subscribeStarter.Stop() + for _, event := range p.contracts { + go p.SubscribeMessageEvents(ctx, blockInfoChan, &types.SubscribeOpts{ + Address: event.Address, + Method: event.GetWasmMsgType(), + Height: latestHeight, + }, resetFunc) + } + case <-pollHeightTicker.C: + pollHeightTicker.Stop() + startHeight = p.GetLastSavedHeight() + latestHeight, err = p.QueryLatestHeight(ctx) + if err != nil { + p.logger.Error("failed to get latest block height", zap.Error(err)) + continue + } + default: + if startHeight < latestHeight { + p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", latestHeight)) + startHeight = p.runBlockQuery(ctx, blockInfoChan, startHeight, latestHeight) + } + } + } +} + +func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { + p.logger.Info("starting to route message", zap.Any("message", message)) + res, err := p.call(ctx, message) + if err != nil { + return err + } + seq := p.wallet.GetSequence() + 1 + if err := p.wallet.SetSequence(seq); err != nil { + p.logger.Error("failed to set sequence", zap.Error(err)) + } + p.waitForTxResult(ctx, message.MessageKey(), res.TxHash, callback) + return nil +} + +// call the smart contract to send the message +func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (*sdkTypes.TxResponse, error) { + rawMsg, err := p.getRawContractMessage(message) + if err != nil { + return nil, err + } + + var contract string + + switch message.EventType { + case events.EmitMessage, events.RevertMessage, events.SetAdmin, events.ClaimFee, events.SetFee: + //contract = p.cfg.Contracts[relayTypes.ConnectionContract] + case events.CallMessage, events.ExecuteRollback: + //contract = p.cfg.Contracts[relayTypes.XcallContract] + default: + return nil, fmt.Errorf("unknown event type: %s ", message.EventType) + } + + msg := &wasmTypes.MsgExecuteContract{ + Sender: p.Wallet().String(), + Contract: contract, + Msg: rawMsg, + } + + msgs := []sdkTypes.Msg{msg} + + res, err := p.sendMessage(ctx, msgs...) + if err != nil { + if strings.Contains(err.Error(), errors.ErrWrongSequence.Error()) { + if mmErr := p.handleSequence(ctx); mmErr != nil { + return res, fmt.Errorf("failed to handle sequence mismatch error: %v || %v", mmErr, err) + } + return p.sendMessage(ctx, msgs...) + } + } + return res, err +} + +func (p *Provider) sendMessage(ctx context.Context, msgs ...sdkTypes.Msg) (*sdkTypes.TxResponse, error) { + return p.prepareAndPushTxToMemPool(ctx, p.wallet.GetAccountNumber(), p.wallet.GetSequence(), msgs...) +} + +func (p *Provider) handleSequence(ctx context.Context) error { + return nil +} + +func (p *Provider) logTxFailed(err error, txHash string, code uint8) { + p.logger.Error("transaction failed", + zap.Error(err), + zap.String("tx_hash", txHash), + zap.Uint8("code", code), + ) +} + +func (p *Provider) logTxSuccess(height uint64, txHash string) { + p.logger.Info("successful transaction", + zap.Uint64("block_height", height), + //zap.String("chain_id", p.cfg.ChainID), + zap.String("tx_hash", txHash), + ) +} + +func (p *Provider) prepareAndPushTxToMemPool(ctx context.Context, acc, seq uint64, msgs ...sdkTypes.Msg) (*sdkTypes.TxResponse, error) { + + return nil, nil +} + +func (p *Provider) waitForTxResult(ctx context.Context, mk *relayTypes.MessageKey, txHash string, callback relayTypes.TxResponseFunc) { + //for txWaitRes := range p.subscribeTxResultStream(ctx, txHash, p.cfg.TxConfirmationInterval) { + // if txWaitRes.Error != nil && txWaitRes.Error != context.DeadlineExceeded { + // p.logTxFailed(txWaitRes.Error, txHash, uint8(txWaitRes.TxResult.Code)) + // callback(mk, txWaitRes.TxResult, txWaitRes.Error) + // return + // } + // p.logTxSuccess(uint64(txWaitRes.TxResult.Height), txHash) + // callback(mk, txWaitRes.TxResult, nil) + //} +} + +func (p *Provider) pollTxResultStream(ctx context.Context, txHash string, maxWaitInterval time.Duration) <-chan *types.TxResultChan { + txResChan := make(chan *types.TxResultChan) + //startTime := time.Now() + //go func(txChan chan *types.TxResultChan) { + // defer close(txChan) + // for range time.NewTicker(p.cfg.TxConfirmationInterval).C { + // res, err := p.client.GetTransactionReceipt(ctx, txHash) + // if err == nil { + // txChan <- &types.TxResultChan{ + // TxResult: &relayTypes.TxResponse{ + // Height: res.TxResponse.Height, + // TxHash: res.TxResponse.TxHash, + // Codespace: res.TxResponse.Codespace, + // Code: relayTypes.ResponseCode(res.TxResponse.Code), + // Data: res.TxResponse.Data, + // }, + // } + // return + // } else if time.Since(startTime) > maxWaitInterval { + // txChan <- &types.TxResultChan{ + // Error: err, + // } + // return + // } + // } + //}(txResChan) + return txResChan +} + +func (p *Provider) subscribeTxResultStream(ctx context.Context, txHash string, maxWaitInterval time.Duration) <-chan *types.TxResultChan { + txResChan := make(chan *types.TxResultChan) + //go func(txRes chan *types.TxResultChan) { + // defer close(txRes) + // + // newCtx, cancel := context.WithTimeout(ctx, maxWaitInterval) + // defer cancel() + // + // query := fmt.Sprintf("tm.event = 'Tx' AND tx.hash = '%s'", txHash) + // resultEventChan, err := p.client.Subscribe(newCtx, "tx-result-waiter", query) + // if err != nil { + // txRes <- &types.TxResultChan{ + // TxResult: &relayTypes.TxResponse{ + // TxHash: txHash, + // }, + // Error: err, + // } + // return + // } + // defer p.client.Unsubscribe(newCtx, "tx-result-waiter", query) + // + // for { + // select { + // case <-ctx.Done(): + // return + // case e := <-resultEventChan: + // eventDataJSON, err := jsoniter.Marshal(e.Data) + // if err != nil { + // txRes <- &types.TxResultChan{ + // TxResult: &relayTypes.TxResponse{ + // TxHash: txHash, + // }, Error: err, + // } + // return + // } + // + // txWaitRes := new(types.TxResultWaitResponse) + // if err := jsoniter.Unmarshal(eventDataJSON, txWaitRes); err != nil { + // txRes <- &types.TxResultChan{ + // TxResult: &relayTypes.TxResponse{ + // TxHash: txHash, + // }, Error: err, + // } + // return + // } + // if uint32(txWaitRes.Result.Code) != types.CodeTypeOK { + // txRes <- &types.TxResultChan{ + // Error: fmt.Errorf(txWaitRes.Result.Log), + // TxResult: &relayTypes.TxResponse{ + // Height: txWaitRes.Height, + // TxHash: txHash, + // Codespace: txWaitRes.Result.Codespace, + // Code: relayTypes.ResponseCode(txWaitRes.Result.Code), + // Data: string(txWaitRes.Result.Data), + // }, + // } + // return + // } + // + // txRes <- &types.TxResultChan{ + // TxResult: &relayTypes.TxResponse{ + // Height: txWaitRes.Height, + // TxHash: txHash, + // Codespace: txWaitRes.Result.Codespace, + // Code: relayTypes.ResponseCode(txWaitRes.Result.Code), + // Data: string(txWaitRes.Result.Data), + // }, + // } + // return + // } + // } + //}(txResChan) + return txResChan +} + +func (p *Provider) MessageReceived(ctx context.Context, key *relayTypes.MessageKey) (bool, error) { + //queryMsg := &types.QueryReceiptMsg{ + // GetReceipt: &types.GetReceiptMsg{ + // SrcNetwork: key.Src, + // ConnSn: strconv.FormatUint(key.Sn, 10), + // }, + //} + //rawQueryMsg, err := jsoniter.Marshal(queryMsg) + //if err != nil { + // return false, err + //} + // + //res, err := p.client.QuerySmartContract(ctx, p.cfg.Contracts[relayTypes.ConnectionContract], rawQueryMsg) + //if err != nil { + // p.logger.Error("failed to check if message is received: ", zap.Error(err)) + // return false, err + //} + // + //receiptMsgRes := types.QueryReceiptMsgResponse{} + //return receiptMsgRes.Status, jsoniter.Unmarshal(res.Data, &receiptMsgRes.Status) + + return false, nil +} + +func (p *Provider) QueryBalance(ctx context.Context, addr string) (*relayTypes.Coin, error) { + //coin, err := p.client.GetBalance(ctx, addr, p.cfg.Denomination) + //if err != nil { + // p.logger.Error("failed to query balance: ", zap.Error(err)) + // return nil, err + //} + //return &relayTypes.Coin{ + // Denom: coin.Denom, + // Amount: coin.Amount.BigInt().Uint64(), + //}, nil + return nil, nil +} + +func (p *Provider) ShouldReceiveMessage(ctx context.Context, message *relayTypes.Message) (bool, error) { + return true, nil +} + +func (p *Provider) ShouldSendMessage(ctx context.Context, message *relayTypes.Message) (bool, error) { + return true, nil +} + +func (p *Provider) GenerateMessages(ctx context.Context, messageKey *relayTypes.MessageKeyWithMessageHeight) ([]*relayTypes.Message, error) { + blocks, err := p.fetchBlockMessages(ctx, &types.HeightRange{messageKey.Height, messageKey.Height}) + if err != nil { + return nil, err + } + var messages []*relayTypes.Message + for _, block := range blocks { + messages = append(messages, block.Messages...) + } + return messages, nil +} + +func (p *Provider) FinalityBlock(ctx context.Context) uint64 { + //return p.cfg.FinalityBlock + return 0 +} + +func (p *Provider) RevertMessage(ctx context.Context, sn *big.Int) error { + msg := &relayTypes.Message{ + Sn: sn.Uint64(), + EventType: events.RevertMessage, + } + _, err := p.call(ctx, msg) + return err +} + +// SetFee +func (p *Provider) SetFee(ctx context.Context, networkdID string, msgFee, resFee uint64) error { + msg := &relayTypes.Message{ + Src: networkdID, + Sn: msgFee, + ReqID: resFee, + EventType: events.SetFee, + } + _, err := p.call(ctx, msg) + return err +} + +// ClaimFee +func (p *Provider) ClaimFee(ctx context.Context) error { + msg := &relayTypes.Message{ + EventType: events.ClaimFee, + } + _, err := p.call(ctx, msg) + return err +} + +// GetFee returns the fee for the given networkID +// responseFee is used to determine if the fee should be returned +func (p *Provider) GetFee(ctx context.Context, networkID string, responseFee bool) (uint64, error) { + //getFee := types.NewExecGetFee(networkID, responseFee) + //data, err := jsoniter.Marshal(getFee) + //if err != nil { + // return 0, err + //} + //return p.client.GetFee(ctx, p.cfg.Contracts[relayTypes.ConnectionContract], data) + + return 0, nil +} + +func (p *Provider) SetAdmin(ctx context.Context, address string) error { + msg := &relayTypes.Message{ + Src: address, + EventType: events.SetAdmin, + } + _, err := p.call(ctx, msg) + return err +} + +// ExecuteRollback +func (p *Provider) ExecuteRollback(ctx context.Context, sn *big.Int) error { + msg := &relayTypes.Message{ + Sn: sn.Uint64(), + EventType: events.ExecuteRollback, + } + _, err := p.call(ctx, msg) + return err +} + +func (p *Provider) getStartHeight(latestHeight, lastSavedHeight uint64) (uint64, error) { + //startHeight := lastSavedHeight + //if p.cfg.StartHeight > 0 && p.cfg.StartHeight < latestHeight { + // return p.cfg.StartHeight, nil + //} + // + //if startHeight > latestHeight { + // return 0, fmt.Errorf("last saved height cannot be greater than latest height") + //} + // + //if startHeight != 0 && startHeight < latestHeight { + // return startHeight, nil + //} + + return latestHeight, nil +} + +func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64) <-chan *types.HeightRange { + heightChan := make(chan *types.HeightRange) + go func(fromHeight, toHeight uint64, heightChan chan *types.HeightRange) { + defer close(heightChan) + for fromHeight < toHeight { + select { + case <-done: + return + case heightChan <- &types.HeightRange{Start: fromHeight, End: fromHeight + 2}: + fromHeight += 2 + } + } + }(fromHeight, toHeight, heightChan) + return heightChan +} + +func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, heightStreamChan <-chan *types.HeightRange) <-chan interface{} { + blockInfoStream := make(chan interface{}) + go func(blockInfoChan chan interface{}, heightChan <-chan *types.HeightRange) { + defer close(blockInfoChan) + for { + select { + case <-done: + return + case height, ok := <-heightChan: + if ok { + for { + messages, err := p.fetchBlockMessages(ctx, height) + if err != nil { + p.logger.Error("failed to fetch block messages", zap.Error(err), zap.Any("height", height)) + time.Sleep(time.Second * 3) + } else { + for _, message := range messages { + blockInfoChan <- message + } + break + } + } + } + } + } + }(blockInfoStream, heightStreamChan) + return blockInfoStream +} + +func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *types.HeightRange) ([]*relayTypes.BlockInfo, error) { + return p.getMessagesFromTxList(nil) +} + +func (p *Provider) getMessagesFromTxList(resultTxList []*coreTypes.ResultTx) ([]*relayTypes.BlockInfo, error) { + //var messages []*relayTypes.BlockInfo + //for _, resultTx := range resultTxList { + // var eventsList []*EventsList + // if err := jsoniter.Unmarshal([]byte(resultTx.TxResult.Log), &eventsList); err != nil { + // return nil, err + // } + // + // for _, event := range eventsList { + // msgs, err := p.ParseMessageFromEvents(event.Events) + // if err != nil { + // return nil, err + // } + // for _, msg := range msgs { + // msg.MessageHeight = uint64(resultTx.Height) + // p.logger.Info("Detected eventlog", + // zap.Uint64("height", msg.MessageHeight), + // zap.String("target_network", msg.Dst), + // zap.Uint64("sn", msg.Sn), + // zap.String("event_type", msg.EventType), + // ) + // } + // messages = append(messages, &relayTypes.BlockInfo{ + // Height: uint64(resultTx.Height), + // Messages: msgs, + // }) + // } + //} + return nil, nil +} + +func (p *Provider) getRawContractMessage(message *relayTypes.Message) (wasmTypes.RawContractMessage, error) { + switch message.EventType { + case events.EmitMessage: + rcvMsg := types.NewExecRecvMsg(message) + return jsoniter.Marshal(rcvMsg) + case events.CallMessage: + execMsg := types.NewExecExecMsg(message) + return jsoniter.Marshal(execMsg) + case events.RevertMessage: + revertMsg := types.NewExecRevertMsg(message) + return jsoniter.Marshal(revertMsg) + case events.SetAdmin: + setAdmin := types.NewExecSetAdmin(message.Dst) + return jsoniter.Marshal(setAdmin) + case events.ClaimFee: + claimFee := types.NewExecClaimFee() + return jsoniter.Marshal(claimFee) + case events.SetFee: + setFee := types.NewExecSetFee(message.Src, message.Sn, message.ReqID) + return jsoniter.Marshal(setFee) + case events.ExecuteRollback: + executeRollback := types.NewExecExecuteRollback(message.Sn) + return jsoniter.Marshal(executeRollback) + default: + return nil, fmt.Errorf("unknown event type: %s ", message.EventType) + } +} + +func (p *Provider) getNumOfPipelines(diff int) int { + if diff <= runtime.NumCPU() { + return diff + } + return runtime.NumCPU() / 2 +} + +func (p *Provider) runBlockQuery(ctx context.Context, blockInfoChan chan *relayTypes.BlockInfo, fromHeight, toHeight uint64) uint64 { + done := make(chan bool) + defer close(done) + + heightStream := p.getHeightStream(done, fromHeight, toHeight) + + diff := int(toHeight-fromHeight) / 2 + + numOfPipelines := p.getNumOfPipelines(diff) + wg := &sync.WaitGroup{} + for i := 0; i < numOfPipelines; i++ { + wg.Add(1) + go func(wg *sync.WaitGroup, heightStream <-chan *types.HeightRange) { + defer wg.Done() + for heightRange := range heightStream { + blockInfo, err := p.fetchBlockMessages(ctx, heightRange) + if err != nil { + p.logger.Error("failed to fetch block messages", zap.Error(err)) + continue + } + var messages []*relayTypes.Message + for _, block := range blockInfo { + messages = append(messages, block.Messages...) + } + blockInfoChan <- &relayTypes.BlockInfo{ + Height: heightRange.End, + Messages: messages, + } + } + }(wg, heightStream) + } + wg.Wait() + return toHeight + 1 +} + +// SubscribeMessageEvents subscribes to the message events +// Expermental: Allows to subscribe to the message events realtime without fully syncing the chain +func (p *Provider) SubscribeMessageEvents(ctx context.Context, blockInfoChan chan *relayTypes.BlockInfo, opts *types.SubscribeOpts, resetFunc func()) error { + return nil +} + +// SetLastSavedHeightFunc sets the function to save the last saved height +func (p *Provider) SetLastSavedHeightFunc(f func() uint64) { + p.LastSavedHeightFunc = f +} + +// GetLastSavedHeight returns the last saved height +func (p *Provider) GetLastSavedHeight() uint64 { + return p.LastSavedHeightFunc() +} From 70b0c209488980d43b6fac5c79d2a882a50ea139 Mon Sep 17 00:00:00 2001 From: homelander Date: Sat, 3 Aug 2024 15:27:16 +0700 Subject: [PATCH 030/113] added iclient and implement function in provide --- go.mod | 2 + go.sum | 2 + relayer/chains/bitcoin/client.go | 99 +++++++++++++++++++++++++++++++ relayer/chains/bitcoin/provide.go | 83 ++++++++++++++++---------- relayer/chains/bitcoin/types.go | 13 ++++ 5 files changed, 169 insertions(+), 30 deletions(-) create mode 100644 relayer/chains/bitcoin/types.go diff --git a/go.mod b/go.mod index 4e1f0c50..3615e431 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,8 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bshuster-repo/logrus-logstash-hook v0.4.1 // 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 github.com/cespare/cp v1.1.1 // indirect github.com/cosmos/ibc-go/v8 v8.0.0 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect diff --git a/go.sum b/go.sum index 497b0e60..45314fbb 100644 --- a/go.sum +++ b/go.sum @@ -338,11 +338,13 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY= diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 6cd16abd..e9b5d9bc 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -2,6 +2,12 @@ package bitcoin import ( "os" + "context" + "github.com/btcsuite/btcd/rpcclient" + "go.uber.org/zap" + // "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/btcjson" ) func RunApp() { @@ -12,3 +18,96 @@ func RunApp() { startSlave() } } + +type IClient interface { + // IsConnected() bool + // Reconnect() error + GetLatestBlockHeight(ctx context.Context) (uint64, error) + GetTransactionReceipt(ctx context.Context, tx string) (*btcjson.TxRawResult, error) + GetBalance(ctx context.Context, addr string) (uint64, error) + + Subscribe(ctx context.Context, _, query string) error + Unsubscribe(ctx context.Context, _, query string) error + GetFee(ctx context.Context) (uint64, error) +} + +// grouped rpc api clients +type Client struct { + log *zap.Logger + client *rpcclient.Client +} + +// create new client +func newClient(rpcUrl, user, pass string, httpPostMode, disableTLS bool, l *zap.Logger) (IClient, error) { + // Connect to the Bitcoin Core RPC server + connConfig := &rpcclient.ConnConfig{ + Host: rpcUrl, + User: user, + Pass: pass, + HTTPPostMode: httpPostMode, + DisableTLS: disableTLS, + } + + client, err := rpcclient.New(connConfig, nil) + if err != nil { + return nil, err + } + + // ws + + return &Client { + log: l, + client: client, + }, nil +} + + +// query block height +func (c *Client) GetLatestBlockHeight(ctx context.Context) (uint64, error) { + // Get the current block height + blockCount, err := c.client.GetBlockCount() + if err != nil { + return 0, err + } + + return uint64(blockCount), nil +} + +// get transaction reciept +func (c *Client) GetTransactionReceipt(ctx context.Context, tx string) (*btcjson.TxRawResult, error) { + // convert to chain hash type + txHash, err := chainhash.NewHashFromStr(tx) + if err != nil { + return nil, err + } + + // query transaction + txVerbose, err := c.client.GetRawTransactionVerbose(txHash) + if err != nil { + return nil, err + } + + return txVerbose, nil +} + +// +func (c *Client) GetBalance(ctx context.Context, addr string) (uint64, error) { + return 0, nil +} + +// +func (c *Client) Subscribe(ctx context.Context, _, query string) error { + // + + return nil +} + +// +func (c *Client) Unsubscribe(ctx context.Context, _, query string) error { + return nil +} + +// test data +func (c *Client) GetFee(ctx context.Context) (uint64, error) { + return 10, nil +} \ No newline at end of file diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provide.go index f8ed0161..58b28fff 100644 --- a/relayer/chains/bitcoin/provide.go +++ b/relayer/chains/bitcoin/provide.go @@ -26,8 +26,8 @@ import ( type Provider struct { logger *zap.Logger - //cfg *Config - //client IClient + // cfg *Config + client IClient kms kms.KMS wallet sdkTypes.AccountI contracts map[string]relayTypes.EventMap @@ -36,22 +36,20 @@ type Provider struct { } func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { - //return p.client.GetLatestBlockHeight(ctx) - return 0, nil + return p.client.GetLatestBlockHeight(ctx) } +// todo: fill up the result func (p *Provider) QueryTransactionReceipt(ctx context.Context, txHash string) (*relayTypes.Receipt, error) { - //res, err := p.client.GetTransactionReceipt(ctx, txHash) - //if err != nil { - // return nil, err - //} - //return &relayTypes.Receipt{ - // TxHash: txHash, - // Height: uint64(res.TxResponse.Height), - // Status: types.CodeTypeOK == res.TxResponse.Code, - //}, nil - - return nil, nil + res, err := p.client.GetTransactionReceipt(ctx, txHash) + if err != nil { + return nil, err + } + return &relayTypes.Receipt{ + TxHash: res.Txid, + // Height: uint64(res.TxResponse.Height), + // Status: types.CodeTypeOK == res.TxResponse.Code, + }, nil } func (p *Provider) NID() string { @@ -382,7 +380,7 @@ func (p *Provider) ShouldSendMessage(ctx context.Context, message *relayTypes.Me } func (p *Provider) GenerateMessages(ctx context.Context, messageKey *relayTypes.MessageKeyWithMessageHeight) ([]*relayTypes.Message, error) { - blocks, err := p.fetchBlockMessages(ctx, &types.HeightRange{messageKey.Height, messageKey.Height}) + blocks, err := p.fetchBlockMessages(ctx, &HeightRange{messageKey.Height, messageKey.Height}) if err != nil { return nil, err } @@ -452,14 +450,10 @@ func (p *Provider) SetAdmin(ctx context.Context, address string) error { // ExecuteRollback func (p *Provider) ExecuteRollback(ctx context.Context, sn *big.Int) error { - msg := &relayTypes.Message{ - Sn: sn.Uint64(), - EventType: events.ExecuteRollback, - } - _, err := p.call(ctx, msg) - return err + return nil } +// todo: func (p *Provider) getStartHeight(latestHeight, lastSavedHeight uint64) (uint64, error) { //startHeight := lastSavedHeight //if p.cfg.StartHeight > 0 && p.cfg.StartHeight < latestHeight { @@ -477,15 +471,15 @@ func (p *Provider) getStartHeight(latestHeight, lastSavedHeight uint64) (uint64, return latestHeight, nil } -func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64) <-chan *types.HeightRange { - heightChan := make(chan *types.HeightRange) - go func(fromHeight, toHeight uint64, heightChan chan *types.HeightRange) { +func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64) <-chan *HeightRange { + heightChan := make(chan *HeightRange) + go func(fromHeight, toHeight uint64, heightChan chan *HeightRange) { defer close(heightChan) for fromHeight < toHeight { select { case <-done: return - case heightChan <- &types.HeightRange{Start: fromHeight, End: fromHeight + 2}: + case heightChan <- &HeightRange{Start: fromHeight, End: fromHeight + 2}: fromHeight += 2 } } @@ -493,9 +487,9 @@ func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64 return heightChan } -func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, heightStreamChan <-chan *types.HeightRange) <-chan interface{} { +func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, heightStreamChan <-chan *HeightRange) <-chan interface{} { blockInfoStream := make(chan interface{}) - go func(blockInfoChan chan interface{}, heightChan <-chan *types.HeightRange) { + go func(blockInfoChan chan interface{}, heightChan <-chan *HeightRange) { defer close(blockInfoChan) for { select { @@ -522,7 +516,36 @@ func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, hei return blockInfoStream } -func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *types.HeightRange) ([]*relayTypes.BlockInfo, error) { +func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { + var ( + wg sync.WaitGroup + errorChan = make(chan error) + // todo: query from provide.config + multisigAddress = "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + ) + + for _, event := range p.eventList { + wg.Add(1) + go func(wg *sync.WaitGroup, searchParam TxSearchParam, messagesChan chan *coreTypes.ResultTxSearch, errorChan chan error) { + defer wg.Done() + searchParam.Events = append(searchParam.Events, event) + res, err := p.client.TxSearch(ctx, searchParam) + if err != nil { + errorChan <- err + return + } + + messagesChan <- res + }(&wg, searchParam, messagesChan, errorChan) + select { + case msgs := <-messagesChan: + messages.Txs = append(messages.Txs, msgs.Txs...) + messages.TotalCount += msgs.TotalCount + case err := <-errorChan: + p.logger.Error("failed to fetch block messages", zap.Error(err)) + } + } + wg.Wait() return p.getMessagesFromTxList(nil) } @@ -604,7 +627,7 @@ func (p *Provider) runBlockQuery(ctx context.Context, blockInfoChan chan *relayT wg := &sync.WaitGroup{} for i := 0; i < numOfPipelines; i++ { wg.Add(1) - go func(wg *sync.WaitGroup, heightStream <-chan *types.HeightRange) { + go func(wg *sync.WaitGroup, heightStream <-chan *HeightRange) { defer wg.Done() for heightRange := range heightStream { blockInfo, err := p.fetchBlockMessages(ctx, heightRange) diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go new file mode 100644 index 00000000..f8ebab54 --- /dev/null +++ b/relayer/chains/bitcoin/types.go @@ -0,0 +1,13 @@ +package bitcoin + +type TxSearchParam struct { + StartHeight, EndHeight uint64 + BitcoinAddress string + OPReturnPrefix byte +} + +// HightRange is a struct to represent a range of heights +type HeightRange struct { + Start uint64 + End uint64 +} \ No newline at end of file From 4c560e6c703c3be1623eb60bc5aec4ba4b94950e Mon Sep 17 00:00:00 2001 From: homelander Date: Sun, 4 Aug 2024 16:07:32 +0700 Subject: [PATCH 031/113] added tx search method --- relayer/chains/bitcoin/client.go | 75 ++++++++++++++++++++++++------- relayer/chains/bitcoin/provide.go | 40 +++++------------ relayer/chains/bitcoin/types.go | 6 +-- 3 files changed, 73 insertions(+), 48 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index e9b5d9bc..fa95210e 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -1,13 +1,16 @@ package bitcoin import ( - "os" "context" + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" "go.uber.org/zap" + "os" // "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/btcjson" ) func RunApp() { @@ -33,12 +36,13 @@ type IClient interface { // grouped rpc api clients type Client struct { - log *zap.Logger - client *rpcclient.Client + log *zap.Logger + client *rpcclient.Client + chainParam *chaincfg.Params } -// create new client -func newClient(rpcUrl, user, pass string, httpPostMode, disableTLS bool, l *zap.Logger) (IClient, error) { +// create new client +func newClient(rpcUrl, user, pass string, httpPostMode, disableTLS bool, l *zap.Logger, chainParam *chaincfg.Params) (IClient, error) { // Connect to the Bitcoin Core RPC server connConfig := &rpcclient.ConnConfig{ Host: rpcUrl, @@ -53,15 +57,15 @@ func newClient(rpcUrl, user, pass string, httpPostMode, disableTLS bool, l *zap. return nil, err } - // ws + // ws - return &Client { - log: l, - client: client, + return &Client{ + log: l, + client: client, + chainParam: chainParam, }, nil } - // query block height func (c *Client) GetLatestBlockHeight(ctx context.Context) (uint64, error) { // Get the current block height @@ -90,24 +94,61 @@ func (c *Client) GetTransactionReceipt(ctx context.Context, tx string) (*btcjson return txVerbose, nil } -// func (c *Client) GetBalance(ctx context.Context, addr string) (uint64, error) { return 0, nil } -// func (c *Client) Subscribe(ctx context.Context, _, query string) error { - // + // return nil } -// func (c *Client) Unsubscribe(ctx context.Context, _, query string) error { - return nil + return nil } // test data func (c *Client) GetFee(ctx context.Context) (uint64, error) { return 10, nil -} \ No newline at end of file +} + +func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*wire.MsgTx, error) { + // + res := []*wire.MsgTx{} + meetRequirements := 0 + + for i := param.StartHeight; i <= param.EndHeight; i++ { + blockHash, err := c.client.GetBlockHash(int64(i)) + if err != nil { + return nil, err + } + + block, err := c.client.GetBlock(blockHash) + // loop thru transactions + for _, tx := range block.Transactions { + // loop thru tx output + for _, txOutput := range tx.TxOut { + if len(txOutput.PkScript) > 2 { + // check OP_RETURN + if txOutput.PkScript[0] == txscript.OP_RETURN && txOutput.PkScript[1] == txscript.OP_13 { + meetRequirements++ + } + + // check EQUAL to multisig script + //if { + // meetRequirements++ + //} + + if meetRequirements == 2 { + res = append(res, tx) + break + } + } + } + meetRequirements = 0 + } + } + + return res, nil +} diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provide.go index 58b28fff..1d3e5064 100644 --- a/relayer/chains/bitcoin/provide.go +++ b/relayer/chains/bitcoin/provide.go @@ -517,35 +517,19 @@ func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, hei } func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { - var ( - wg sync.WaitGroup - errorChan = make(chan error) - // todo: query from provide.config - multisigAddress = "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - ) + //var ( + // // todo: query from provide.config + // multisigAddress = "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + // preFixOP = txscript.OP_13 + //) + // + //searchParam := TxSearchParam{ + // StartHeight: heightInfo.Start, + // EndHeight: heightInfo.End, + // BitcoinAddress: multisigAddress, + // OPReturnPrefix: preFixOP, + //} - for _, event := range p.eventList { - wg.Add(1) - go func(wg *sync.WaitGroup, searchParam TxSearchParam, messagesChan chan *coreTypes.ResultTxSearch, errorChan chan error) { - defer wg.Done() - searchParam.Events = append(searchParam.Events, event) - res, err := p.client.TxSearch(ctx, searchParam) - if err != nil { - errorChan <- err - return - } - - messagesChan <- res - }(&wg, searchParam, messagesChan, errorChan) - select { - case msgs := <-messagesChan: - messages.Txs = append(messages.Txs, msgs.Txs...) - messages.TotalCount += msgs.TotalCount - case err := <-errorChan: - p.logger.Error("failed to fetch block messages", zap.Error(err)) - } - } - wg.Wait() return p.getMessagesFromTxList(nil) } diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index f8ebab54..85944f71 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -2,12 +2,12 @@ package bitcoin type TxSearchParam struct { StartHeight, EndHeight uint64 - BitcoinAddress string - OPReturnPrefix byte + BitcoinAddress string + OPReturnPrefix int } // HightRange is a struct to represent a range of heights type HeightRange struct { Start uint64 End uint64 -} \ No newline at end of file +} From af783bbca1c3c351d3beb7abbd56ac94ff7344fd Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Sun, 4 Aug 2024 22:33:47 +0700 Subject: [PATCH 032/113] BB-31 update encoder and decoder for ICON bitcoin bridge --- utils/multisig/multisig_test.go | 68 +++++++++++++++ utils/multisig/op_message.go | 150 ++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 utils/multisig/op_message.go diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 8c10873a..08dae838 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -365,3 +365,71 @@ func TestTransferRune(t *testing.T) { a, _ := json.Marshal(artifact) fmt.Printf("Artifact: %s\n", string(a)) } + +func TestTransferBitcoinWithBridgeMessage(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + // Add Bridge Message + + message := []byte("Test Bridge Message") + scripts, _ := CreateBridgeMessageScripts(message, 5) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + msgTx.AddTxOut(wire.NewTxOut(0, script)) + } + + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decode bridge message + decodedMessage, err := readRelayMessage(signedMsgTx, false) + fmt.Println("err decode: ", err) + fmt.Println("origina message: ", message) + fmt.Println("decoded message: ", decodedMessage) +} \ No newline at end of file diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go new file mode 100644 index 00000000..08b1d633 --- /dev/null +++ b/utils/multisig/op_message.go @@ -0,0 +1,150 @@ +package multisig + +import ( + "fmt" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" +) + +const ( + OP_RADFI_IDENT = txscript.OP_12 + OP_RUNE_IDENT = txscript.OP_13 + OP_BRIDGE_IDENT = txscript.OP_14 + + OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 + OP_RADFI_SWAP = txscript.OP_2 + OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 + OP_RADFI_COLLECT_FEE = txscript.OP_4 +) + +type RadFiProvideLiquidityMsg struct { + Fee []byte + UpperTick []byte + LowerTick []byte + Min0 []byte + Min1 []byte +} + +type RadFiDecodedMsg struct { + Flag []byte + ProvideLiquidityMsg RadFiProvideLiquidityMsg +} + +// func createProvideLiquidityScript(fee uint8, upperTick uint32) ([]byte, error) { +// builder := txscript.NewScriptBuilder() + +// builder.AddOp(txscript.OP_RETURN) +// builder.AddOp(OP_RADFI_IDENT) + +// return builder.Script() +// } + +func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { + var chunk []byte + chunks := make([][]byte, 0, len(payload)/partLimit+1) + for len(payload) >= partLimit { + chunk, payload = payload[:partLimit], payload[partLimit:] + chunks = append(chunks, chunk) + } + if len(payload) > 0 { + chunks = append(chunks, payload) + } + + scripts := [][]byte{} + for _, part := range chunks { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_BRIDGE_IDENT) + builder.AddData(part) + + script, err := builder.Script() + if err != nil { + return nil, fmt.Errorf("could not build script - Error %v", err) + } + scripts = append(scripts, script) + } + + return scripts, nil +} + +func readRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { + var payload []byte + for _, output := range transaction.TxOut { + tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) + if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != txscript.OP_RETURN { + // Check for OP_RETURN + continue + } + if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() == OP_RUNE_IDENT { + // Check to ignore Rune protocol identifier (Runestone::MAGIC_NUMBER) + continue + } + + if (isRadFi && tokenizer.Opcode() != OP_RADFI_IDENT) || ((!isRadFi && tokenizer.Opcode() != OP_BRIDGE_IDENT)){ + // Check for Relayer protocol identifier (RadFi or ICON Bridge) + continue + } + + // Construct the payload by concatenating remaining data pushes + for tokenizer.Next() { + if tokenizer.Err() != nil { + return nil, tokenizer.Err() + } + payload = append(payload, tokenizer.Data()...) + } + + // only read 1 message output for radfi protocol + if isRadFi { + break + } + } + + return payload, nil +} + +// func decodeRadFiMessage(payload []byte) (*DecodedMsg, error) { +// tokenizer := txscript.MakeScriptTokenizer(0, payload) + +// // take the flag +// if !tokenizer.Next() || tokenizer.Err() != nil { +// return nil, fmt.Errorf("decodeRadFiMessage could not read the flag - Error %v", tokenizer.Err()) +// } +// flag := tokenizer.Opcode() + +// switch flag { +// case OP_RADFI_PROVIDE_LIQUIDITY: +// if !tokenizer.Next() || tokenizer.Err() != nil { +// return nil, fmt.Errorf("decodeRadFiMessage could not read the ProvideLiquidityMsg Fee - Error %v", tokenizer.Err()) +// } +// fee := +// return &DecodedMsg { +// Flag : flag, +// ProvideLiquidityMsg: RadFiProvideLiquidityMsg { +// Fee : , +// UpperTick : , +// LowerTick : , +// Min0 : , +// Min1 : , +// } +// } +// case 2: +// fmt.Println("two") +// case 3: +// fmt.Println("three") +// default: +// fmt.Println("It's after noon") +// } + + +// return payload, nil +// } + +// func nextToken(tokenizer *txscript.ScriptTokenizer) ([]byte, error) { +// if !tokenizer.Next() || tokenizer.Err() != nil { +// return nil, fmt.Errorf("decodeRadFiMessage could not read the flag - Error %v", tokenizer.Err()) +// } + +// return tokenizer.Opcode() +// } \ No newline at end of file From f0ecd0df82ca7914dec9457e99ce094ff6a02ae8 Mon Sep 17 00:00:00 2001 From: homelander Date: Mon, 5 Aug 2024 20:34:39 +0700 Subject: [PATCH 033/113] imple gettx detail --- relayer/chains/bitcoin/client.go | 43 ++++++++++---- relayer/chains/bitcoin/provide.go | 98 ++++++++++++++++++------------- relayer/chains/bitcoin/types.go | 9 ++- 3 files changed, 95 insertions(+), 55 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index fa95210e..483c1adb 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -1,12 +1,13 @@ package bitcoin import ( + "bytes" "context" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" "go.uber.org/zap" "os" // "github.com/btcsuite/btcd/wire" @@ -32,6 +33,8 @@ type IClient interface { Subscribe(ctx context.Context, _, query string) error Unsubscribe(ctx context.Context, _, query string) error GetFee(ctx context.Context) (uint64, error) + DecodeAddress(btcAddr string) ([]byte, error) + TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearchRes, error) } // grouped rpc api clients @@ -113,10 +116,11 @@ func (c *Client) GetFee(ctx context.Context) (uint64, error) { return 10, nil } -func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*wire.MsgTx, error) { +func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearchRes, error) { // - res := []*wire.MsgTx{} - meetRequirements := 0 + res := []*TxSearchRes{} + meetRequirement1 := 0 + meetRequirement2 := 0 for i := param.StartHeight; i <= param.EndHeight; i++ { blockHash, err := c.client.GetBlockHash(int64(i)) @@ -131,24 +135,39 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*wire.Msg for _, txOutput := range tx.TxOut { if len(txOutput.PkScript) > 2 { // check OP_RETURN - if txOutput.PkScript[0] == txscript.OP_RETURN && txOutput.PkScript[1] == txscript.OP_13 { - meetRequirements++ + if txOutput.PkScript[0] == txscript.OP_RETURN && txOutput.PkScript[1] == byte(param.OPReturnPrefix) { + meetRequirement1++ } // check EQUAL to multisig script - //if { - // meetRequirements++ - //} + if bytes.Equal(param.BitcoinScript, txOutput.PkScript) { + meetRequirement2++ + } - if meetRequirements == 2 { - res = append(res, tx) + if meetRequirement2*meetRequirement1 != 0 { + res = append(res, &TxSearchRes{Height: i, Tx: tx}) break } } } - meetRequirements = 0 + meetRequirement2 = 0 + meetRequirement1 = 0 } } return res, nil } + +func (c *Client) DecodeAddress(btcAddr string) ([]byte, error) { + // return bitcoin script value + decodedAddr, err := btcutil.DecodeAddress(btcAddr, c.chainParam) + if err != nil { + return nil, err + } + destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) + if err != nil { + return nil, err + } + + return destinationAddrByte, nil +} diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provide.go index 1d3e5064..e437a12e 100644 --- a/relayer/chains/bitcoin/provide.go +++ b/relayer/chains/bitcoin/provide.go @@ -3,6 +3,7 @@ package bitcoin import ( "context" "fmt" + "github.com/btcsuite/btcd/txscript" "math/big" "runtime" "strings" @@ -10,7 +11,6 @@ import ( "time" wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" - coreTypes "github.com/cometbft/cometbft/rpc/core/types" sdkTypes "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/errors" "github.com/icon-project/centralized-relay/relayer/chains/wasm/types" @@ -33,6 +33,7 @@ type Provider struct { contracts map[string]relayTypes.EventMap eventList []sdkTypes.Event LastSavedHeightFunc func() uint64 + multisigAddrScript []byte } func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { @@ -517,50 +518,63 @@ func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, hei } func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { - //var ( - // // todo: query from provide.config - // multisigAddress = "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - // preFixOP = txscript.OP_13 - //) - // - //searchParam := TxSearchParam{ - // StartHeight: heightInfo.Start, - // EndHeight: heightInfo.End, - // BitcoinAddress: multisigAddress, - // OPReturnPrefix: preFixOP, - //} + var ( + // todo: query from provide.config + multisigAddress = "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + preFixOP = txscript.OP_13 + ) + + multiSigScript, err := p.client.DecodeAddress(multisigAddress) + if err != nil { + return nil, err + } - return p.getMessagesFromTxList(nil) + searchParam := TxSearchParam{ + StartHeight: heightInfo.Start, + EndHeight: heightInfo.End, + BitcoinScript: multiSigScript, + OPReturnPrefix: preFixOP, + } + + messages, err := p.client.TxSearch(context.Background(), searchParam) + + if err != nil { + return nil, err + } + + return p.getMessagesFromTxList(messages) } -func (p *Provider) getMessagesFromTxList(resultTxList []*coreTypes.ResultTx) ([]*relayTypes.BlockInfo, error) { - //var messages []*relayTypes.BlockInfo - //for _, resultTx := range resultTxList { - // var eventsList []*EventsList - // if err := jsoniter.Unmarshal([]byte(resultTx.TxResult.Log), &eventsList); err != nil { - // return nil, err - // } - // - // for _, event := range eventsList { - // msgs, err := p.ParseMessageFromEvents(event.Events) - // if err != nil { - // return nil, err - // } - // for _, msg := range msgs { - // msg.MessageHeight = uint64(resultTx.Height) - // p.logger.Info("Detected eventlog", - // zap.Uint64("height", msg.MessageHeight), - // zap.String("target_network", msg.Dst), - // zap.Uint64("sn", msg.Sn), - // zap.String("event_type", msg.EventType), - // ) - // } - // messages = append(messages, &relayTypes.BlockInfo{ - // Height: uint64(resultTx.Height), - // Messages: msgs, - // }) - // } - //} +func parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, error) { + // handle for bitcoin bridge + + // parse message + + // todo: handle for rad fi + + return nil, nil +} + +func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayTypes.BlockInfo, error) { + var messages []*relayTypes.BlockInfo + for _, resultTx := range resultTxList { + msg, err := parseMessageFromTx(resultTx) + if err != nil { + return nil, err + } + + msg.MessageHeight = resultTx.Height + p.logger.Info("Detected eventlog", + zap.Uint64("height", msg.MessageHeight), + zap.String("target_network", msg.Dst), + zap.Uint64("sn", msg.Sn), + zap.String("event_type", msg.EventType), + ) + messages = append(messages, &relayTypes.BlockInfo{ + Height: resultTx.Height, + Messages: msgs, + }) + } return nil, nil } diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index 85944f71..50569445 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -1,11 +1,18 @@ package bitcoin +import "github.com/btcsuite/btcd/wire" + type TxSearchParam struct { StartHeight, EndHeight uint64 - BitcoinAddress string + BitcoinScript []byte OPReturnPrefix int } +type TxSearchRes struct { + Tx *wire.MsgTx + Height uint64 +} + // HightRange is a struct to represent a range of heights type HeightRange struct { Start uint64 From 8f42a7bbe86acbcbd2ae370bce2ee78e21171dc3 Mon Sep 17 00:00:00 2001 From: homelander Date: Tue, 6 Aug 2024 11:41:40 +0700 Subject: [PATCH 034/113] decode btc message --- relayer/chains/bitcoin/decode_test.go | 21 +++++++++++ relayer/chains/bitcoin/provide.go | 52 +++++++++++++++++++++++++-- relayer/chains/bitcoin/types.go | 13 ++++++- utils/multisig/op_message.go | 37 ++++++++++--------- 4 files changed, 100 insertions(+), 23 deletions(-) create mode 100644 relayer/chains/bitcoin/decode_test.go diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go new file mode 100644 index 00000000..7c5a4cde --- /dev/null +++ b/relayer/chains/bitcoin/decode_test.go @@ -0,0 +1,21 @@ +package bitcoin + +import ( + "encoding/hex" + "fmt" + "log" + "testing" + + "github.com/icon-project/icon-bridge/common/codec" +) + +func TestDecode(t *testing.T) { + data, _ := hex.DecodeString("f90106874465706f736974aa307830303030303030303030303030303030303030303030303030303030303030303030303030303030aa307843393736333336343766363634664645443041613933363937374437353638363664433733433037b33078312e69636f6e2f637832316539346330386330336461656538306332356438656533656132326132303738366563323331890db7148f8c6dd40000b8687b226d6574686f64223a225f73776170222c22706172616d73223a7b2270617468223a5b5d2c227265636569766572223a223078312e69636f6e2f687830343232393361393061303433656136383933653731663565343662663464646366323334633233227d7d") + depositInfo := DepositMessage{} + _, err := codec.RLP.UnmarshalFromBytes(data, &depositInfo) + if err != nil { + log.Fatal(err.Error()) + } + + fmt.Println(depositInfo) +} diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provide.go index 4c536ee6..4c5db26a 100644 --- a/relayer/chains/bitcoin/provide.go +++ b/relayer/chains/bitcoin/provide.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "github.com/btcsuite/btcd/txscript" + "github.com/icon-project/centralized-relay/utils/multisig" "math/big" "runtime" "strings" @@ -18,6 +19,7 @@ import ( "github.com/icon-project/centralized-relay/relayer/kms" "github.com/icon-project/centralized-relay/relayer/provider" relayTypes "github.com/icon-project/centralized-relay/relayer/types" + "github.com/icon-project/icon-bridge/common/codec" jsoniter "github.com/json-iterator/go" "go.uber.org/zap" ) @@ -33,6 +35,7 @@ type Provider struct { contracts map[string]relayTypes.EventMap eventList []sdkTypes.Event LastSavedHeightFunc func() uint64 + LastSerialNumFunc func() *big.Int multisigAddrScript []byte } @@ -545,20 +548,55 @@ func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRan return p.getMessagesFromTxList(messages) } -func parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, error) { +func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, error) { // handle for bitcoin bridge + // decode message from OP_RETURN + decodeMessage, err := multisig.ReadRelayMessage(tx.Tx, false) + if err != nil { + return nil, err + } + + // check if it is Deposit request + messageInfo := XCallMessage{} + _, err = codec.RLP.UnmarshalFromBytes(decodeMessage, &messageInfo) + if err != nil { + fmt.Printf("\n not a xcall format request \n") + } else if messageInfo.Action == "Deposit" { // maybe get this function name from cf file + // todo verify transfer amount match in calldata if it + // call 3rd to check rune amount + tokenId := messageInfo.TokenAddress + amount := big.NewInt(0) + amount.SetBytes(messageInfo.Amount) + destContract := messageInfo.To + + fmt.Println(tokenId) + fmt.Println(amount.String()) + fmt.Println(destContract) + + // todo: verify dest contract address on dest chain + } + + // todo: verify bridge fee // parse message // todo: handle for rad fi - return nil, nil + return &relayTypes.Message{ + // todo: + //Dst: messageInfo.To, + //Src: messageInfo.From, + Sn: p.LastSerialNumFunc(), + Data: decodeMessage, + MessageHeight: tx.Height, + EventType: events.CallMessage, + }, nil } func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayTypes.BlockInfo, error) { var messages []*relayTypes.BlockInfo for _, resultTx := range resultTxList { - msg, err := parseMessageFromTx(resultTx) + msg, err := p.parseMessageFromTx(resultTx) if err != nil { return nil, err } @@ -663,3 +701,11 @@ func (p *Provider) SetLastSavedHeightFunc(f func() uint64) { func (p *Provider) GetLastSavedHeight() uint64 { return p.LastSavedHeightFunc() } + +func (p *Provider) SetSerialNumberFunc(f func() *big.Int) { + p.LastSerialNumFunc = f +} + +func (p *Provider) GetSerialNumber() *big.Int { + return p.LastSerialNumFunc() +} diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index 50569445..30e38c90 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -1,6 +1,8 @@ package bitcoin -import "github.com/btcsuite/btcd/wire" +import ( + "github.com/btcsuite/btcd/wire" +) type TxSearchParam struct { StartHeight, EndHeight uint64 @@ -18,3 +20,12 @@ type HeightRange struct { Start uint64 End uint64 } + +type XCallMessage struct { + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte +} diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index 08b1d633..f21d59d3 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -8,27 +8,27 @@ import ( ) const ( - OP_RADFI_IDENT = txscript.OP_12 - OP_RUNE_IDENT = txscript.OP_13 - OP_BRIDGE_IDENT = txscript.OP_14 - - OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 - OP_RADFI_SWAP = txscript.OP_2 - OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 - OP_RADFI_COLLECT_FEE = txscript.OP_4 + OP_RADFI_IDENT = txscript.OP_12 + OP_RUNE_IDENT = txscript.OP_13 + OP_BRIDGE_IDENT = txscript.OP_14 + + OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 + OP_RADFI_SWAP = txscript.OP_2 + OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 + OP_RADFI_COLLECT_FEE = txscript.OP_4 ) type RadFiProvideLiquidityMsg struct { - Fee []byte - UpperTick []byte - LowerTick []byte - Min0 []byte - Min1 []byte + Fee []byte + UpperTick []byte + LowerTick []byte + Min0 []byte + Min1 []byte } type RadFiDecodedMsg struct { - Flag []byte - ProvideLiquidityMsg RadFiProvideLiquidityMsg + Flag []byte + ProvideLiquidityMsg RadFiProvideLiquidityMsg } // func createProvideLiquidityScript(fee uint8, upperTick uint32) ([]byte, error) { @@ -69,7 +69,7 @@ func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) return scripts, nil } -func readRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { +func ReadRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { var payload []byte for _, output := range transaction.TxOut { tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) @@ -82,7 +82,7 @@ func readRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { continue } - if (isRadFi && tokenizer.Opcode() != OP_RADFI_IDENT) || ((!isRadFi && tokenizer.Opcode() != OP_BRIDGE_IDENT)){ + if (isRadFi && tokenizer.Opcode() != OP_RADFI_IDENT) || (!isRadFi && tokenizer.Opcode() != OP_BRIDGE_IDENT) { // Check for Relayer protocol identifier (RadFi or ICON Bridge) continue } @@ -137,7 +137,6 @@ func readRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { // fmt.Println("It's after noon") // } - // return payload, nil // } @@ -147,4 +146,4 @@ func readRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { // } // return tokenizer.Opcode() -// } \ No newline at end of file +// } From 5eb336609fb83709333784e1384342fac3c1bdf4 Mon Sep 17 00:00:00 2001 From: homelander Date: Tue, 6 Aug 2024 11:49:24 +0700 Subject: [PATCH 035/113] fixed test --- relayer/chains/bitcoin/decode_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index 7c5a4cde..7a10b2f9 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -11,7 +11,7 @@ import ( func TestDecode(t *testing.T) { data, _ := hex.DecodeString("f90106874465706f736974aa307830303030303030303030303030303030303030303030303030303030303030303030303030303030aa307843393736333336343766363634664645443041613933363937374437353638363664433733433037b33078312e69636f6e2f637832316539346330386330336461656538306332356438656533656132326132303738366563323331890db7148f8c6dd40000b8687b226d6574686f64223a225f73776170222c22706172616d73223a7b2270617468223a5b5d2c227265636569766572223a223078312e69636f6e2f687830343232393361393061303433656136383933653731663565343662663464646366323334633233227d7d") - depositInfo := DepositMessage{} + depositInfo := XCallMessage{} _, err := codec.RLP.UnmarshalFromBytes(data, &depositInfo) if err != nil { log.Fatal(err.Error()) From b1fbbc5845297f4e0d6d8ed5365c1c9180c98e7c Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 6 Aug 2024 21:12:46 +0700 Subject: [PATCH 036/113] BB-68 update encoder and decoder for RadFi Provide Liquidity OP_RETURN --- utils/multisig/multisig_test.go | 81 +++++++++++++++- utils/multisig/op_message.go | 165 ++++++++++++++++++-------------- 2 files changed, 169 insertions(+), 77 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 08dae838..a8ea5cc8 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -392,8 +392,7 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) // Add Bridge Message - - message := []byte("Test Bridge Message") + message := []byte("{\"msg\":\"Test Bridge Message\"}") scripts, _ := CreateBridgeMessageScripts(message, 5) for i, script := range scripts { fmt.Println("OP_RETURN ", i, " script ", script) @@ -428,8 +427,80 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { fmt.Println("err sign: ", err) // Decode bridge message - decodedMessage, err := readRelayMessage(signedMsgTx, false) + decodedMessage, err := ReadBridgeMessage(signedMsgTx) + fmt.Println("err decode: ", err) + fmt.Println("origina message: ", string(message)) + fmt.Println("decoded message: ", string(decodedMessage)) +} + +func TestRadFiProvideLiquidity(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + // Add Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 0 + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + msgTx.AddTxOut(wire.NewTxOut(0, script1)) + + // Add RadFi Provive Liquidity Message + script2, _ := CreateProvideLiquidityScript(30, 12345, -12345, 0, 10000) + fmt.Println("OP_RETURN script: ", script2) + msgTx.AddTxOut(wire.NewTxOut(0, script2)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decode Radfi message + decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) + fmt.Println("err decode: ", err) - fmt.Println("origina message: ", message) - fmt.Println("decoded message: ", decodedMessage) + fmt.Println("decoded message - Flag: ", decodedRadFiMessage.Flag) + fmt.Println("decoded message - Fee: ", decodedRadFiMessage.ProvideLiquidityMsg.Fee) + fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.ProvideLiquidityMsg.UpperTick) + fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.LowerTick) + fmt.Println("decoded message - Min0: ", decodedRadFiMessage.ProvideLiquidityMsg.Min0) + fmt.Println("decoded message - Min1: ", decodedRadFiMessage.ProvideLiquidityMsg.Min1) } \ No newline at end of file diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index 08b1d633..e3ca31b3 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -1,6 +1,8 @@ package multisig import ( + "bytes" + "encoding/binary" "fmt" "github.com/btcsuite/btcd/txscript" @@ -19,27 +21,18 @@ const ( ) type RadFiProvideLiquidityMsg struct { - Fee []byte - UpperTick []byte - LowerTick []byte - Min0 []byte - Min1 []byte + Fee uint8 + UpperTick int32 + LowerTick int32 + Min0 uint16 + Min1 uint16 } type RadFiDecodedMsg struct { - Flag []byte - ProvideLiquidityMsg RadFiProvideLiquidityMsg + Flag byte + ProvideLiquidityMsg *RadFiProvideLiquidityMsg } -// func createProvideLiquidityScript(fee uint8, upperTick uint32) ([]byte, error) { -// builder := txscript.NewScriptBuilder() - -// builder.AddOp(txscript.OP_RETURN) -// builder.AddOp(OP_RADFI_IDENT) - -// return builder.Script() -// } - func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { var chunk []byte chunks := make([][]byte, 0, len(payload)/partLimit+1) @@ -69,24 +62,72 @@ func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) return scripts, nil } -func readRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { - var payload []byte +func CreateProvideLiquidityScript(fee uint8, upperTick int32, lowerTick int32, min0 uint16, min1 uint16) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_RADFI_IDENT) + builder.AddOp(OP_RADFI_PROVIDE_LIQUIDITY) + // encode message content + buf := new(bytes.Buffer) + var data = []any{ fee, upperTick, lowerTick, min0, min1 } + for _, v := range data { + err := binary.Write(buf, binary.LittleEndian, v) + if err != nil { + fmt.Println("CreateProvideLiquidityScript encode data failed:", err) + } + } + + return builder.AddData(buf.Bytes()).Script() +} + +func ReadBridgeMessage(transaction *wire.MsgTx) ([]byte, error) { + payload := []byte{} for _, output := range transaction.TxOut { tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != txscript.OP_RETURN { // Check for OP_RETURN continue } - if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() == OP_RUNE_IDENT { - // Check to ignore Rune protocol identifier (Runestone::MAGIC_NUMBER) + if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != OP_BRIDGE_IDENT { + // Check to ignore non Bridge protocol identifier (Rune or RadFi) continue } - if (isRadFi && tokenizer.Opcode() != OP_RADFI_IDENT) || ((!isRadFi && tokenizer.Opcode() != OP_BRIDGE_IDENT)){ - // Check for Relayer protocol identifier (RadFi or ICON Bridge) + // Construct the payload by concatenating remaining data pushes + for tokenizer.Next() { + if tokenizer.Err() != nil { + return nil, tokenizer.Err() + } + payload = append(payload, tokenizer.Data()...) + } + } + + if len(payload) == 0 { + return nil, fmt.Errorf("ReadBridgeMessage - no Bridge message found") + } + + return payload, nil +} + +func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { + var flag byte + var payload []byte + for _, output := range transaction.TxOut { + tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) + if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != txscript.OP_RETURN { + // Check for OP_RETURN + continue + } + if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != OP_RADFI_IDENT { + // Check to ignore non RadFi protocol identifier (Rune or Bridge) continue } + if tokenizer.Next() && tokenizer.Err() == nil { + flag = tokenizer.Opcode() + } + // Construct the payload by concatenating remaining data pushes for tokenizer.Next() { if tokenizer.Err() != nil { @@ -95,56 +136,36 @@ func readRelayMessage(transaction *wire.MsgTx, isRadFi bool) ([]byte, error) { payload = append(payload, tokenizer.Data()...) } - // only read 1 message output for radfi protocol - if isRadFi { - break - } + // only read 1 OP_RETURN output for RadFi protocol + break } - return payload, nil -} + // Decode RadFi message + r := bytes.NewReader(payload) + switch flag { + case OP_RADFI_PROVIDE_LIQUIDITY: + var provideLiquidityMsg RadFiProvideLiquidityMsg + if err := binary.Read(r, binary.LittleEndian, &provideLiquidityMsg); err != nil { + fmt.Println("OP_RADFI_PROVIDE_LIQUIDITY Read failed:", err) + } + + return &RadFiDecodedMsg { + Flag : flag, + ProvideLiquidityMsg: &provideLiquidityMsg, + }, nil + + case OP_RADFI_SWAP: + fmt.Println("OP_RADFI_SWAP") -// func decodeRadFiMessage(payload []byte) (*DecodedMsg, error) { -// tokenizer := txscript.MakeScriptTokenizer(0, payload) - -// // take the flag -// if !tokenizer.Next() || tokenizer.Err() != nil { -// return nil, fmt.Errorf("decodeRadFiMessage could not read the flag - Error %v", tokenizer.Err()) -// } -// flag := tokenizer.Opcode() - -// switch flag { -// case OP_RADFI_PROVIDE_LIQUIDITY: -// if !tokenizer.Next() || tokenizer.Err() != nil { -// return nil, fmt.Errorf("decodeRadFiMessage could not read the ProvideLiquidityMsg Fee - Error %v", tokenizer.Err()) -// } -// fee := -// return &DecodedMsg { -// Flag : flag, -// ProvideLiquidityMsg: RadFiProvideLiquidityMsg { -// Fee : , -// UpperTick : , -// LowerTick : , -// Min0 : , -// Min1 : , -// } -// } -// case 2: -// fmt.Println("two") -// case 3: -// fmt.Println("three") -// default: -// fmt.Println("It's after noon") -// } - - -// return payload, nil -// } - -// func nextToken(tokenizer *txscript.ScriptTokenizer) ([]byte, error) { -// if !tokenizer.Next() || tokenizer.Err() != nil { -// return nil, fmt.Errorf("decodeRadFiMessage could not read the flag - Error %v", tokenizer.Err()) -// } - -// return tokenizer.Opcode() -// } \ No newline at end of file + case OP_RADFI_WITHDRAW_LIQUIDITY: + fmt.Println("OP_RADFI_WITHDRAW_LIQUIDITY") + + case OP_RADFI_COLLECT_FEE: + fmt.Println("OP_RADFI_COLLECT_FEE") + + default: + return nil, fmt.Errorf("ReadRadFiMessage - invalid flag") + } + + return nil, fmt.Errorf("ReadRadFiMessage - no RadFi message found") +} From 9664004e0b3ad711fbf7cfcc884ea604537b6b15 Mon Sep 17 00:00:00 2001 From: homelander Date: Wed, 7 Aug 2024 17:10:15 +0700 Subject: [PATCH 037/113] validate runes deposit request --- relayer/chains/bitcoin/client.go | 2 - relayer/chains/bitcoin/decode_test.go | 11 ++++ relayer/chains/bitcoin/helper.go | 44 ++++++++++++++ relayer/chains/bitcoin/provide.go | 87 +++++++++++++++++---------- relayer/chains/bitcoin/types.go | 14 +++++ 5 files changed, 124 insertions(+), 34 deletions(-) create mode 100644 relayer/chains/bitcoin/helper.go diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 1f81b4f9..12b50fc9 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -102,8 +102,6 @@ func (c *Client) GetBalance(ctx context.Context, addr string) (uint64, error) { } func (c *Client) Subscribe(ctx context.Context, _, query string) error { - // - return nil } diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index 7a10b2f9..452d14a1 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "log" + "os" "testing" "github.com/icon-project/icon-bridge/common/codec" @@ -19,3 +20,13 @@ func TestDecode(t *testing.T) { fmt.Println(depositInfo) } + +func TestGetRuneBalanceAtIndex(t *testing.T) { + // + res, err := GetRuneTxIndex("https://open-api.unisat.io/v1/indexer/runes", "GET", os.Getenv("APIToken"), "60fa23d19c8116dbb09441bf3d1ee27067c3d2b3735caf2045db84ea8f76d436", 2) + if err != nil { + log.Fatal(err.Error()) + } + + fmt.Printf("%+v", res) +} diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go new file mode 100644 index 00000000..674240e3 --- /dev/null +++ b/relayer/chains/bitcoin/helper.go @@ -0,0 +1,44 @@ +package bitcoin + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strconv" +) + +func GetRuneTxIndex(endpoint, method, bearToken, txId string, index int) (*RuneTxIndexResponse, error) { + client := &http.Client{} + endpoint = endpoint + "/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" + fmt.Println(endpoint) + req, err := http.NewRequest(method, endpoint, nil) + + if err != nil { + fmt.Println(err) + return nil, err + } + req.Header.Add("Authorization", bearToken) + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return nil, err + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return nil, err + } + + var resp *RuneTxIndexResponse + err = json.Unmarshal(body, &resp) + if err != nil { + fmt.Println(err) + return nil, err + } + + return resp, nil +} diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provide.go index 4c5db26a..d89e2a6a 100644 --- a/relayer/chains/bitcoin/provide.go +++ b/relayer/chains/bitcoin/provide.go @@ -1,6 +1,7 @@ package bitcoin import ( + "bytes" "context" "fmt" "github.com/btcsuite/btcd/txscript" @@ -29,14 +30,17 @@ import ( type Provider struct { logger *zap.Logger // cfg *Config - client IClient - kms kms.KMS - wallet sdkTypes.AccountI - contracts map[string]relayTypes.EventMap - eventList []sdkTypes.Event - LastSavedHeightFunc func() uint64 - LastSerialNumFunc func() *big.Int - multisigAddrScript []byte + client IClient + kms kms.KMS + wallet sdkTypes.AccountI + contracts map[string]relayTypes.EventMap + eventList []sdkTypes.Event + LastSavedHeightFunc func() uint64 + LastSerialNumFunc func() *big.Int + multisigAddrScript []byte // + assetManagerAddrIcon string + bearToken string + unitsatEndpoint string } func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { @@ -100,33 +104,16 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn return err } - subscribeStarter := time.NewTicker(time.Second * 1) - pollHeightTicker := time.NewTicker(time.Second * 1) + pollHeightTicker := time.NewTicker(time.Second * 60) // do scan each 2 mins pollHeightTicker.Stop() - resetFunc := func() { - subscribeStarter.Reset(time.Second * 3) - pollHeightTicker.Reset(time.Second * 3) - } - p.logger.Info("Start from height", zap.Uint64("height", startHeight), zap.Uint64("finality block", p.FinalityBlock(ctx))) for { select { - case <-ctx.Done(): - return ctx.Err() - case <-subscribeStarter.C: - subscribeStarter.Stop() - for _, event := range p.contracts { - go p.SubscribeMessageEvents(ctx, blockInfoChan, &types.SubscribeOpts{ - Address: event.Address, - Method: event.GetWasmMsgType(), - Height: latestHeight, - }, resetFunc) - } case <-pollHeightTicker.C: - pollHeightTicker.Stop() - startHeight = p.GetLastSavedHeight() + //pollHeightTicker.Stop() + //startHeight = p.GetLastSavedHeight() latestHeight, err = p.QueryLatestHeight(ctx) if err != nil { p.logger.Error("failed to get latest block height", zap.Error(err)) @@ -561,7 +548,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err _, err = codec.RLP.UnmarshalFromBytes(decodeMessage, &messageInfo) if err != nil { fmt.Printf("\n not a xcall format request \n") - } else if messageInfo.Action == "Deposit" { // maybe get this function name from cf file + } else if messageInfo.Action == "Deposit" && messageInfo.To == p.assetManagerAddrIcon { // maybe get this function name from cf file // todo verify transfer amount match in calldata if it // call 3rd to check rune amount tokenId := messageInfo.TokenAddress @@ -573,7 +560,43 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err fmt.Println(amount.String()) fmt.Println(destContract) - // todo: verify dest contract address on dest chain + // call api to verify the data + // https://docs.unisat.io/dev/unisat-developer-center/runes/get-utxo-runes-balance + verified := false + for i, out := range tx.Tx.TxOut { + if messageInfo.TokenAddress == "0:0" { + if amount.Cmp(big.NewInt(out.Value)) == 0 && bytes.Compare(out.PkScript, p.multisigAddrScript) == 0 { + verified = true + break + } + } else { + // https://open-api.unisat.io/v1/indexer/runes/utxo + runes, err := GetRuneTxIndex(p.unitsatEndpoint, "GET", p.bearToken, tx.Tx.TxHash().String(), i) + if err != nil { + return nil, err + } + + if len(runes.Data) == 0 { + continue + } + + for _, runeOut := range runes.Data { + runeTokenBal, ok := big.NewInt(0).SetString(runeOut.Amount, 10) + if !ok { + return nil, fmt.Errorf("rune amount out invalid") + } + + if amount.Cmp(runeTokenBal) == 0 && runeOut.RuneId == messageInfo.TokenAddress { + verified = true + break + } + } + } + } + + if !verified { + return nil, fmt.Errorf("failed to verify transaction %v", tx.Tx.TxHash().String()) + } } // todo: verify bridge fee @@ -584,8 +607,8 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err return &relayTypes.Message{ // todo: - //Dst: messageInfo.To, - //Src: messageInfo.From, + Dst: "icon", + Src: messageInfo.From, Sn: p.LastSerialNumFunc(), Data: decodeMessage, MessageHeight: tx.Height, diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index 30e38c90..cd7b7ecd 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -29,3 +29,17 @@ type XCallMessage struct { Amount []byte Data []byte } + +type RuneInfo struct { + Rune string `json:"rune"` + RuneId string `json:"runeId"` + SpaceRune string `json:"spaceRune"` + Amount string `json:"amount"` + Symbol string `json:"symbol"` + Divisibility int `json:"divisibility"` +} + +type RuneTxIndexResponse struct { + Code int `json:"code"` + Data []RuneInfo `json:"data"` +} From 76af44f0bf3329d5d724aa8d0b17b9ff58ca4d0b Mon Sep 17 00:00:00 2001 From: homelander Date: Wed, 7 Aug 2024 17:17:06 +0700 Subject: [PATCH 038/113] fixed validation --- relayer/chains/bitcoin/provide.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provide.go index d89e2a6a..28a3a0cc 100644 --- a/relayer/chains/bitcoin/provide.go +++ b/relayer/chains/bitcoin/provide.go @@ -564,8 +564,12 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err // https://docs.unisat.io/dev/unisat-developer-center/runes/get-utxo-runes-balance verified := false for i, out := range tx.Tx.TxOut { + if bytes.Compare(out.PkScript, p.multisigAddrScript) != 0 { + continue + } + if messageInfo.TokenAddress == "0:0" { - if amount.Cmp(big.NewInt(out.Value)) == 0 && bytes.Compare(out.PkScript, p.multisigAddrScript) == 0 { + if amount.Cmp(big.NewInt(out.Value)) == 0 { verified = true break } From ee14986d1838afe3e88bc7f91c3c883fc1990bc6 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 7 Aug 2024 20:43:02 +0700 Subject: [PATCH 039/113] BB-69 update encoder decoder for radfi withdraw liquidity OP_RETURN --- utils/multisig/multisig_test.go | 97 ++++++++++++++++++++++++++++++--- utils/multisig/op_message.go | 69 ++++++++++++++++++++--- 2 files changed, 151 insertions(+), 15 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index a8ea5cc8..67e0f8af 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/bxelab/runestone" + "github.com/holiman/uint256" ) func TestGenerateKeys(t *testing.T) { @@ -429,8 +430,8 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { // Decode bridge message decodedMessage, err := ReadBridgeMessage(signedMsgTx) fmt.Println("err decode: ", err) - fmt.Println("origina message: ", string(message)) - fmt.Println("decoded message: ", string(decodedMessage)) + fmt.Println("original message: ", string(message)) + fmt.Println("decoded message : ", string(decodedMessage)) } func TestRadFiProvideLiquidity(t *testing.T) { @@ -464,7 +465,14 @@ func TestRadFiProvideLiquidity(t *testing.T) { msgTx.AddTxOut(wire.NewTxOut(0, script1)) // Add RadFi Provive Liquidity Message - script2, _ := CreateProvideLiquidityScript(30, 12345, -12345, 0, 10000) + radfiMsg := RadFiProvideLiquidityMsg { + Fee: 30, + UpperTick: 12345, + LowerTick: -12345, + Min0: 0, + Min1: 10000, + } + script2, _ := CreateProvideLiquidityScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script2) msgTx.AddTxOut(wire.NewTxOut(0, script2)) @@ -497,10 +505,85 @@ func TestRadFiProvideLiquidity(t *testing.T) { decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) fmt.Println("err decode: ", err) - fmt.Println("decoded message - Flag: ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - Fee: ", decodedRadFiMessage.ProvideLiquidityMsg.Fee) + fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) + fmt.Println("decoded message - Fee : ", decodedRadFiMessage.ProvideLiquidityMsg.Fee) fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.ProvideLiquidityMsg.UpperTick) fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.LowerTick) - fmt.Println("decoded message - Min0: ", decodedRadFiMessage.ProvideLiquidityMsg.Min0) - fmt.Println("decoded message - Min1: ", decodedRadFiMessage.ProvideLiquidityMsg.Min1) + fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.ProvideLiquidityMsg.Min0) + fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Min1) +} + +func TestRadFiWithdrawLiquidity(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + // Add Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 0 + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + msgTx.AddTxOut(wire.NewTxOut(0, script1)) + + // Add RadFi Withdraw Liquidity Message + radfiMsg := RadFiWithdrawLiquidityMsg { + RecipientIndex: 123, + LiquidityValue: uint256.MustFromDecimal("123456"), + NftId: uint256.MustFromDecimal("123456789"), + } + script2, _ := CreateWithdrawLiquidityScript(&radfiMsg) + fmt.Println("OP_RETURN script: ", script2) + msgTx.AddTxOut(wire.NewTxOut(0, script2)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decode Radfi message + decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) + + fmt.Println("err decode: ", err) + fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) + fmt.Println("decoded message - RecipientIndex : ", decodedRadFiMessage.WithdrawLiquidityMsg.RecipientIndex) + fmt.Println("decoded message - LiquidityValue : ", decodedRadFiMessage.WithdrawLiquidityMsg.LiquidityValue) + fmt.Println("decoded message - NftId : ", decodedRadFiMessage.WithdrawLiquidityMsg.NftId) } \ No newline at end of file diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index e3ca31b3..d10d69e5 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/holiman/uint256" ) const ( @@ -28,9 +29,16 @@ type RadFiProvideLiquidityMsg struct { Min1 uint16 } +type RadFiWithdrawLiquidityMsg struct { + RecipientIndex uint32 + LiquidityValue *uint256.Int + NftId *uint256.Int +} + type RadFiDecodedMsg struct { Flag byte ProvideLiquidityMsg *RadFiProvideLiquidityMsg + WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg } func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { @@ -62,7 +70,7 @@ func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) return scripts, nil } -func CreateProvideLiquidityScript(fee uint8, upperTick int32, lowerTick int32, min0 uint16, min1 uint16) ([]byte, error) { +func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) { builder := txscript.NewScriptBuilder() builder.AddOp(txscript.OP_RETURN) @@ -70,9 +78,9 @@ func CreateProvideLiquidityScript(fee uint8, upperTick int32, lowerTick int32, m builder.AddOp(OP_RADFI_PROVIDE_LIQUIDITY) // encode message content buf := new(bytes.Buffer) - var data = []any{ fee, upperTick, lowerTick, min0, min1 } + var data = []any{ msg.Fee, msg.UpperTick, msg.LowerTick, msg.Min0, msg.Min1 } for _, v := range data { - err := binary.Write(buf, binary.LittleEndian, v) + err := binary.Write(buf, binary.BigEndian, v) if err != nil { fmt.Println("CreateProvideLiquidityScript encode data failed:", err) } @@ -81,6 +89,31 @@ func CreateProvideLiquidityScript(fee uint8, upperTick int32, lowerTick int32, m return builder.AddData(buf.Bytes()).Script() } +func CreateWithdrawLiquidityScript(msg *RadFiWithdrawLiquidityMsg) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_RADFI_IDENT) + builder.AddOp(OP_RADFI_WITHDRAW_LIQUIDITY) + // encode message content + recipientIndexByte := make([]byte, 4) + binary.BigEndian.PutUint32(recipientIndexByte, msg.RecipientIndex) + // recipientIndexLen := uint8(bits.Len32(msg.RecipientIndex)) + liquidityValueBytes := msg.LiquidityValue.Bytes() + liquidityValueBytesLen := uint8(len(liquidityValueBytes)) + // singleByte := byte((recipientIndexLen << 5) ^ liquidityValueBytesLen) + singleByte := byte(liquidityValueBytesLen) + // data := append([]byte{singleByte}, recipientIndexByte[4-recipientIndexLen:]...) + data := append([]byte{singleByte}, recipientIndexByte...) + data = append(data, liquidityValueBytes...) + data = append(data, msg.NftId.Bytes()...) + // fmt.Println("data: ", data) + // fmt.Println("singleByte: ", singleByte) + // fmt.Println("recipientIndexByte: ", recipientIndexByte) + // fmt.Println("liquidityValueBytes: ", liquidityValueBytes) + return builder.AddData(data).Script() +} + func ReadBridgeMessage(transaction *wire.MsgTx) ([]byte, error) { payload := []byte{} for _, output := range transaction.TxOut { @@ -141,24 +174,44 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { } // Decode RadFi message - r := bytes.NewReader(payload) switch flag { case OP_RADFI_PROVIDE_LIQUIDITY: + r := bytes.NewReader(payload) var provideLiquidityMsg RadFiProvideLiquidityMsg - if err := binary.Read(r, binary.LittleEndian, &provideLiquidityMsg); err != nil { + if err := binary.Read(r, binary.BigEndian, &provideLiquidityMsg); err != nil { fmt.Println("OP_RADFI_PROVIDE_LIQUIDITY Read failed:", err) } return &RadFiDecodedMsg { - Flag : flag, - ProvideLiquidityMsg: &provideLiquidityMsg, + Flag : flag, + ProvideLiquidityMsg : &provideLiquidityMsg, }, nil case OP_RADFI_SWAP: fmt.Println("OP_RADFI_SWAP") case OP_RADFI_WITHDRAW_LIQUIDITY: - fmt.Println("OP_RADFI_WITHDRAW_LIQUIDITY") + // singleByte := uint8(payload[0]) + // recipientIndexLen := singleByte >> 5 + // fmt.Println("recipientIndexLen", recipientIndexLen) + // liquidityValueBytesLen := singleByte << 3 >> 3 + liquidityValueBytesLen := uint8(payload[0]) + // fmt.Println("liquidityValueBytesLen", liquidityValueBytesLen) + payload = payload[1:] + recipientIndex := binary.BigEndian.Uint32(payload[:4]) + payload = payload[4:] + liquidityValue := new(uint256.Int).SetBytes(payload[:liquidityValueBytesLen]) + nftId := new(uint256.Int).SetBytes(payload[liquidityValueBytesLen:]) + // fmt.Println("OP_RADFI_WITHDRAW_LIQUIDITY", recipientIndex, liquidityValue, NftId) + + return &RadFiDecodedMsg { + Flag : flag, + WithdrawLiquidityMsg: &RadFiWithdrawLiquidityMsg{ + RecipientIndex : recipientIndex, + LiquidityValue : liquidityValue, + NftId : nftId, + }, + }, nil case OP_RADFI_COLLECT_FEE: fmt.Println("OP_RADFI_COLLECT_FEE") From 81be1ecfbe51f2a57fc5b13b5285dda768018ebf Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Thu, 8 Aug 2024 15:32:00 +0700 Subject: [PATCH 040/113] BB-69 update encoder decoder for RadFi collect fees OP_RETURN --- utils/multisig/multisig_test.go | 73 +++++++++++++++++++++++++++++++++ utils/multisig/op_message.go | 40 +++++++++++++++--- 2 files changed, 107 insertions(+), 6 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 67e0f8af..e47ed6c4 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -586,4 +586,77 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { fmt.Println("decoded message - RecipientIndex : ", decodedRadFiMessage.WithdrawLiquidityMsg.RecipientIndex) fmt.Println("decoded message - LiquidityValue : ", decodedRadFiMessage.WithdrawLiquidityMsg.LiquidityValue) fmt.Println("decoded message - NftId : ", decodedRadFiMessage.WithdrawLiquidityMsg.NftId) +} + +func TestRadFiCollectFees(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + // Add Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 0 + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + msgTx.AddTxOut(wire.NewTxOut(0, script1)) + + // Add RadFi Withdraw Liquidity Message + radfiMsg := RadFiCollectFeesMsg { + RecipientIndex: 123, + NftId: uint256.MustFromDecimal("123456789"), + } + script2, _ := CreateCollectFeesScript(&radfiMsg) + fmt.Println("OP_RETURN script: ", script2) + msgTx.AddTxOut(wire.NewTxOut(0, script2)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decode Radfi message + decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) + + fmt.Println("err decode: ", err) + fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) + fmt.Println("decoded message - RecipientIndex : ", decodedRadFiMessage.CollectFeesMsg.RecipientIndex) + fmt.Println("decoded message - NftId : ", decodedRadFiMessage.CollectFeesMsg.NftId) } \ No newline at end of file diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index d10d69e5..d7b6a8e1 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -18,7 +18,7 @@ const ( OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 OP_RADFI_SWAP = txscript.OP_2 OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 - OP_RADFI_COLLECT_FEE = txscript.OP_4 + OP_RADFI_COLLECT_FEES = txscript.OP_4 ) type RadFiProvideLiquidityMsg struct { @@ -35,10 +35,15 @@ type RadFiWithdrawLiquidityMsg struct { NftId *uint256.Int } +type RadFiCollectFeesMsg struct { + RecipientIndex uint32 + NftId *uint256.Int +} type RadFiDecodedMsg struct { - Flag byte - ProvideLiquidityMsg *RadFiProvideLiquidityMsg - WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg + Flag byte + ProvideLiquidityMsg *RadFiProvideLiquidityMsg + WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg + CollectFeesMsg *RadFiCollectFeesMsg } func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { @@ -114,6 +119,20 @@ func CreateWithdrawLiquidityScript(msg *RadFiWithdrawLiquidityMsg) ([]byte, erro return builder.AddData(data).Script() } +func CreateCollectFeesScript(msg *RadFiCollectFeesMsg) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_RADFI_IDENT) + builder.AddOp(OP_RADFI_COLLECT_FEES) + // encode message content + recipientIndexByte := make([]byte, 4) + binary.BigEndian.PutUint32(recipientIndexByte, msg.RecipientIndex) + data := append(recipientIndexByte, msg.NftId.Bytes()...) + + return builder.AddData(data).Script() +} + func ReadBridgeMessage(transaction *wire.MsgTx) ([]byte, error) { payload := []byte{} for _, output := range transaction.TxOut { @@ -213,8 +232,17 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { }, }, nil - case OP_RADFI_COLLECT_FEE: - fmt.Println("OP_RADFI_COLLECT_FEE") + case OP_RADFI_COLLECT_FEES: + recipientIndex := binary.BigEndian.Uint32(payload[:4]) + nftId := new(uint256.Int).SetBytes(payload[4:]) + + return &RadFiDecodedMsg { + Flag : flag, + CollectFeesMsg: &RadFiCollectFeesMsg{ + RecipientIndex : recipientIndex, + NftId : nftId, + }, + }, nil default: return nil, fmt.Errorf("ReadRadFiMessage - invalid flag") From 896118cd4e7de9b4c3bfb0ea868ecbb05c9893c1 Mon Sep 17 00:00:00 2001 From: homelander Date: Thu, 8 Aug 2024 21:23:30 +0700 Subject: [PATCH 041/113] added contract abis --- relayer/chains/bitcoin/abi/bitcoin_state.go | 5177 +++++++++++++++++ relayer/chains/bitcoin/abi/icall_service.go | 1814 ++++++ .../bitcoin/abi/icentralized_connection.go | 722 +++ .../chains/bitcoin/abi/inonfungible_token.go | 2017 +++++++ relayer/chains/bitcoin/abi/iswap_router.go | 328 ++ relayer/chains/bitcoin/helper.go | 80 +- relayer/chains/bitcoin/types.go | 55 +- 7 files changed, 10134 insertions(+), 59 deletions(-) create mode 100644 relayer/chains/bitcoin/abi/bitcoin_state.go create mode 100644 relayer/chains/bitcoin/abi/icall_service.go create mode 100644 relayer/chains/bitcoin/abi/icentralized_connection.go create mode 100644 relayer/chains/bitcoin/abi/inonfungible_token.go create mode 100644 relayer/chains/bitcoin/abi/iswap_router.go diff --git a/relayer/chains/bitcoin/abi/bitcoin_state.go b/relayer/chains/bitcoin/abi/bitcoin_state.go new file mode 100644 index 00000000..45792178 --- /dev/null +++ b/relayer/chains/bitcoin/abi/bitcoin_state.go @@ -0,0 +1,5177 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package abi + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// IBitcoinStateTokenInfo is an auto generated low-level Go binding around an user-defined struct. +type IBitcoinStateTokenInfo struct { + Name string + Symbol string +} + +// StdInvariantFuzzArtifactSelector is an auto generated low-level Go binding around an user-defined struct. +type StdInvariantFuzzArtifactSelector struct { + Artifact string + Selectors [][4]byte +} + +// StdInvariantFuzzInterface is an auto generated low-level Go binding around an user-defined struct. +type StdInvariantFuzzInterface struct { + Addr common.Address + Artifacts []string +} + +// StdInvariantFuzzSelector is an auto generated low-level Go binding around an user-defined struct. +type StdInvariantFuzzSelector struct { + Addr common.Address + Selectors [][4]byte +} + +// BitcoinStateMetaData contains all meta data concerning the BitcoinState contract. +var BitcoinStateMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"IS_TEST\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"_PERMIT_TYPEHASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"accountBalances\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"bitcoinNid\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimTokens\",\"inputs\":[{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"computeTokenAddress\",\"inputs\":[{\"name\":\"tokenName\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"connections\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"connectionsEndpoints\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeArtifacts\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedArtifacts_\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeContracts\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedContracts_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeSelectors\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedSelectors_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzSelector[]\",\"components\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"selectors\",\"type\":\"bytes4[]\",\"internalType\":\"bytes4[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeSenders\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedSenders_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"failed\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSignData\",\"inputs\":[{\"name\":\"requester_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleCallMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_protocols\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initPool\",\"inputs\":[{\"name\":\"data_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"xcall_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"uinswapV3Router_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nonfungiblePositionManager_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"connections\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"migrate\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"migrateComplete\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"nftOwners\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nonFungibleManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"params\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIBitcoinState.TokenInfo\",\"components\":[{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"symbol\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"removeConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeLiquidity\",\"inputs\":[{\"name\":\"data_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"routerV2\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetArtifactSelectors\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedArtifactSelectors_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzArtifactSelector[]\",\"components\":[{\"name\":\"artifact\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"selectors\",\"type\":\"bytes4[]\",\"internalType\":\"bytes4[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetArtifacts\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedArtifacts_\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetContracts\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedContracts_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetInterfaces\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedInterfaces_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzInterface[]\",\"components\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"artifacts\",\"type\":\"string[]\",\"internalType\":\"string[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetSelectors\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedSelectors_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzSelector[]\",\"components\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"selectors\",\"type\":\"bytes4[]\",\"internalType\":\"bytes4[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetSenders\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedSenders_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokens\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"xcallService\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AddConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AddSelector\",\"inputs\":[{\"name\":\"selector_\",\"type\":\"bytes4\",\"indexed\":false,\"internalType\":\"bytes4\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemoveConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemoveSelector\",\"inputs\":[{\"name\":\"selector_\",\"type\":\"bytes4\",\"indexed\":false,\"internalType\":\"bytes4\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RequestExecuted\",\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"stateRoot\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log\",\"inputs\":[{\"name\":\"\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_address\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_array\",\"inputs\":[{\"name\":\"val\",\"type\":\"uint256[]\",\"indexed\":false,\"internalType\":\"uint256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_array\",\"inputs\":[{\"name\":\"val\",\"type\":\"int256[]\",\"indexed\":false,\"internalType\":\"int256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_array\",\"inputs\":[{\"name\":\"val\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_bytes\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_bytes32\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_int\",\"inputs\":[{\"name\":\"\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_address\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_array\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"uint256[]\",\"indexed\":false,\"internalType\":\"uint256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_array\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"int256[]\",\"indexed\":false,\"internalType\":\"int256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_array\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_bytes\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_bytes32\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_decimal_int\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"},{\"name\":\"decimals\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_decimal_uint\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"decimals\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_int\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_string\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_uint\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_string\",\"inputs\":[{\"name\":\"\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_uint\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"logs\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false}]", +} + +// BitcoinStateABI is the input ABI used to generate the binding from. +// Deprecated: Use BitcoinStateMetaData.ABI instead. +var BitcoinStateABI = BitcoinStateMetaData.ABI + +// BitcoinState is an auto generated Go binding around an Ethereum contract. +type BitcoinState struct { + BitcoinStateCaller // Read-only binding to the contract + BitcoinStateTransactor // Write-only binding to the contract + BitcoinStateFilterer // Log filterer for contract events +} + +// BitcoinStateCaller is an auto generated read-only Go binding around an Ethereum contract. +type BitcoinStateCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BitcoinStateTransactor is an auto generated write-only Go binding around an Ethereum contract. +type BitcoinStateTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BitcoinStateFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type BitcoinStateFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// BitcoinStateSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type BitcoinStateSession struct { + Contract *BitcoinState // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// BitcoinStateCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type BitcoinStateCallerSession struct { + Contract *BitcoinStateCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// BitcoinStateTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type BitcoinStateTransactorSession struct { + Contract *BitcoinStateTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// BitcoinStateRaw is an auto generated low-level Go binding around an Ethereum contract. +type BitcoinStateRaw struct { + Contract *BitcoinState // Generic contract binding to access the raw methods on +} + +// BitcoinStateCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type BitcoinStateCallerRaw struct { + Contract *BitcoinStateCaller // Generic read-only contract binding to access the raw methods on +} + +// BitcoinStateTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type BitcoinStateTransactorRaw struct { + Contract *BitcoinStateTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewBitcoinState creates a new instance of BitcoinState, bound to a specific deployed contract. +func NewBitcoinState(address common.Address, backend bind.ContractBackend) (*BitcoinState, error) { + contract, err := bindBitcoinState(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &BitcoinState{BitcoinStateCaller: BitcoinStateCaller{contract: contract}, BitcoinStateTransactor: BitcoinStateTransactor{contract: contract}, BitcoinStateFilterer: BitcoinStateFilterer{contract: contract}}, nil +} + +// NewBitcoinStateCaller creates a new read-only instance of BitcoinState, bound to a specific deployed contract. +func NewBitcoinStateCaller(address common.Address, caller bind.ContractCaller) (*BitcoinStateCaller, error) { + contract, err := bindBitcoinState(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &BitcoinStateCaller{contract: contract}, nil +} + +// NewBitcoinStateTransactor creates a new write-only instance of BitcoinState, bound to a specific deployed contract. +func NewBitcoinStateTransactor(address common.Address, transactor bind.ContractTransactor) (*BitcoinStateTransactor, error) { + contract, err := bindBitcoinState(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &BitcoinStateTransactor{contract: contract}, nil +} + +// NewBitcoinStateFilterer creates a new log filterer instance of BitcoinState, bound to a specific deployed contract. +func NewBitcoinStateFilterer(address common.Address, filterer bind.ContractFilterer) (*BitcoinStateFilterer, error) { + contract, err := bindBitcoinState(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &BitcoinStateFilterer{contract: contract}, nil +} + +// bindBitcoinState binds a generic wrapper to an already deployed contract. +func bindBitcoinState(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := BitcoinStateMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_BitcoinState *BitcoinStateRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BitcoinState.Contract.BitcoinStateCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_BitcoinState *BitcoinStateRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BitcoinState.Contract.BitcoinStateTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_BitcoinState *BitcoinStateRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BitcoinState.Contract.BitcoinStateTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_BitcoinState *BitcoinStateCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _BitcoinState.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_BitcoinState *BitcoinStateTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BitcoinState.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_BitcoinState *BitcoinStateTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _BitcoinState.Contract.contract.Transact(opts, method, params...) +} + +// ISTEST is a free data retrieval call binding the contract method 0xfa7626d4. +// +// Solidity: function IS_TEST() view returns(bool) +func (_BitcoinState *BitcoinStateCaller) ISTEST(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "IS_TEST") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// ISTEST is a free data retrieval call binding the contract method 0xfa7626d4. +// +// Solidity: function IS_TEST() view returns(bool) +func (_BitcoinState *BitcoinStateSession) ISTEST() (bool, error) { + return _BitcoinState.Contract.ISTEST(&_BitcoinState.CallOpts) +} + +// ISTEST is a free data retrieval call binding the contract method 0xfa7626d4. +// +// Solidity: function IS_TEST() view returns(bool) +func (_BitcoinState *BitcoinStateCallerSession) ISTEST() (bool, error) { + return _BitcoinState.Contract.ISTEST(&_BitcoinState.CallOpts) +} + +// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x982aaf6b. +// +// Solidity: function _PERMIT_TYPEHASH() view returns(bytes32) +func (_BitcoinState *BitcoinStateCaller) PERMITTYPEHASH(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "_PERMIT_TYPEHASH") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x982aaf6b. +// +// Solidity: function _PERMIT_TYPEHASH() view returns(bytes32) +func (_BitcoinState *BitcoinStateSession) PERMITTYPEHASH() ([32]byte, error) { + return _BitcoinState.Contract.PERMITTYPEHASH(&_BitcoinState.CallOpts) +} + +// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x982aaf6b. +// +// Solidity: function _PERMIT_TYPEHASH() view returns(bytes32) +func (_BitcoinState *BitcoinStateCallerSession) PERMITTYPEHASH() ([32]byte, error) { + return _BitcoinState.Contract.PERMITTYPEHASH(&_BitcoinState.CallOpts) +} + +// AccountBalances is a free data retrieval call binding the contract method 0x1242e5fd. +// +// Solidity: function accountBalances(address , address ) view returns(uint256) +func (_BitcoinState *BitcoinStateCaller) AccountBalances(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "accountBalances", arg0, arg1) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// AccountBalances is a free data retrieval call binding the contract method 0x1242e5fd. +// +// Solidity: function accountBalances(address , address ) view returns(uint256) +func (_BitcoinState *BitcoinStateSession) AccountBalances(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _BitcoinState.Contract.AccountBalances(&_BitcoinState.CallOpts, arg0, arg1) +} + +// AccountBalances is a free data retrieval call binding the contract method 0x1242e5fd. +// +// Solidity: function accountBalances(address , address ) view returns(uint256) +func (_BitcoinState *BitcoinStateCallerSession) AccountBalances(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _BitcoinState.Contract.AccountBalances(&_BitcoinState.CallOpts, arg0, arg1) +} + +// BitcoinNid is a free data retrieval call binding the contract method 0xf3cc4515. +// +// Solidity: function bitcoinNid() view returns(string) +func (_BitcoinState *BitcoinStateCaller) BitcoinNid(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "bitcoinNid") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// BitcoinNid is a free data retrieval call binding the contract method 0xf3cc4515. +// +// Solidity: function bitcoinNid() view returns(string) +func (_BitcoinState *BitcoinStateSession) BitcoinNid() (string, error) { + return _BitcoinState.Contract.BitcoinNid(&_BitcoinState.CallOpts) +} + +// BitcoinNid is a free data retrieval call binding the contract method 0xf3cc4515. +// +// Solidity: function bitcoinNid() view returns(string) +func (_BitcoinState *BitcoinStateCallerSession) BitcoinNid() (string, error) { + return _BitcoinState.Contract.BitcoinNid(&_BitcoinState.CallOpts) +} + +// ClaimTokens is a free data retrieval call binding the contract method 0x69ffa08a. +// +// Solidity: function claimTokens(address token0, address token1) pure returns() +func (_BitcoinState *BitcoinStateCaller) ClaimTokens(opts *bind.CallOpts, token0 common.Address, token1 common.Address) error { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "claimTokens", token0, token1) + + if err != nil { + return err + } + + return err + +} + +// ClaimTokens is a free data retrieval call binding the contract method 0x69ffa08a. +// +// Solidity: function claimTokens(address token0, address token1) pure returns() +func (_BitcoinState *BitcoinStateSession) ClaimTokens(token0 common.Address, token1 common.Address) error { + return _BitcoinState.Contract.ClaimTokens(&_BitcoinState.CallOpts, token0, token1) +} + +// ClaimTokens is a free data retrieval call binding the contract method 0x69ffa08a. +// +// Solidity: function claimTokens(address token0, address token1) pure returns() +func (_BitcoinState *BitcoinStateCallerSession) ClaimTokens(token0 common.Address, token1 common.Address) error { + return _BitcoinState.Contract.ClaimTokens(&_BitcoinState.CallOpts, token0, token1) +} + +// ComputeTokenAddress is a free data retrieval call binding the contract method 0x4aa6af7b. +// +// Solidity: function computeTokenAddress(string tokenName) view returns(address) +func (_BitcoinState *BitcoinStateCaller) ComputeTokenAddress(opts *bind.CallOpts, tokenName string) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "computeTokenAddress", tokenName) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// ComputeTokenAddress is a free data retrieval call binding the contract method 0x4aa6af7b. +// +// Solidity: function computeTokenAddress(string tokenName) view returns(address) +func (_BitcoinState *BitcoinStateSession) ComputeTokenAddress(tokenName string) (common.Address, error) { + return _BitcoinState.Contract.ComputeTokenAddress(&_BitcoinState.CallOpts, tokenName) +} + +// ComputeTokenAddress is a free data retrieval call binding the contract method 0x4aa6af7b. +// +// Solidity: function computeTokenAddress(string tokenName) view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) ComputeTokenAddress(tokenName string) (common.Address, error) { + return _BitcoinState.Contract.ComputeTokenAddress(&_BitcoinState.CallOpts, tokenName) +} + +// Connections is a free data retrieval call binding the contract method 0xc0896578. +// +// Solidity: function connections(address ) view returns(bool) +func (_BitcoinState *BitcoinStateCaller) Connections(opts *bind.CallOpts, arg0 common.Address) (bool, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "connections", arg0) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Connections is a free data retrieval call binding the contract method 0xc0896578. +// +// Solidity: function connections(address ) view returns(bool) +func (_BitcoinState *BitcoinStateSession) Connections(arg0 common.Address) (bool, error) { + return _BitcoinState.Contract.Connections(&_BitcoinState.CallOpts, arg0) +} + +// Connections is a free data retrieval call binding the contract method 0xc0896578. +// +// Solidity: function connections(address ) view returns(bool) +func (_BitcoinState *BitcoinStateCallerSession) Connections(arg0 common.Address) (bool, error) { + return _BitcoinState.Contract.Connections(&_BitcoinState.CallOpts, arg0) +} + +// ConnectionsEndpoints is a free data retrieval call binding the contract method 0xb687db2e. +// +// Solidity: function connectionsEndpoints(uint256 ) view returns(address) +func (_BitcoinState *BitcoinStateCaller) ConnectionsEndpoints(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "connectionsEndpoints", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// ConnectionsEndpoints is a free data retrieval call binding the contract method 0xb687db2e. +// +// Solidity: function connectionsEndpoints(uint256 ) view returns(address) +func (_BitcoinState *BitcoinStateSession) ConnectionsEndpoints(arg0 *big.Int) (common.Address, error) { + return _BitcoinState.Contract.ConnectionsEndpoints(&_BitcoinState.CallOpts, arg0) +} + +// ConnectionsEndpoints is a free data retrieval call binding the contract method 0xb687db2e. +// +// Solidity: function connectionsEndpoints(uint256 ) view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) ConnectionsEndpoints(arg0 *big.Int) (common.Address, error) { + return _BitcoinState.Contract.ConnectionsEndpoints(&_BitcoinState.CallOpts, arg0) +} + +// ExcludeArtifacts is a free data retrieval call binding the contract method 0xb5508aa9. +// +// Solidity: function excludeArtifacts() view returns(string[] excludedArtifacts_) +func (_BitcoinState *BitcoinStateCaller) ExcludeArtifacts(opts *bind.CallOpts) ([]string, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "excludeArtifacts") + + if err != nil { + return *new([]string), err + } + + out0 := *abi.ConvertType(out[0], new([]string)).(*[]string) + + return out0, err + +} + +// ExcludeArtifacts is a free data retrieval call binding the contract method 0xb5508aa9. +// +// Solidity: function excludeArtifacts() view returns(string[] excludedArtifacts_) +func (_BitcoinState *BitcoinStateSession) ExcludeArtifacts() ([]string, error) { + return _BitcoinState.Contract.ExcludeArtifacts(&_BitcoinState.CallOpts) +} + +// ExcludeArtifacts is a free data retrieval call binding the contract method 0xb5508aa9. +// +// Solidity: function excludeArtifacts() view returns(string[] excludedArtifacts_) +func (_BitcoinState *BitcoinStateCallerSession) ExcludeArtifacts() ([]string, error) { + return _BitcoinState.Contract.ExcludeArtifacts(&_BitcoinState.CallOpts) +} + +// ExcludeContracts is a free data retrieval call binding the contract method 0xe20c9f71. +// +// Solidity: function excludeContracts() view returns(address[] excludedContracts_) +func (_BitcoinState *BitcoinStateCaller) ExcludeContracts(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "excludeContracts") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// ExcludeContracts is a free data retrieval call binding the contract method 0xe20c9f71. +// +// Solidity: function excludeContracts() view returns(address[] excludedContracts_) +func (_BitcoinState *BitcoinStateSession) ExcludeContracts() ([]common.Address, error) { + return _BitcoinState.Contract.ExcludeContracts(&_BitcoinState.CallOpts) +} + +// ExcludeContracts is a free data retrieval call binding the contract method 0xe20c9f71. +// +// Solidity: function excludeContracts() view returns(address[] excludedContracts_) +func (_BitcoinState *BitcoinStateCallerSession) ExcludeContracts() ([]common.Address, error) { + return _BitcoinState.Contract.ExcludeContracts(&_BitcoinState.CallOpts) +} + +// ExcludeSelectors is a free data retrieval call binding the contract method 0xb0464fdc. +// +// Solidity: function excludeSelectors() view returns((address,bytes4[])[] excludedSelectors_) +func (_BitcoinState *BitcoinStateCaller) ExcludeSelectors(opts *bind.CallOpts) ([]StdInvariantFuzzSelector, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "excludeSelectors") + + if err != nil { + return *new([]StdInvariantFuzzSelector), err + } + + out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzSelector)).(*[]StdInvariantFuzzSelector) + + return out0, err + +} + +// ExcludeSelectors is a free data retrieval call binding the contract method 0xb0464fdc. +// +// Solidity: function excludeSelectors() view returns((address,bytes4[])[] excludedSelectors_) +func (_BitcoinState *BitcoinStateSession) ExcludeSelectors() ([]StdInvariantFuzzSelector, error) { + return _BitcoinState.Contract.ExcludeSelectors(&_BitcoinState.CallOpts) +} + +// ExcludeSelectors is a free data retrieval call binding the contract method 0xb0464fdc. +// +// Solidity: function excludeSelectors() view returns((address,bytes4[])[] excludedSelectors_) +func (_BitcoinState *BitcoinStateCallerSession) ExcludeSelectors() ([]StdInvariantFuzzSelector, error) { + return _BitcoinState.Contract.ExcludeSelectors(&_BitcoinState.CallOpts) +} + +// ExcludeSenders is a free data retrieval call binding the contract method 0x1ed7831c. +// +// Solidity: function excludeSenders() view returns(address[] excludedSenders_) +func (_BitcoinState *BitcoinStateCaller) ExcludeSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "excludeSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// ExcludeSenders is a free data retrieval call binding the contract method 0x1ed7831c. +// +// Solidity: function excludeSenders() view returns(address[] excludedSenders_) +func (_BitcoinState *BitcoinStateSession) ExcludeSenders() ([]common.Address, error) { + return _BitcoinState.Contract.ExcludeSenders(&_BitcoinState.CallOpts) +} + +// ExcludeSenders is a free data retrieval call binding the contract method 0x1ed7831c. +// +// Solidity: function excludeSenders() view returns(address[] excludedSenders_) +func (_BitcoinState *BitcoinStateCallerSession) ExcludeSenders() ([]common.Address, error) { + return _BitcoinState.Contract.ExcludeSenders(&_BitcoinState.CallOpts) +} + +// Failed is a free data retrieval call binding the contract method 0xba414fa6. +// +// Solidity: function failed() view returns(bool) +func (_BitcoinState *BitcoinStateCaller) Failed(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "failed") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// Failed is a free data retrieval call binding the contract method 0xba414fa6. +// +// Solidity: function failed() view returns(bool) +func (_BitcoinState *BitcoinStateSession) Failed() (bool, error) { + return _BitcoinState.Contract.Failed(&_BitcoinState.CallOpts) +} + +// Failed is a free data retrieval call binding the contract method 0xba414fa6. +// +// Solidity: function failed() view returns(bool) +func (_BitcoinState *BitcoinStateCallerSession) Failed() (bool, error) { + return _BitcoinState.Contract.Failed(&_BitcoinState.CallOpts) +} + +// InitPool is a free data retrieval call binding the contract method 0xca38b326. +// +// Solidity: function initPool(bytes data_) pure returns() +func (_BitcoinState *BitcoinStateCaller) InitPool(opts *bind.CallOpts, data_ []byte) error { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "initPool", data_) + + if err != nil { + return err + } + + return err + +} + +// InitPool is a free data retrieval call binding the contract method 0xca38b326. +// +// Solidity: function initPool(bytes data_) pure returns() +func (_BitcoinState *BitcoinStateSession) InitPool(data_ []byte) error { + return _BitcoinState.Contract.InitPool(&_BitcoinState.CallOpts, data_) +} + +// InitPool is a free data retrieval call binding the contract method 0xca38b326. +// +// Solidity: function initPool(bytes data_) pure returns() +func (_BitcoinState *BitcoinStateCallerSession) InitPool(data_ []byte) error { + return _BitcoinState.Contract.InitPool(&_BitcoinState.CallOpts, data_) +} + +// NftOwners is a free data retrieval call binding the contract method 0xbbd94c2f. +// +// Solidity: function nftOwners(uint256 ) view returns(address) +func (_BitcoinState *BitcoinStateCaller) NftOwners(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "nftOwners", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// NftOwners is a free data retrieval call binding the contract method 0xbbd94c2f. +// +// Solidity: function nftOwners(uint256 ) view returns(address) +func (_BitcoinState *BitcoinStateSession) NftOwners(arg0 *big.Int) (common.Address, error) { + return _BitcoinState.Contract.NftOwners(&_BitcoinState.CallOpts, arg0) +} + +// NftOwners is a free data retrieval call binding the contract method 0xbbd94c2f. +// +// Solidity: function nftOwners(uint256 ) view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) NftOwners(arg0 *big.Int) (common.Address, error) { + return _BitcoinState.Contract.NftOwners(&_BitcoinState.CallOpts, arg0) +} + +// NonFungibleManager is a free data retrieval call binding the contract method 0xecc28165. +// +// Solidity: function nonFungibleManager() view returns(address) +func (_BitcoinState *BitcoinStateCaller) NonFungibleManager(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "nonFungibleManager") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// NonFungibleManager is a free data retrieval call binding the contract method 0xecc28165. +// +// Solidity: function nonFungibleManager() view returns(address) +func (_BitcoinState *BitcoinStateSession) NonFungibleManager() (common.Address, error) { + return _BitcoinState.Contract.NonFungibleManager(&_BitcoinState.CallOpts) +} + +// NonFungibleManager is a free data retrieval call binding the contract method 0xecc28165. +// +// Solidity: function nonFungibleManager() view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) NonFungibleManager() (common.Address, error) { + return _BitcoinState.Contract.NonFungibleManager(&_BitcoinState.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_BitcoinState *BitcoinStateCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_BitcoinState *BitcoinStateSession) Owner() (common.Address, error) { + return _BitcoinState.Contract.Owner(&_BitcoinState.CallOpts) +} + +// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. +// +// Solidity: function owner() view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) Owner() (common.Address, error) { + return _BitcoinState.Contract.Owner(&_BitcoinState.CallOpts) +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns((string,string)) +func (_BitcoinState *BitcoinStateCaller) Params(opts *bind.CallOpts) (IBitcoinStateTokenInfo, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "params") + + if err != nil { + return *new(IBitcoinStateTokenInfo), err + } + + out0 := *abi.ConvertType(out[0], new(IBitcoinStateTokenInfo)).(*IBitcoinStateTokenInfo) + + return out0, err + +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns((string,string)) +func (_BitcoinState *BitcoinStateSession) Params() (IBitcoinStateTokenInfo, error) { + return _BitcoinState.Contract.Params(&_BitcoinState.CallOpts) +} + +// Params is a free data retrieval call binding the contract method 0xcff0ab96. +// +// Solidity: function params() view returns((string,string)) +func (_BitcoinState *BitcoinStateCallerSession) Params() (IBitcoinStateTokenInfo, error) { + return _BitcoinState.Contract.Params(&_BitcoinState.CallOpts) +} + +// RemoveLiquidity is a free data retrieval call binding the contract method 0x028318cf. +// +// Solidity: function removeLiquidity(bytes data_) pure returns() +func (_BitcoinState *BitcoinStateCaller) RemoveLiquidity(opts *bind.CallOpts, data_ []byte) error { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "removeLiquidity", data_) + + if err != nil { + return err + } + + return err + +} + +// RemoveLiquidity is a free data retrieval call binding the contract method 0x028318cf. +// +// Solidity: function removeLiquidity(bytes data_) pure returns() +func (_BitcoinState *BitcoinStateSession) RemoveLiquidity(data_ []byte) error { + return _BitcoinState.Contract.RemoveLiquidity(&_BitcoinState.CallOpts, data_) +} + +// RemoveLiquidity is a free data retrieval call binding the contract method 0x028318cf. +// +// Solidity: function removeLiquidity(bytes data_) pure returns() +func (_BitcoinState *BitcoinStateCallerSession) RemoveLiquidity(data_ []byte) error { + return _BitcoinState.Contract.RemoveLiquidity(&_BitcoinState.CallOpts, data_) +} + +// RouterV2 is a free data retrieval call binding the contract method 0x502f7446. +// +// Solidity: function routerV2() view returns(address) +func (_BitcoinState *BitcoinStateCaller) RouterV2(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "routerV2") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// RouterV2 is a free data retrieval call binding the contract method 0x502f7446. +// +// Solidity: function routerV2() view returns(address) +func (_BitcoinState *BitcoinStateSession) RouterV2() (common.Address, error) { + return _BitcoinState.Contract.RouterV2(&_BitcoinState.CallOpts) +} + +// RouterV2 is a free data retrieval call binding the contract method 0x502f7446. +// +// Solidity: function routerV2() view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) RouterV2() (common.Address, error) { + return _BitcoinState.Contract.RouterV2(&_BitcoinState.CallOpts) +} + +// TargetArtifactSelectors is a free data retrieval call binding the contract method 0x66d9a9a0. +// +// Solidity: function targetArtifactSelectors() view returns((string,bytes4[])[] targetedArtifactSelectors_) +func (_BitcoinState *BitcoinStateCaller) TargetArtifactSelectors(opts *bind.CallOpts) ([]StdInvariantFuzzArtifactSelector, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "targetArtifactSelectors") + + if err != nil { + return *new([]StdInvariantFuzzArtifactSelector), err + } + + out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzArtifactSelector)).(*[]StdInvariantFuzzArtifactSelector) + + return out0, err + +} + +// TargetArtifactSelectors is a free data retrieval call binding the contract method 0x66d9a9a0. +// +// Solidity: function targetArtifactSelectors() view returns((string,bytes4[])[] targetedArtifactSelectors_) +func (_BitcoinState *BitcoinStateSession) TargetArtifactSelectors() ([]StdInvariantFuzzArtifactSelector, error) { + return _BitcoinState.Contract.TargetArtifactSelectors(&_BitcoinState.CallOpts) +} + +// TargetArtifactSelectors is a free data retrieval call binding the contract method 0x66d9a9a0. +// +// Solidity: function targetArtifactSelectors() view returns((string,bytes4[])[] targetedArtifactSelectors_) +func (_BitcoinState *BitcoinStateCallerSession) TargetArtifactSelectors() ([]StdInvariantFuzzArtifactSelector, error) { + return _BitcoinState.Contract.TargetArtifactSelectors(&_BitcoinState.CallOpts) +} + +// TargetArtifacts is a free data retrieval call binding the contract method 0x85226c81. +// +// Solidity: function targetArtifacts() view returns(string[] targetedArtifacts_) +func (_BitcoinState *BitcoinStateCaller) TargetArtifacts(opts *bind.CallOpts) ([]string, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "targetArtifacts") + + if err != nil { + return *new([]string), err + } + + out0 := *abi.ConvertType(out[0], new([]string)).(*[]string) + + return out0, err + +} + +// TargetArtifacts is a free data retrieval call binding the contract method 0x85226c81. +// +// Solidity: function targetArtifacts() view returns(string[] targetedArtifacts_) +func (_BitcoinState *BitcoinStateSession) TargetArtifacts() ([]string, error) { + return _BitcoinState.Contract.TargetArtifacts(&_BitcoinState.CallOpts) +} + +// TargetArtifacts is a free data retrieval call binding the contract method 0x85226c81. +// +// Solidity: function targetArtifacts() view returns(string[] targetedArtifacts_) +func (_BitcoinState *BitcoinStateCallerSession) TargetArtifacts() ([]string, error) { + return _BitcoinState.Contract.TargetArtifacts(&_BitcoinState.CallOpts) +} + +// TargetContracts is a free data retrieval call binding the contract method 0x3f7286f4. +// +// Solidity: function targetContracts() view returns(address[] targetedContracts_) +func (_BitcoinState *BitcoinStateCaller) TargetContracts(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "targetContracts") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// TargetContracts is a free data retrieval call binding the contract method 0x3f7286f4. +// +// Solidity: function targetContracts() view returns(address[] targetedContracts_) +func (_BitcoinState *BitcoinStateSession) TargetContracts() ([]common.Address, error) { + return _BitcoinState.Contract.TargetContracts(&_BitcoinState.CallOpts) +} + +// TargetContracts is a free data retrieval call binding the contract method 0x3f7286f4. +// +// Solidity: function targetContracts() view returns(address[] targetedContracts_) +func (_BitcoinState *BitcoinStateCallerSession) TargetContracts() ([]common.Address, error) { + return _BitcoinState.Contract.TargetContracts(&_BitcoinState.CallOpts) +} + +// TargetInterfaces is a free data retrieval call binding the contract method 0x2ade3880. +// +// Solidity: function targetInterfaces() view returns((address,string[])[] targetedInterfaces_) +func (_BitcoinState *BitcoinStateCaller) TargetInterfaces(opts *bind.CallOpts) ([]StdInvariantFuzzInterface, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "targetInterfaces") + + if err != nil { + return *new([]StdInvariantFuzzInterface), err + } + + out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzInterface)).(*[]StdInvariantFuzzInterface) + + return out0, err + +} + +// TargetInterfaces is a free data retrieval call binding the contract method 0x2ade3880. +// +// Solidity: function targetInterfaces() view returns((address,string[])[] targetedInterfaces_) +func (_BitcoinState *BitcoinStateSession) TargetInterfaces() ([]StdInvariantFuzzInterface, error) { + return _BitcoinState.Contract.TargetInterfaces(&_BitcoinState.CallOpts) +} + +// TargetInterfaces is a free data retrieval call binding the contract method 0x2ade3880. +// +// Solidity: function targetInterfaces() view returns((address,string[])[] targetedInterfaces_) +func (_BitcoinState *BitcoinStateCallerSession) TargetInterfaces() ([]StdInvariantFuzzInterface, error) { + return _BitcoinState.Contract.TargetInterfaces(&_BitcoinState.CallOpts) +} + +// TargetSelectors is a free data retrieval call binding the contract method 0x916a17c6. +// +// Solidity: function targetSelectors() view returns((address,bytes4[])[] targetedSelectors_) +func (_BitcoinState *BitcoinStateCaller) TargetSelectors(opts *bind.CallOpts) ([]StdInvariantFuzzSelector, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "targetSelectors") + + if err != nil { + return *new([]StdInvariantFuzzSelector), err + } + + out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzSelector)).(*[]StdInvariantFuzzSelector) + + return out0, err + +} + +// TargetSelectors is a free data retrieval call binding the contract method 0x916a17c6. +// +// Solidity: function targetSelectors() view returns((address,bytes4[])[] targetedSelectors_) +func (_BitcoinState *BitcoinStateSession) TargetSelectors() ([]StdInvariantFuzzSelector, error) { + return _BitcoinState.Contract.TargetSelectors(&_BitcoinState.CallOpts) +} + +// TargetSelectors is a free data retrieval call binding the contract method 0x916a17c6. +// +// Solidity: function targetSelectors() view returns((address,bytes4[])[] targetedSelectors_) +func (_BitcoinState *BitcoinStateCallerSession) TargetSelectors() ([]StdInvariantFuzzSelector, error) { + return _BitcoinState.Contract.TargetSelectors(&_BitcoinState.CallOpts) +} + +// TargetSenders is a free data retrieval call binding the contract method 0x3e5e3c23. +// +// Solidity: function targetSenders() view returns(address[] targetedSenders_) +func (_BitcoinState *BitcoinStateCaller) TargetSenders(opts *bind.CallOpts) ([]common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "targetSenders") + + if err != nil { + return *new([]common.Address), err + } + + out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) + + return out0, err + +} + +// TargetSenders is a free data retrieval call binding the contract method 0x3e5e3c23. +// +// Solidity: function targetSenders() view returns(address[] targetedSenders_) +func (_BitcoinState *BitcoinStateSession) TargetSenders() ([]common.Address, error) { + return _BitcoinState.Contract.TargetSenders(&_BitcoinState.CallOpts) +} + +// TargetSenders is a free data retrieval call binding the contract method 0x3e5e3c23. +// +// Solidity: function targetSenders() view returns(address[] targetedSenders_) +func (_BitcoinState *BitcoinStateCallerSession) TargetSenders() ([]common.Address, error) { + return _BitcoinState.Contract.TargetSenders(&_BitcoinState.CallOpts) +} + +// Tokens is a free data retrieval call binding the contract method 0x904194a3. +// +// Solidity: function tokens(bytes32 ) view returns(address) +func (_BitcoinState *BitcoinStateCaller) Tokens(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "tokens", arg0) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Tokens is a free data retrieval call binding the contract method 0x904194a3. +// +// Solidity: function tokens(bytes32 ) view returns(address) +func (_BitcoinState *BitcoinStateSession) Tokens(arg0 [32]byte) (common.Address, error) { + return _BitcoinState.Contract.Tokens(&_BitcoinState.CallOpts, arg0) +} + +// Tokens is a free data retrieval call binding the contract method 0x904194a3. +// +// Solidity: function tokens(bytes32 ) view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) Tokens(arg0 [32]byte) (common.Address, error) { + return _BitcoinState.Contract.Tokens(&_BitcoinState.CallOpts, arg0) +} + +// XcallService is a free data retrieval call binding the contract method 0x7bf07164. +// +// Solidity: function xcallService() view returns(address) +func (_BitcoinState *BitcoinStateCaller) XcallService(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _BitcoinState.contract.Call(opts, &out, "xcallService") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// XcallService is a free data retrieval call binding the contract method 0x7bf07164. +// +// Solidity: function xcallService() view returns(address) +func (_BitcoinState *BitcoinStateSession) XcallService() (common.Address, error) { + return _BitcoinState.Contract.XcallService(&_BitcoinState.CallOpts) +} + +// XcallService is a free data retrieval call binding the contract method 0x7bf07164. +// +// Solidity: function xcallService() view returns(address) +func (_BitcoinState *BitcoinStateCallerSession) XcallService() (common.Address, error) { + return _BitcoinState.Contract.XcallService(&_BitcoinState.CallOpts) +} + +// AddConnection is a paid mutator transaction binding the contract method 0x677dea1d. +// +// Solidity: function addConnection(address connection_) returns() +func (_BitcoinState *BitcoinStateTransactor) AddConnection(opts *bind.TransactOpts, connection_ common.Address) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "addConnection", connection_) +} + +// AddConnection is a paid mutator transaction binding the contract method 0x677dea1d. +// +// Solidity: function addConnection(address connection_) returns() +func (_BitcoinState *BitcoinStateSession) AddConnection(connection_ common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.AddConnection(&_BitcoinState.TransactOpts, connection_) +} + +// AddConnection is a paid mutator transaction binding the contract method 0x677dea1d. +// +// Solidity: function addConnection(address connection_) returns() +func (_BitcoinState *BitcoinStateTransactorSession) AddConnection(connection_ common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.AddConnection(&_BitcoinState.TransactOpts, connection_) +} + +// GetSignData is a paid mutator transaction binding the contract method 0xbcc2f19d. +// +// Solidity: function getSignData(address requester_, bytes data_) returns(bytes32) +func (_BitcoinState *BitcoinStateTransactor) GetSignData(opts *bind.TransactOpts, requester_ common.Address, data_ []byte) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "getSignData", requester_, data_) +} + +// GetSignData is a paid mutator transaction binding the contract method 0xbcc2f19d. +// +// Solidity: function getSignData(address requester_, bytes data_) returns(bytes32) +func (_BitcoinState *BitcoinStateSession) GetSignData(requester_ common.Address, data_ []byte) (*types.Transaction, error) { + return _BitcoinState.Contract.GetSignData(&_BitcoinState.TransactOpts, requester_, data_) +} + +// GetSignData is a paid mutator transaction binding the contract method 0xbcc2f19d. +// +// Solidity: function getSignData(address requester_, bytes data_) returns(bytes32) +func (_BitcoinState *BitcoinStateTransactorSession) GetSignData(requester_ common.Address, data_ []byte) (*types.Transaction, error) { + return _BitcoinState.Contract.GetSignData(&_BitcoinState.TransactOpts, requester_, data_) +} + +// HandleCallMessage is a paid mutator transaction binding the contract method 0x5d6a16f5. +// +// Solidity: function handleCallMessage(string _from, bytes _data, string[] _protocols) returns() +func (_BitcoinState *BitcoinStateTransactor) HandleCallMessage(opts *bind.TransactOpts, _from string, _data []byte, _protocols []string) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "handleCallMessage", _from, _data, _protocols) +} + +// HandleCallMessage is a paid mutator transaction binding the contract method 0x5d6a16f5. +// +// Solidity: function handleCallMessage(string _from, bytes _data, string[] _protocols) returns() +func (_BitcoinState *BitcoinStateSession) HandleCallMessage(_from string, _data []byte, _protocols []string) (*types.Transaction, error) { + return _BitcoinState.Contract.HandleCallMessage(&_BitcoinState.TransactOpts, _from, _data, _protocols) +} + +// HandleCallMessage is a paid mutator transaction binding the contract method 0x5d6a16f5. +// +// Solidity: function handleCallMessage(string _from, bytes _data, string[] _protocols) returns() +func (_BitcoinState *BitcoinStateTransactorSession) HandleCallMessage(_from string, _data []byte, _protocols []string) (*types.Transaction, error) { + return _BitcoinState.Contract.HandleCallMessage(&_BitcoinState.TransactOpts, _from, _data, _protocols) +} + +// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. +// +// Solidity: function initialize(address xcall_, address uinswapV3Router_, address nonfungiblePositionManager_, address[] connections) returns() +func (_BitcoinState *BitcoinStateTransactor) Initialize(opts *bind.TransactOpts, xcall_ common.Address, uinswapV3Router_ common.Address, nonfungiblePositionManager_ common.Address, connections []common.Address) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "initialize", xcall_, uinswapV3Router_, nonfungiblePositionManager_, connections) +} + +// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. +// +// Solidity: function initialize(address xcall_, address uinswapV3Router_, address nonfungiblePositionManager_, address[] connections) returns() +func (_BitcoinState *BitcoinStateSession) Initialize(xcall_ common.Address, uinswapV3Router_ common.Address, nonfungiblePositionManager_ common.Address, connections []common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.Initialize(&_BitcoinState.TransactOpts, xcall_, uinswapV3Router_, nonfungiblePositionManager_, connections) +} + +// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. +// +// Solidity: function initialize(address xcall_, address uinswapV3Router_, address nonfungiblePositionManager_, address[] connections) returns() +func (_BitcoinState *BitcoinStateTransactorSession) Initialize(xcall_ common.Address, uinswapV3Router_ common.Address, nonfungiblePositionManager_ common.Address, connections []common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.Initialize(&_BitcoinState.TransactOpts, xcall_, uinswapV3Router_, nonfungiblePositionManager_, connections) +} + +// Migrate is a paid mutator transaction binding the contract method 0x8932a90d. +// +// Solidity: function migrate(bytes _data) returns() +func (_BitcoinState *BitcoinStateTransactor) Migrate(opts *bind.TransactOpts, _data []byte) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "migrate", _data) +} + +// Migrate is a paid mutator transaction binding the contract method 0x8932a90d. +// +// Solidity: function migrate(bytes _data) returns() +func (_BitcoinState *BitcoinStateSession) Migrate(_data []byte) (*types.Transaction, error) { + return _BitcoinState.Contract.Migrate(&_BitcoinState.TransactOpts, _data) +} + +// Migrate is a paid mutator transaction binding the contract method 0x8932a90d. +// +// Solidity: function migrate(bytes _data) returns() +func (_BitcoinState *BitcoinStateTransactorSession) Migrate(_data []byte) (*types.Transaction, error) { + return _BitcoinState.Contract.Migrate(&_BitcoinState.TransactOpts, _data) +} + +// MigrateComplete is a paid mutator transaction binding the contract method 0xf0ad3762. +// +// Solidity: function migrateComplete() returns() +func (_BitcoinState *BitcoinStateTransactor) MigrateComplete(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "migrateComplete") +} + +// MigrateComplete is a paid mutator transaction binding the contract method 0xf0ad3762. +// +// Solidity: function migrateComplete() returns() +func (_BitcoinState *BitcoinStateSession) MigrateComplete() (*types.Transaction, error) { + return _BitcoinState.Contract.MigrateComplete(&_BitcoinState.TransactOpts) +} + +// MigrateComplete is a paid mutator transaction binding the contract method 0xf0ad3762. +// +// Solidity: function migrateComplete() returns() +func (_BitcoinState *BitcoinStateTransactorSession) MigrateComplete() (*types.Transaction, error) { + return _BitcoinState.Contract.MigrateComplete(&_BitcoinState.TransactOpts) +} + +// RemoveConnection is a paid mutator transaction binding the contract method 0x65301f0d. +// +// Solidity: function removeConnection(address connection_) returns() +func (_BitcoinState *BitcoinStateTransactor) RemoveConnection(opts *bind.TransactOpts, connection_ common.Address) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "removeConnection", connection_) +} + +// RemoveConnection is a paid mutator transaction binding the contract method 0x65301f0d. +// +// Solidity: function removeConnection(address connection_) returns() +func (_BitcoinState *BitcoinStateSession) RemoveConnection(connection_ common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.RemoveConnection(&_BitcoinState.TransactOpts, connection_) +} + +// RemoveConnection is a paid mutator transaction binding the contract method 0x65301f0d. +// +// Solidity: function removeConnection(address connection_) returns() +func (_BitcoinState *BitcoinStateTransactorSession) RemoveConnection(connection_ common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.RemoveConnection(&_BitcoinState.TransactOpts, connection_) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_BitcoinState *BitcoinStateTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "renounceOwnership") +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_BitcoinState *BitcoinStateSession) RenounceOwnership() (*types.Transaction, error) { + return _BitcoinState.Contract.RenounceOwnership(&_BitcoinState.TransactOpts) +} + +// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. +// +// Solidity: function renounceOwnership() returns() +func (_BitcoinState *BitcoinStateTransactorSession) RenounceOwnership() (*types.Transaction, error) { + return _BitcoinState.Contract.RenounceOwnership(&_BitcoinState.TransactOpts) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_BitcoinState *BitcoinStateTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { + return _BitcoinState.contract.Transact(opts, "transferOwnership", newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_BitcoinState *BitcoinStateSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.TransferOwnership(&_BitcoinState.TransactOpts, newOwner) +} + +// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. +// +// Solidity: function transferOwnership(address newOwner) returns() +func (_BitcoinState *BitcoinStateTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { + return _BitcoinState.Contract.TransferOwnership(&_BitcoinState.TransactOpts, newOwner) +} + +// BitcoinStateAddConnectionIterator is returned from FilterAddConnection and is used to iterate over the raw logs and unpacked data for AddConnection events raised by the BitcoinState contract. +type BitcoinStateAddConnectionIterator struct { + Event *BitcoinStateAddConnection // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateAddConnectionIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateAddConnection) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateAddConnection) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateAddConnectionIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateAddConnectionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateAddConnection represents a AddConnection event raised by the BitcoinState contract. +type BitcoinStateAddConnection struct { + Connection common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddConnection is a free log retrieval operation binding the contract event 0x5cd3d8da8ef00a8b5228348fe7683dae605751d4867ba7ea9fdc8260b9e2c7d3. +// +// Solidity: event AddConnection(address connection_) +func (_BitcoinState *BitcoinStateFilterer) FilterAddConnection(opts *bind.FilterOpts) (*BitcoinStateAddConnectionIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "AddConnection") + if err != nil { + return nil, err + } + return &BitcoinStateAddConnectionIterator{contract: _BitcoinState.contract, event: "AddConnection", logs: logs, sub: sub}, nil +} + +// WatchAddConnection is a free log subscription operation binding the contract event 0x5cd3d8da8ef00a8b5228348fe7683dae605751d4867ba7ea9fdc8260b9e2c7d3. +// +// Solidity: event AddConnection(address connection_) +func (_BitcoinState *BitcoinStateFilterer) WatchAddConnection(opts *bind.WatchOpts, sink chan<- *BitcoinStateAddConnection) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "AddConnection") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateAddConnection) + if err := _BitcoinState.contract.UnpackLog(event, "AddConnection", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddConnection is a log parse operation binding the contract event 0x5cd3d8da8ef00a8b5228348fe7683dae605751d4867ba7ea9fdc8260b9e2c7d3. +// +// Solidity: event AddConnection(address connection_) +func (_BitcoinState *BitcoinStateFilterer) ParseAddConnection(log types.Log) (*BitcoinStateAddConnection, error) { + event := new(BitcoinStateAddConnection) + if err := _BitcoinState.contract.UnpackLog(event, "AddConnection", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateAddSelectorIterator is returned from FilterAddSelector and is used to iterate over the raw logs and unpacked data for AddSelector events raised by the BitcoinState contract. +type BitcoinStateAddSelectorIterator struct { + Event *BitcoinStateAddSelector // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateAddSelectorIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateAddSelector) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateAddSelector) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateAddSelectorIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateAddSelectorIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateAddSelector represents a AddSelector event raised by the BitcoinState contract. +type BitcoinStateAddSelector struct { + Selector [4]byte + Recipient common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterAddSelector is a free log retrieval operation binding the contract event 0x95c0d09571a33725bdfaf52708354735c2650abb90fe193d20429e324a2b3696. +// +// Solidity: event AddSelector(bytes4 selector_, address recipient) +func (_BitcoinState *BitcoinStateFilterer) FilterAddSelector(opts *bind.FilterOpts) (*BitcoinStateAddSelectorIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "AddSelector") + if err != nil { + return nil, err + } + return &BitcoinStateAddSelectorIterator{contract: _BitcoinState.contract, event: "AddSelector", logs: logs, sub: sub}, nil +} + +// WatchAddSelector is a free log subscription operation binding the contract event 0x95c0d09571a33725bdfaf52708354735c2650abb90fe193d20429e324a2b3696. +// +// Solidity: event AddSelector(bytes4 selector_, address recipient) +func (_BitcoinState *BitcoinStateFilterer) WatchAddSelector(opts *bind.WatchOpts, sink chan<- *BitcoinStateAddSelector) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "AddSelector") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateAddSelector) + if err := _BitcoinState.contract.UnpackLog(event, "AddSelector", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseAddSelector is a log parse operation binding the contract event 0x95c0d09571a33725bdfaf52708354735c2650abb90fe193d20429e324a2b3696. +// +// Solidity: event AddSelector(bytes4 selector_, address recipient) +func (_BitcoinState *BitcoinStateFilterer) ParseAddSelector(log types.Log) (*BitcoinStateAddSelector, error) { + event := new(BitcoinStateAddSelector) + if err := _BitcoinState.contract.UnpackLog(event, "AddSelector", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the BitcoinState contract. +type BitcoinStateInitializedIterator struct { + Event *BitcoinStateInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateInitialized represents a Initialized event raised by the BitcoinState contract. +type BitcoinStateInitialized struct { + Version uint8 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_BitcoinState *BitcoinStateFilterer) FilterInitialized(opts *bind.FilterOpts) (*BitcoinStateInitializedIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &BitcoinStateInitializedIterator{contract: _BitcoinState.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_BitcoinState *BitcoinStateFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *BitcoinStateInitialized) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateInitialized) + if err := _BitcoinState.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. +// +// Solidity: event Initialized(uint8 version) +func (_BitcoinState *BitcoinStateFilterer) ParseInitialized(log types.Log) (*BitcoinStateInitialized, error) { + event := new(BitcoinStateInitialized) + if err := _BitcoinState.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the BitcoinState contract. +type BitcoinStateOwnershipTransferredIterator struct { + Event *BitcoinStateOwnershipTransferred // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateOwnershipTransferredIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateOwnershipTransferredIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateOwnershipTransferred represents a OwnershipTransferred event raised by the BitcoinState contract. +type BitcoinStateOwnershipTransferred struct { + PreviousOwner common.Address + NewOwner common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_BitcoinState *BitcoinStateFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*BitcoinStateOwnershipTransferredIterator, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return &BitcoinStateOwnershipTransferredIterator{contract: _BitcoinState.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_BitcoinState *BitcoinStateFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BitcoinStateOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { + + var previousOwnerRule []interface{} + for _, previousOwnerItem := range previousOwner { + previousOwnerRule = append(previousOwnerRule, previousOwnerItem) + } + var newOwnerRule []interface{} + for _, newOwnerItem := range newOwner { + newOwnerRule = append(newOwnerRule, newOwnerItem) + } + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateOwnershipTransferred) + if err := _BitcoinState.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. +// +// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) +func (_BitcoinState *BitcoinStateFilterer) ParseOwnershipTransferred(log types.Log) (*BitcoinStateOwnershipTransferred, error) { + event := new(BitcoinStateOwnershipTransferred) + if err := _BitcoinState.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateRemoveConnectionIterator is returned from FilterRemoveConnection and is used to iterate over the raw logs and unpacked data for RemoveConnection events raised by the BitcoinState contract. +type BitcoinStateRemoveConnectionIterator struct { + Event *BitcoinStateRemoveConnection // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateRemoveConnectionIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateRemoveConnection) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateRemoveConnection) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateRemoveConnectionIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateRemoveConnectionIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateRemoveConnection represents a RemoveConnection event raised by the BitcoinState contract. +type BitcoinStateRemoveConnection struct { + Connection common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRemoveConnection is a free log retrieval operation binding the contract event 0xace8d11a44b7aa536cc46a77b519166c001adc485ba8cfa404e1aa252b07db38. +// +// Solidity: event RemoveConnection(address connection_) +func (_BitcoinState *BitcoinStateFilterer) FilterRemoveConnection(opts *bind.FilterOpts) (*BitcoinStateRemoveConnectionIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "RemoveConnection") + if err != nil { + return nil, err + } + return &BitcoinStateRemoveConnectionIterator{contract: _BitcoinState.contract, event: "RemoveConnection", logs: logs, sub: sub}, nil +} + +// WatchRemoveConnection is a free log subscription operation binding the contract event 0xace8d11a44b7aa536cc46a77b519166c001adc485ba8cfa404e1aa252b07db38. +// +// Solidity: event RemoveConnection(address connection_) +func (_BitcoinState *BitcoinStateFilterer) WatchRemoveConnection(opts *bind.WatchOpts, sink chan<- *BitcoinStateRemoveConnection) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "RemoveConnection") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateRemoveConnection) + if err := _BitcoinState.contract.UnpackLog(event, "RemoveConnection", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRemoveConnection is a log parse operation binding the contract event 0xace8d11a44b7aa536cc46a77b519166c001adc485ba8cfa404e1aa252b07db38. +// +// Solidity: event RemoveConnection(address connection_) +func (_BitcoinState *BitcoinStateFilterer) ParseRemoveConnection(log types.Log) (*BitcoinStateRemoveConnection, error) { + event := new(BitcoinStateRemoveConnection) + if err := _BitcoinState.contract.UnpackLog(event, "RemoveConnection", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateRemoveSelectorIterator is returned from FilterRemoveSelector and is used to iterate over the raw logs and unpacked data for RemoveSelector events raised by the BitcoinState contract. +type BitcoinStateRemoveSelectorIterator struct { + Event *BitcoinStateRemoveSelector // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateRemoveSelectorIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateRemoveSelector) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateRemoveSelector) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateRemoveSelectorIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateRemoveSelectorIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateRemoveSelector represents a RemoveSelector event raised by the BitcoinState contract. +type BitcoinStateRemoveSelector struct { + Selector [4]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRemoveSelector is a free log retrieval operation binding the contract event 0x85a48e474e38192938033da06ebe84a59fb194958d1be091ac2fa9a6630da31f. +// +// Solidity: event RemoveSelector(bytes4 selector_) +func (_BitcoinState *BitcoinStateFilterer) FilterRemoveSelector(opts *bind.FilterOpts) (*BitcoinStateRemoveSelectorIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "RemoveSelector") + if err != nil { + return nil, err + } + return &BitcoinStateRemoveSelectorIterator{contract: _BitcoinState.contract, event: "RemoveSelector", logs: logs, sub: sub}, nil +} + +// WatchRemoveSelector is a free log subscription operation binding the contract event 0x85a48e474e38192938033da06ebe84a59fb194958d1be091ac2fa9a6630da31f. +// +// Solidity: event RemoveSelector(bytes4 selector_) +func (_BitcoinState *BitcoinStateFilterer) WatchRemoveSelector(opts *bind.WatchOpts, sink chan<- *BitcoinStateRemoveSelector) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "RemoveSelector") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateRemoveSelector) + if err := _BitcoinState.contract.UnpackLog(event, "RemoveSelector", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRemoveSelector is a log parse operation binding the contract event 0x85a48e474e38192938033da06ebe84a59fb194958d1be091ac2fa9a6630da31f. +// +// Solidity: event RemoveSelector(bytes4 selector_) +func (_BitcoinState *BitcoinStateFilterer) ParseRemoveSelector(log types.Log) (*BitcoinStateRemoveSelector, error) { + event := new(BitcoinStateRemoveSelector) + if err := _BitcoinState.contract.UnpackLog(event, "RemoveSelector", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateRequestExecutedIterator is returned from FilterRequestExecuted and is used to iterate over the raw logs and unpacked data for RequestExecuted events raised by the BitcoinState contract. +type BitcoinStateRequestExecutedIterator struct { + Event *BitcoinStateRequestExecuted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateRequestExecutedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateRequestExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateRequestExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateRequestExecutedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateRequestExecutedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateRequestExecuted represents a RequestExecuted event raised by the BitcoinState contract. +type BitcoinStateRequestExecuted struct { + Id *big.Int + StateRoot [32]byte + Data []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRequestExecuted is a free log retrieval operation binding the contract event 0x9c343316d67a8e28446ef883ab491ece3ff70d3eeaa9fbd13a362a0afd690721. +// +// Solidity: event RequestExecuted(uint256 id, bytes32 stateRoot, bytes data) +func (_BitcoinState *BitcoinStateFilterer) FilterRequestExecuted(opts *bind.FilterOpts) (*BitcoinStateRequestExecutedIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "RequestExecuted") + if err != nil { + return nil, err + } + return &BitcoinStateRequestExecutedIterator{contract: _BitcoinState.contract, event: "RequestExecuted", logs: logs, sub: sub}, nil +} + +// WatchRequestExecuted is a free log subscription operation binding the contract event 0x9c343316d67a8e28446ef883ab491ece3ff70d3eeaa9fbd13a362a0afd690721. +// +// Solidity: event RequestExecuted(uint256 id, bytes32 stateRoot, bytes data) +func (_BitcoinState *BitcoinStateFilterer) WatchRequestExecuted(opts *bind.WatchOpts, sink chan<- *BitcoinStateRequestExecuted) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "RequestExecuted") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateRequestExecuted) + if err := _BitcoinState.contract.UnpackLog(event, "RequestExecuted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRequestExecuted is a log parse operation binding the contract event 0x9c343316d67a8e28446ef883ab491ece3ff70d3eeaa9fbd13a362a0afd690721. +// +// Solidity: event RequestExecuted(uint256 id, bytes32 stateRoot, bytes data) +func (_BitcoinState *BitcoinStateFilterer) ParseRequestExecuted(log types.Log) (*BitcoinStateRequestExecuted, error) { + event := new(BitcoinStateRequestExecuted) + if err := _BitcoinState.contract.UnpackLog(event, "RequestExecuted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogIterator is returned from FilterLog and is used to iterate over the raw logs and unpacked data for Log events raised by the BitcoinState contract. +type BitcoinStateLogIterator struct { + Event *BitcoinStateLog // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLog) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLog) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLog represents a Log event raised by the BitcoinState contract. +type BitcoinStateLog struct { + Arg0 string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLog is a free log retrieval operation binding the contract event 0x41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50. +// +// Solidity: event log(string arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLog(opts *bind.FilterOpts) (*BitcoinStateLogIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log") + if err != nil { + return nil, err + } + return &BitcoinStateLogIterator{contract: _BitcoinState.contract, event: "log", logs: logs, sub: sub}, nil +} + +// WatchLog is a free log subscription operation binding the contract event 0x41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50. +// +// Solidity: event log(string arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLog(opts *bind.WatchOpts, sink chan<- *BitcoinStateLog) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLog) + if err := _BitcoinState.contract.UnpackLog(event, "log", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLog is a log parse operation binding the contract event 0x41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50. +// +// Solidity: event log(string arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLog(log types.Log) (*BitcoinStateLog, error) { + event := new(BitcoinStateLog) + if err := _BitcoinState.contract.UnpackLog(event, "log", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogAddressIterator is returned from FilterLogAddress and is used to iterate over the raw logs and unpacked data for LogAddress events raised by the BitcoinState contract. +type BitcoinStateLogAddressIterator struct { + Event *BitcoinStateLogAddress // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogAddressIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogAddress) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogAddress) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogAddressIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogAddressIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogAddress represents a LogAddress event raised by the BitcoinState contract. +type BitcoinStateLogAddress struct { + Arg0 common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogAddress is a free log retrieval operation binding the contract event 0x7ae74c527414ae135fd97047b12921a5ec3911b804197855d67e25c7b75ee6f3. +// +// Solidity: event log_address(address arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLogAddress(opts *bind.FilterOpts) (*BitcoinStateLogAddressIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_address") + if err != nil { + return nil, err + } + return &BitcoinStateLogAddressIterator{contract: _BitcoinState.contract, event: "log_address", logs: logs, sub: sub}, nil +} + +// WatchLogAddress is a free log subscription operation binding the contract event 0x7ae74c527414ae135fd97047b12921a5ec3911b804197855d67e25c7b75ee6f3. +// +// Solidity: event log_address(address arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLogAddress(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogAddress) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_address") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogAddress) + if err := _BitcoinState.contract.UnpackLog(event, "log_address", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogAddress is a log parse operation binding the contract event 0x7ae74c527414ae135fd97047b12921a5ec3911b804197855d67e25c7b75ee6f3. +// +// Solidity: event log_address(address arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLogAddress(log types.Log) (*BitcoinStateLogAddress, error) { + event := new(BitcoinStateLogAddress) + if err := _BitcoinState.contract.UnpackLog(event, "log_address", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogArrayIterator is returned from FilterLogArray and is used to iterate over the raw logs and unpacked data for LogArray events raised by the BitcoinState contract. +type BitcoinStateLogArrayIterator struct { + Event *BitcoinStateLogArray // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogArrayIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogArray) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogArray) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogArrayIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogArrayIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogArray represents a LogArray event raised by the BitcoinState contract. +type BitcoinStateLogArray struct { + Val []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogArray is a free log retrieval operation binding the contract event 0xfb102865d50addddf69da9b5aa1bced66c80cf869a5c8d0471a467e18ce9cab1. +// +// Solidity: event log_array(uint256[] val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogArray(opts *bind.FilterOpts) (*BitcoinStateLogArrayIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_array") + if err != nil { + return nil, err + } + return &BitcoinStateLogArrayIterator{contract: _BitcoinState.contract, event: "log_array", logs: logs, sub: sub}, nil +} + +// WatchLogArray is a free log subscription operation binding the contract event 0xfb102865d50addddf69da9b5aa1bced66c80cf869a5c8d0471a467e18ce9cab1. +// +// Solidity: event log_array(uint256[] val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogArray(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogArray) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_array") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogArray) + if err := _BitcoinState.contract.UnpackLog(event, "log_array", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogArray is a log parse operation binding the contract event 0xfb102865d50addddf69da9b5aa1bced66c80cf869a5c8d0471a467e18ce9cab1. +// +// Solidity: event log_array(uint256[] val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogArray(log types.Log) (*BitcoinStateLogArray, error) { + event := new(BitcoinStateLogArray) + if err := _BitcoinState.contract.UnpackLog(event, "log_array", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogArray0Iterator is returned from FilterLogArray0 and is used to iterate over the raw logs and unpacked data for LogArray0 events raised by the BitcoinState contract. +type BitcoinStateLogArray0Iterator struct { + Event *BitcoinStateLogArray0 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogArray0Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogArray0) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogArray0) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogArray0Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogArray0Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogArray0 represents a LogArray0 event raised by the BitcoinState contract. +type BitcoinStateLogArray0 struct { + Val []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogArray0 is a free log retrieval operation binding the contract event 0x890a82679b470f2bd82816ed9b161f97d8b967f37fa3647c21d5bf39749e2dd5. +// +// Solidity: event log_array(int256[] val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogArray0(opts *bind.FilterOpts) (*BitcoinStateLogArray0Iterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_array0") + if err != nil { + return nil, err + } + return &BitcoinStateLogArray0Iterator{contract: _BitcoinState.contract, event: "log_array0", logs: logs, sub: sub}, nil +} + +// WatchLogArray0 is a free log subscription operation binding the contract event 0x890a82679b470f2bd82816ed9b161f97d8b967f37fa3647c21d5bf39749e2dd5. +// +// Solidity: event log_array(int256[] val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogArray0(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogArray0) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_array0") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogArray0) + if err := _BitcoinState.contract.UnpackLog(event, "log_array0", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogArray0 is a log parse operation binding the contract event 0x890a82679b470f2bd82816ed9b161f97d8b967f37fa3647c21d5bf39749e2dd5. +// +// Solidity: event log_array(int256[] val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogArray0(log types.Log) (*BitcoinStateLogArray0, error) { + event := new(BitcoinStateLogArray0) + if err := _BitcoinState.contract.UnpackLog(event, "log_array0", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogArray1Iterator is returned from FilterLogArray1 and is used to iterate over the raw logs and unpacked data for LogArray1 events raised by the BitcoinState contract. +type BitcoinStateLogArray1Iterator struct { + Event *BitcoinStateLogArray1 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogArray1Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogArray1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogArray1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogArray1Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogArray1Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogArray1 represents a LogArray1 event raised by the BitcoinState contract. +type BitcoinStateLogArray1 struct { + Val []common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogArray1 is a free log retrieval operation binding the contract event 0x40e1840f5769073d61bd01372d9b75baa9842d5629a0c99ff103be1178a8e9e2. +// +// Solidity: event log_array(address[] val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogArray1(opts *bind.FilterOpts) (*BitcoinStateLogArray1Iterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_array1") + if err != nil { + return nil, err + } + return &BitcoinStateLogArray1Iterator{contract: _BitcoinState.contract, event: "log_array1", logs: logs, sub: sub}, nil +} + +// WatchLogArray1 is a free log subscription operation binding the contract event 0x40e1840f5769073d61bd01372d9b75baa9842d5629a0c99ff103be1178a8e9e2. +// +// Solidity: event log_array(address[] val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogArray1(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogArray1) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_array1") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogArray1) + if err := _BitcoinState.contract.UnpackLog(event, "log_array1", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogArray1 is a log parse operation binding the contract event 0x40e1840f5769073d61bd01372d9b75baa9842d5629a0c99ff103be1178a8e9e2. +// +// Solidity: event log_array(address[] val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogArray1(log types.Log) (*BitcoinStateLogArray1, error) { + event := new(BitcoinStateLogArray1) + if err := _BitcoinState.contract.UnpackLog(event, "log_array1", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogBytesIterator is returned from FilterLogBytes and is used to iterate over the raw logs and unpacked data for LogBytes events raised by the BitcoinState contract. +type BitcoinStateLogBytesIterator struct { + Event *BitcoinStateLogBytes // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogBytesIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogBytes) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogBytes) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogBytesIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogBytesIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogBytes represents a LogBytes event raised by the BitcoinState contract. +type BitcoinStateLogBytes struct { + Arg0 []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogBytes is a free log retrieval operation binding the contract event 0x23b62ad0584d24a75f0bf3560391ef5659ec6db1269c56e11aa241d637f19b20. +// +// Solidity: event log_bytes(bytes arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLogBytes(opts *bind.FilterOpts) (*BitcoinStateLogBytesIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_bytes") + if err != nil { + return nil, err + } + return &BitcoinStateLogBytesIterator{contract: _BitcoinState.contract, event: "log_bytes", logs: logs, sub: sub}, nil +} + +// WatchLogBytes is a free log subscription operation binding the contract event 0x23b62ad0584d24a75f0bf3560391ef5659ec6db1269c56e11aa241d637f19b20. +// +// Solidity: event log_bytes(bytes arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLogBytes(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogBytes) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_bytes") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogBytes) + if err := _BitcoinState.contract.UnpackLog(event, "log_bytes", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogBytes is a log parse operation binding the contract event 0x23b62ad0584d24a75f0bf3560391ef5659ec6db1269c56e11aa241d637f19b20. +// +// Solidity: event log_bytes(bytes arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLogBytes(log types.Log) (*BitcoinStateLogBytes, error) { + event := new(BitcoinStateLogBytes) + if err := _BitcoinState.contract.UnpackLog(event, "log_bytes", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogBytes32Iterator is returned from FilterLogBytes32 and is used to iterate over the raw logs and unpacked data for LogBytes32 events raised by the BitcoinState contract. +type BitcoinStateLogBytes32Iterator struct { + Event *BitcoinStateLogBytes32 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogBytes32Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogBytes32) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogBytes32) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogBytes32Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogBytes32Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogBytes32 represents a LogBytes32 event raised by the BitcoinState contract. +type BitcoinStateLogBytes32 struct { + Arg0 [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogBytes32 is a free log retrieval operation binding the contract event 0xe81699b85113eea1c73e10588b2b035e55893369632173afd43feb192fac64e3. +// +// Solidity: event log_bytes32(bytes32 arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLogBytes32(opts *bind.FilterOpts) (*BitcoinStateLogBytes32Iterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_bytes32") + if err != nil { + return nil, err + } + return &BitcoinStateLogBytes32Iterator{contract: _BitcoinState.contract, event: "log_bytes32", logs: logs, sub: sub}, nil +} + +// WatchLogBytes32 is a free log subscription operation binding the contract event 0xe81699b85113eea1c73e10588b2b035e55893369632173afd43feb192fac64e3. +// +// Solidity: event log_bytes32(bytes32 arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLogBytes32(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogBytes32) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_bytes32") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogBytes32) + if err := _BitcoinState.contract.UnpackLog(event, "log_bytes32", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogBytes32 is a log parse operation binding the contract event 0xe81699b85113eea1c73e10588b2b035e55893369632173afd43feb192fac64e3. +// +// Solidity: event log_bytes32(bytes32 arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLogBytes32(log types.Log) (*BitcoinStateLogBytes32, error) { + event := new(BitcoinStateLogBytes32) + if err := _BitcoinState.contract.UnpackLog(event, "log_bytes32", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogIntIterator is returned from FilterLogInt and is used to iterate over the raw logs and unpacked data for LogInt events raised by the BitcoinState contract. +type BitcoinStateLogIntIterator struct { + Event *BitcoinStateLogInt // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogIntIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogInt) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogInt) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogIntIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogIntIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogInt represents a LogInt event raised by the BitcoinState contract. +type BitcoinStateLogInt struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogInt is a free log retrieval operation binding the contract event 0x0eb5d52624c8d28ada9fc55a8c502ed5aa3fbe2fb6e91b71b5f376882b1d2fb8. +// +// Solidity: event log_int(int256 arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLogInt(opts *bind.FilterOpts) (*BitcoinStateLogIntIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_int") + if err != nil { + return nil, err + } + return &BitcoinStateLogIntIterator{contract: _BitcoinState.contract, event: "log_int", logs: logs, sub: sub}, nil +} + +// WatchLogInt is a free log subscription operation binding the contract event 0x0eb5d52624c8d28ada9fc55a8c502ed5aa3fbe2fb6e91b71b5f376882b1d2fb8. +// +// Solidity: event log_int(int256 arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLogInt(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogInt) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_int") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogInt) + if err := _BitcoinState.contract.UnpackLog(event, "log_int", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogInt is a log parse operation binding the contract event 0x0eb5d52624c8d28ada9fc55a8c502ed5aa3fbe2fb6e91b71b5f376882b1d2fb8. +// +// Solidity: event log_int(int256 arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLogInt(log types.Log) (*BitcoinStateLogInt, error) { + event := new(BitcoinStateLogInt) + if err := _BitcoinState.contract.UnpackLog(event, "log_int", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedAddressIterator is returned from FilterLogNamedAddress and is used to iterate over the raw logs and unpacked data for LogNamedAddress events raised by the BitcoinState contract. +type BitcoinStateLogNamedAddressIterator struct { + Event *BitcoinStateLogNamedAddress // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedAddressIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedAddress) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedAddress) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedAddressIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedAddressIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedAddress represents a LogNamedAddress event raised by the BitcoinState contract. +type BitcoinStateLogNamedAddress struct { + Key string + Val common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedAddress is a free log retrieval operation binding the contract event 0x9c4e8541ca8f0dc1c413f9108f66d82d3cecb1bddbce437a61caa3175c4cc96f. +// +// Solidity: event log_named_address(string key, address val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedAddress(opts *bind.FilterOpts) (*BitcoinStateLogNamedAddressIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_address") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedAddressIterator{contract: _BitcoinState.contract, event: "log_named_address", logs: logs, sub: sub}, nil +} + +// WatchLogNamedAddress is a free log subscription operation binding the contract event 0x9c4e8541ca8f0dc1c413f9108f66d82d3cecb1bddbce437a61caa3175c4cc96f. +// +// Solidity: event log_named_address(string key, address val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedAddress(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedAddress) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_address") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedAddress) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_address", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedAddress is a log parse operation binding the contract event 0x9c4e8541ca8f0dc1c413f9108f66d82d3cecb1bddbce437a61caa3175c4cc96f. +// +// Solidity: event log_named_address(string key, address val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedAddress(log types.Log) (*BitcoinStateLogNamedAddress, error) { + event := new(BitcoinStateLogNamedAddress) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_address", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedArrayIterator is returned from FilterLogNamedArray and is used to iterate over the raw logs and unpacked data for LogNamedArray events raised by the BitcoinState contract. +type BitcoinStateLogNamedArrayIterator struct { + Event *BitcoinStateLogNamedArray // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedArrayIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedArray) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedArray) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedArrayIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedArrayIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedArray represents a LogNamedArray event raised by the BitcoinState contract. +type BitcoinStateLogNamedArray struct { + Key string + Val []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedArray is a free log retrieval operation binding the contract event 0x00aaa39c9ffb5f567a4534380c737075702e1f7f14107fc95328e3b56c0325fb. +// +// Solidity: event log_named_array(string key, uint256[] val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedArray(opts *bind.FilterOpts) (*BitcoinStateLogNamedArrayIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_array") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedArrayIterator{contract: _BitcoinState.contract, event: "log_named_array", logs: logs, sub: sub}, nil +} + +// WatchLogNamedArray is a free log subscription operation binding the contract event 0x00aaa39c9ffb5f567a4534380c737075702e1f7f14107fc95328e3b56c0325fb. +// +// Solidity: event log_named_array(string key, uint256[] val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedArray(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedArray) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_array") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedArray) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_array", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedArray is a log parse operation binding the contract event 0x00aaa39c9ffb5f567a4534380c737075702e1f7f14107fc95328e3b56c0325fb. +// +// Solidity: event log_named_array(string key, uint256[] val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedArray(log types.Log) (*BitcoinStateLogNamedArray, error) { + event := new(BitcoinStateLogNamedArray) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_array", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedArray0Iterator is returned from FilterLogNamedArray0 and is used to iterate over the raw logs and unpacked data for LogNamedArray0 events raised by the BitcoinState contract. +type BitcoinStateLogNamedArray0Iterator struct { + Event *BitcoinStateLogNamedArray0 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedArray0Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedArray0) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedArray0) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedArray0Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedArray0Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedArray0 represents a LogNamedArray0 event raised by the BitcoinState contract. +type BitcoinStateLogNamedArray0 struct { + Key string + Val []*big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedArray0 is a free log retrieval operation binding the contract event 0xa73eda09662f46dde729be4611385ff34fe6c44fbbc6f7e17b042b59a3445b57. +// +// Solidity: event log_named_array(string key, int256[] val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedArray0(opts *bind.FilterOpts) (*BitcoinStateLogNamedArray0Iterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_array0") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedArray0Iterator{contract: _BitcoinState.contract, event: "log_named_array0", logs: logs, sub: sub}, nil +} + +// WatchLogNamedArray0 is a free log subscription operation binding the contract event 0xa73eda09662f46dde729be4611385ff34fe6c44fbbc6f7e17b042b59a3445b57. +// +// Solidity: event log_named_array(string key, int256[] val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedArray0(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedArray0) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_array0") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedArray0) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_array0", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedArray0 is a log parse operation binding the contract event 0xa73eda09662f46dde729be4611385ff34fe6c44fbbc6f7e17b042b59a3445b57. +// +// Solidity: event log_named_array(string key, int256[] val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedArray0(log types.Log) (*BitcoinStateLogNamedArray0, error) { + event := new(BitcoinStateLogNamedArray0) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_array0", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedArray1Iterator is returned from FilterLogNamedArray1 and is used to iterate over the raw logs and unpacked data for LogNamedArray1 events raised by the BitcoinState contract. +type BitcoinStateLogNamedArray1Iterator struct { + Event *BitcoinStateLogNamedArray1 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedArray1Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedArray1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedArray1) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedArray1Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedArray1Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedArray1 represents a LogNamedArray1 event raised by the BitcoinState contract. +type BitcoinStateLogNamedArray1 struct { + Key string + Val []common.Address + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedArray1 is a free log retrieval operation binding the contract event 0x3bcfb2ae2e8d132dd1fce7cf278a9a19756a9fceabe470df3bdabb4bc577d1bd. +// +// Solidity: event log_named_array(string key, address[] val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedArray1(opts *bind.FilterOpts) (*BitcoinStateLogNamedArray1Iterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_array1") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedArray1Iterator{contract: _BitcoinState.contract, event: "log_named_array1", logs: logs, sub: sub}, nil +} + +// WatchLogNamedArray1 is a free log subscription operation binding the contract event 0x3bcfb2ae2e8d132dd1fce7cf278a9a19756a9fceabe470df3bdabb4bc577d1bd. +// +// Solidity: event log_named_array(string key, address[] val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedArray1(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedArray1) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_array1") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedArray1) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_array1", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedArray1 is a log parse operation binding the contract event 0x3bcfb2ae2e8d132dd1fce7cf278a9a19756a9fceabe470df3bdabb4bc577d1bd. +// +// Solidity: event log_named_array(string key, address[] val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedArray1(log types.Log) (*BitcoinStateLogNamedArray1, error) { + event := new(BitcoinStateLogNamedArray1) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_array1", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedBytesIterator is returned from FilterLogNamedBytes and is used to iterate over the raw logs and unpacked data for LogNamedBytes events raised by the BitcoinState contract. +type BitcoinStateLogNamedBytesIterator struct { + Event *BitcoinStateLogNamedBytes // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedBytesIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedBytes) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedBytes) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedBytesIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedBytesIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedBytes represents a LogNamedBytes event raised by the BitcoinState contract. +type BitcoinStateLogNamedBytes struct { + Key string + Val []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedBytes is a free log retrieval operation binding the contract event 0xd26e16cad4548705e4c9e2d94f98ee91c289085ee425594fd5635fa2964ccf18. +// +// Solidity: event log_named_bytes(string key, bytes val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedBytes(opts *bind.FilterOpts) (*BitcoinStateLogNamedBytesIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_bytes") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedBytesIterator{contract: _BitcoinState.contract, event: "log_named_bytes", logs: logs, sub: sub}, nil +} + +// WatchLogNamedBytes is a free log subscription operation binding the contract event 0xd26e16cad4548705e4c9e2d94f98ee91c289085ee425594fd5635fa2964ccf18. +// +// Solidity: event log_named_bytes(string key, bytes val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedBytes(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedBytes) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_bytes") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedBytes) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedBytes is a log parse operation binding the contract event 0xd26e16cad4548705e4c9e2d94f98ee91c289085ee425594fd5635fa2964ccf18. +// +// Solidity: event log_named_bytes(string key, bytes val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedBytes(log types.Log) (*BitcoinStateLogNamedBytes, error) { + event := new(BitcoinStateLogNamedBytes) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedBytes32Iterator is returned from FilterLogNamedBytes32 and is used to iterate over the raw logs and unpacked data for LogNamedBytes32 events raised by the BitcoinState contract. +type BitcoinStateLogNamedBytes32Iterator struct { + Event *BitcoinStateLogNamedBytes32 // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedBytes32Iterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedBytes32) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedBytes32) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedBytes32Iterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedBytes32Iterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedBytes32 represents a LogNamedBytes32 event raised by the BitcoinState contract. +type BitcoinStateLogNamedBytes32 struct { + Key string + Val [32]byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedBytes32 is a free log retrieval operation binding the contract event 0xafb795c9c61e4fe7468c386f925d7a5429ecad9c0495ddb8d38d690614d32f99. +// +// Solidity: event log_named_bytes32(string key, bytes32 val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedBytes32(opts *bind.FilterOpts) (*BitcoinStateLogNamedBytes32Iterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_bytes32") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedBytes32Iterator{contract: _BitcoinState.contract, event: "log_named_bytes32", logs: logs, sub: sub}, nil +} + +// WatchLogNamedBytes32 is a free log subscription operation binding the contract event 0xafb795c9c61e4fe7468c386f925d7a5429ecad9c0495ddb8d38d690614d32f99. +// +// Solidity: event log_named_bytes32(string key, bytes32 val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedBytes32(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedBytes32) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_bytes32") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedBytes32) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes32", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedBytes32 is a log parse operation binding the contract event 0xafb795c9c61e4fe7468c386f925d7a5429ecad9c0495ddb8d38d690614d32f99. +// +// Solidity: event log_named_bytes32(string key, bytes32 val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedBytes32(log types.Log) (*BitcoinStateLogNamedBytes32, error) { + event := new(BitcoinStateLogNamedBytes32) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes32", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedDecimalIntIterator is returned from FilterLogNamedDecimalInt and is used to iterate over the raw logs and unpacked data for LogNamedDecimalInt events raised by the BitcoinState contract. +type BitcoinStateLogNamedDecimalIntIterator struct { + Event *BitcoinStateLogNamedDecimalInt // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedDecimalIntIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedDecimalInt) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedDecimalInt) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedDecimalIntIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedDecimalIntIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedDecimalInt represents a LogNamedDecimalInt event raised by the BitcoinState contract. +type BitcoinStateLogNamedDecimalInt struct { + Key string + Val *big.Int + Decimals *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedDecimalInt is a free log retrieval operation binding the contract event 0x5da6ce9d51151ba10c09a559ef24d520b9dac5c5b8810ae8434e4d0d86411a95. +// +// Solidity: event log_named_decimal_int(string key, int256 val, uint256 decimals) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedDecimalInt(opts *bind.FilterOpts) (*BitcoinStateLogNamedDecimalIntIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_decimal_int") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedDecimalIntIterator{contract: _BitcoinState.contract, event: "log_named_decimal_int", logs: logs, sub: sub}, nil +} + +// WatchLogNamedDecimalInt is a free log subscription operation binding the contract event 0x5da6ce9d51151ba10c09a559ef24d520b9dac5c5b8810ae8434e4d0d86411a95. +// +// Solidity: event log_named_decimal_int(string key, int256 val, uint256 decimals) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedDecimalInt(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedDecimalInt) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_decimal_int") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedDecimalInt) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_int", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedDecimalInt is a log parse operation binding the contract event 0x5da6ce9d51151ba10c09a559ef24d520b9dac5c5b8810ae8434e4d0d86411a95. +// +// Solidity: event log_named_decimal_int(string key, int256 val, uint256 decimals) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedDecimalInt(log types.Log) (*BitcoinStateLogNamedDecimalInt, error) { + event := new(BitcoinStateLogNamedDecimalInt) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_int", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedDecimalUintIterator is returned from FilterLogNamedDecimalUint and is used to iterate over the raw logs and unpacked data for LogNamedDecimalUint events raised by the BitcoinState contract. +type BitcoinStateLogNamedDecimalUintIterator struct { + Event *BitcoinStateLogNamedDecimalUint // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedDecimalUintIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedDecimalUint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedDecimalUint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedDecimalUintIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedDecimalUintIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedDecimalUint represents a LogNamedDecimalUint event raised by the BitcoinState contract. +type BitcoinStateLogNamedDecimalUint struct { + Key string + Val *big.Int + Decimals *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedDecimalUint is a free log retrieval operation binding the contract event 0xeb8ba43ced7537421946bd43e828b8b2b8428927aa8f801c13d934bf11aca57b. +// +// Solidity: event log_named_decimal_uint(string key, uint256 val, uint256 decimals) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedDecimalUint(opts *bind.FilterOpts) (*BitcoinStateLogNamedDecimalUintIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_decimal_uint") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedDecimalUintIterator{contract: _BitcoinState.contract, event: "log_named_decimal_uint", logs: logs, sub: sub}, nil +} + +// WatchLogNamedDecimalUint is a free log subscription operation binding the contract event 0xeb8ba43ced7537421946bd43e828b8b2b8428927aa8f801c13d934bf11aca57b. +// +// Solidity: event log_named_decimal_uint(string key, uint256 val, uint256 decimals) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedDecimalUint(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedDecimalUint) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_decimal_uint") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedDecimalUint) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_uint", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedDecimalUint is a log parse operation binding the contract event 0xeb8ba43ced7537421946bd43e828b8b2b8428927aa8f801c13d934bf11aca57b. +// +// Solidity: event log_named_decimal_uint(string key, uint256 val, uint256 decimals) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedDecimalUint(log types.Log) (*BitcoinStateLogNamedDecimalUint, error) { + event := new(BitcoinStateLogNamedDecimalUint) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_uint", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedIntIterator is returned from FilterLogNamedInt and is used to iterate over the raw logs and unpacked data for LogNamedInt events raised by the BitcoinState contract. +type BitcoinStateLogNamedIntIterator struct { + Event *BitcoinStateLogNamedInt // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedIntIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedInt) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedInt) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedIntIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedIntIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedInt represents a LogNamedInt event raised by the BitcoinState contract. +type BitcoinStateLogNamedInt struct { + Key string + Val *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedInt is a free log retrieval operation binding the contract event 0x2fe632779174374378442a8e978bccfbdcc1d6b2b0d81f7e8eb776ab2286f168. +// +// Solidity: event log_named_int(string key, int256 val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedInt(opts *bind.FilterOpts) (*BitcoinStateLogNamedIntIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_int") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedIntIterator{contract: _BitcoinState.contract, event: "log_named_int", logs: logs, sub: sub}, nil +} + +// WatchLogNamedInt is a free log subscription operation binding the contract event 0x2fe632779174374378442a8e978bccfbdcc1d6b2b0d81f7e8eb776ab2286f168. +// +// Solidity: event log_named_int(string key, int256 val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedInt(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedInt) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_int") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedInt) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_int", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedInt is a log parse operation binding the contract event 0x2fe632779174374378442a8e978bccfbdcc1d6b2b0d81f7e8eb776ab2286f168. +// +// Solidity: event log_named_int(string key, int256 val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedInt(log types.Log) (*BitcoinStateLogNamedInt, error) { + event := new(BitcoinStateLogNamedInt) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_int", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedStringIterator is returned from FilterLogNamedString and is used to iterate over the raw logs and unpacked data for LogNamedString events raised by the BitcoinState contract. +type BitcoinStateLogNamedStringIterator struct { + Event *BitcoinStateLogNamedString // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedStringIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedString) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedString) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedStringIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedStringIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedString represents a LogNamedString event raised by the BitcoinState contract. +type BitcoinStateLogNamedString struct { + Key string + Val string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedString is a free log retrieval operation binding the contract event 0x280f4446b28a1372417dda658d30b95b2992b12ac9c7f378535f29a97acf3583. +// +// Solidity: event log_named_string(string key, string val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedString(opts *bind.FilterOpts) (*BitcoinStateLogNamedStringIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_string") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedStringIterator{contract: _BitcoinState.contract, event: "log_named_string", logs: logs, sub: sub}, nil +} + +// WatchLogNamedString is a free log subscription operation binding the contract event 0x280f4446b28a1372417dda658d30b95b2992b12ac9c7f378535f29a97acf3583. +// +// Solidity: event log_named_string(string key, string val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedString(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedString) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_string") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedString) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_string", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedString is a log parse operation binding the contract event 0x280f4446b28a1372417dda658d30b95b2992b12ac9c7f378535f29a97acf3583. +// +// Solidity: event log_named_string(string key, string val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedString(log types.Log) (*BitcoinStateLogNamedString, error) { + event := new(BitcoinStateLogNamedString) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_string", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogNamedUintIterator is returned from FilterLogNamedUint and is used to iterate over the raw logs and unpacked data for LogNamedUint events raised by the BitcoinState contract. +type BitcoinStateLogNamedUintIterator struct { + Event *BitcoinStateLogNamedUint // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogNamedUintIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedUint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogNamedUint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogNamedUintIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogNamedUintIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogNamedUint represents a LogNamedUint event raised by the BitcoinState contract. +type BitcoinStateLogNamedUint struct { + Key string + Val *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogNamedUint is a free log retrieval operation binding the contract event 0xb2de2fbe801a0df6c0cbddfd448ba3c41d48a040ca35c56c8196ef0fcae721a8. +// +// Solidity: event log_named_uint(string key, uint256 val) +func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedUint(opts *bind.FilterOpts) (*BitcoinStateLogNamedUintIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_uint") + if err != nil { + return nil, err + } + return &BitcoinStateLogNamedUintIterator{contract: _BitcoinState.contract, event: "log_named_uint", logs: logs, sub: sub}, nil +} + +// WatchLogNamedUint is a free log subscription operation binding the contract event 0xb2de2fbe801a0df6c0cbddfd448ba3c41d48a040ca35c56c8196ef0fcae721a8. +// +// Solidity: event log_named_uint(string key, uint256 val) +func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedUint(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedUint) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_uint") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogNamedUint) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_uint", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogNamedUint is a log parse operation binding the contract event 0xb2de2fbe801a0df6c0cbddfd448ba3c41d48a040ca35c56c8196ef0fcae721a8. +// +// Solidity: event log_named_uint(string key, uint256 val) +func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedUint(log types.Log) (*BitcoinStateLogNamedUint, error) { + event := new(BitcoinStateLogNamedUint) + if err := _BitcoinState.contract.UnpackLog(event, "log_named_uint", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogStringIterator is returned from FilterLogString and is used to iterate over the raw logs and unpacked data for LogString events raised by the BitcoinState contract. +type BitcoinStateLogStringIterator struct { + Event *BitcoinStateLogString // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogStringIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogString) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogString) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogStringIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogStringIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogString represents a LogString event raised by the BitcoinState contract. +type BitcoinStateLogString struct { + Arg0 string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogString is a free log retrieval operation binding the contract event 0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b. +// +// Solidity: event log_string(string arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLogString(opts *bind.FilterOpts) (*BitcoinStateLogStringIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_string") + if err != nil { + return nil, err + } + return &BitcoinStateLogStringIterator{contract: _BitcoinState.contract, event: "log_string", logs: logs, sub: sub}, nil +} + +// WatchLogString is a free log subscription operation binding the contract event 0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b. +// +// Solidity: event log_string(string arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLogString(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogString) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_string") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogString) + if err := _BitcoinState.contract.UnpackLog(event, "log_string", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogString is a log parse operation binding the contract event 0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b. +// +// Solidity: event log_string(string arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLogString(log types.Log) (*BitcoinStateLogString, error) { + event := new(BitcoinStateLogString) + if err := _BitcoinState.contract.UnpackLog(event, "log_string", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogUintIterator is returned from FilterLogUint and is used to iterate over the raw logs and unpacked data for LogUint events raised by the BitcoinState contract. +type BitcoinStateLogUintIterator struct { + Event *BitcoinStateLogUint // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogUintIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogUint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogUint) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogUintIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogUintIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogUint represents a LogUint event raised by the BitcoinState contract. +type BitcoinStateLogUint struct { + Arg0 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogUint is a free log retrieval operation binding the contract event 0x2cab9790510fd8bdfbd2115288db33fec66691d476efc5427cfd4c0969301755. +// +// Solidity: event log_uint(uint256 arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLogUint(opts *bind.FilterOpts) (*BitcoinStateLogUintIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_uint") + if err != nil { + return nil, err + } + return &BitcoinStateLogUintIterator{contract: _BitcoinState.contract, event: "log_uint", logs: logs, sub: sub}, nil +} + +// WatchLogUint is a free log subscription operation binding the contract event 0x2cab9790510fd8bdfbd2115288db33fec66691d476efc5427cfd4c0969301755. +// +// Solidity: event log_uint(uint256 arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLogUint(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogUint) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_uint") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogUint) + if err := _BitcoinState.contract.UnpackLog(event, "log_uint", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogUint is a log parse operation binding the contract event 0x2cab9790510fd8bdfbd2115288db33fec66691d476efc5427cfd4c0969301755. +// +// Solidity: event log_uint(uint256 arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLogUint(log types.Log) (*BitcoinStateLogUint, error) { + event := new(BitcoinStateLogUint) + if err := _BitcoinState.contract.UnpackLog(event, "log_uint", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// BitcoinStateLogsIterator is returned from FilterLogs and is used to iterate over the raw logs and unpacked data for Logs events raised by the BitcoinState contract. +type BitcoinStateLogsIterator struct { + Event *BitcoinStateLogs // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *BitcoinStateLogsIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogs) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(BitcoinStateLogs) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *BitcoinStateLogsIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *BitcoinStateLogsIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// BitcoinStateLogs represents a Logs event raised by the BitcoinState contract. +type BitcoinStateLogs struct { + Arg0 []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterLogs is a free log retrieval operation binding the contract event 0xe7950ede0394b9f2ce4a5a1bf5a7e1852411f7e6661b4308c913c4bfd11027e4. +// +// Solidity: event logs(bytes arg0) +func (_BitcoinState *BitcoinStateFilterer) FilterLogs(opts *bind.FilterOpts) (*BitcoinStateLogsIterator, error) { + + logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "logs") + if err != nil { + return nil, err + } + return &BitcoinStateLogsIterator{contract: _BitcoinState.contract, event: "logs", logs: logs, sub: sub}, nil +} + +// WatchLogs is a free log subscription operation binding the contract event 0xe7950ede0394b9f2ce4a5a1bf5a7e1852411f7e6661b4308c913c4bfd11027e4. +// +// Solidity: event logs(bytes arg0) +func (_BitcoinState *BitcoinStateFilterer) WatchLogs(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogs) (event.Subscription, error) { + + logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "logs") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(BitcoinStateLogs) + if err := _BitcoinState.contract.UnpackLog(event, "logs", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseLogs is a log parse operation binding the contract event 0xe7950ede0394b9f2ce4a5a1bf5a7e1852411f7e6661b4308c913c4bfd11027e4. +// +// Solidity: event logs(bytes arg0) +func (_BitcoinState *BitcoinStateFilterer) ParseLogs(log types.Log) (*BitcoinStateLogs, error) { + event := new(BitcoinStateLogs) + if err := _BitcoinState.contract.UnpackLog(event, "logs", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/relayer/chains/bitcoin/abi/icall_service.go b/relayer/chains/bitcoin/abi/icall_service.go new file mode 100644 index 00000000..13735784 --- /dev/null +++ b/relayer/chains/bitcoin/abi/icall_service.go @@ -0,0 +1,1814 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package abi + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// CallServiceMetaData contains all meta data concerning the CallService contract. +var CallServiceMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"admin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"executeCall\",\"inputs\":[{\"name\":\"_reqId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executeMessage\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"protocols\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executeRollback\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getDefaultConnection\",\"inputs\":[{\"name\":\"_nid\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"_net\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_rollback\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"_sources\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"_net\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_rollback\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNetworkAddress\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNetworkId\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getProtocolFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getProtocolFeeHandler\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"handleBTPError\",\"inputs\":[{\"name\":\"_src\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_svc\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_code\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleBTPMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_svc\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleError\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_nid\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendCall\",\"inputs\":[{\"name\":\"_to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"sendCallMessage\",\"inputs\":[{\"name\":\"_to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_rollback\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"sendCallMessage\",\"inputs\":[{\"name\":\"_to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_rollback\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sources\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"destinations\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"setAdmin\",\"inputs\":[{\"name\":\"_address\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setDefaultConnection\",\"inputs\":[{\"name\":\"_nid\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"connection\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setProtocolFee\",\"inputs\":[{\"name\":\"_value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setProtocolFeeHandler\",\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verifySuccess\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"CallExecuted\",\"inputs\":[{\"name\":\"_reqId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"_code\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"},{\"name\":\"_msg\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CallMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"_to\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"_reqId\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CallMessageSent\",\"inputs\":[{\"name\":\"_from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"_to\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ResponseMessage\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"_code\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RollbackExecuted\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RollbackMessage\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]}]", +} + +// CallServiceABI is the input ABI used to generate the binding from. +// Deprecated: Use CallServiceMetaData.ABI instead. +var CallServiceABI = CallServiceMetaData.ABI + +// CallService is an auto generated Go binding around an Ethereum contract. +type CallService struct { + CallServiceCaller // Read-only binding to the contract + CallServiceTransactor // Write-only binding to the contract + CallServiceFilterer // Log filterer for contract events +} + +// CallServiceCaller is an auto generated read-only Go binding around an Ethereum contract. +type CallServiceCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CallServiceTransactor is an auto generated write-only Go binding around an Ethereum contract. +type CallServiceTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CallServiceFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type CallServiceFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CallServiceSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type CallServiceSession struct { + Contract *CallService // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CallServiceCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type CallServiceCallerSession struct { + Contract *CallServiceCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// CallServiceTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type CallServiceTransactorSession struct { + Contract *CallServiceTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CallServiceRaw is an auto generated low-level Go binding around an Ethereum contract. +type CallServiceRaw struct { + Contract *CallService // Generic contract binding to access the raw methods on +} + +// CallServiceCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type CallServiceCallerRaw struct { + Contract *CallServiceCaller // Generic read-only contract binding to access the raw methods on +} + +// CallServiceTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type CallServiceTransactorRaw struct { + Contract *CallServiceTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewCallService creates a new instance of CallService, bound to a specific deployed contract. +func NewCallService(address common.Address, backend bind.ContractBackend) (*CallService, error) { + contract, err := bindCallService(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CallService{CallServiceCaller: CallServiceCaller{contract: contract}, CallServiceTransactor: CallServiceTransactor{contract: contract}, CallServiceFilterer: CallServiceFilterer{contract: contract}}, nil +} + +// NewCallServiceCaller creates a new read-only instance of CallService, bound to a specific deployed contract. +func NewCallServiceCaller(address common.Address, caller bind.ContractCaller) (*CallServiceCaller, error) { + contract, err := bindCallService(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CallServiceCaller{contract: contract}, nil +} + +// NewCallServiceTransactor creates a new write-only instance of CallService, bound to a specific deployed contract. +func NewCallServiceTransactor(address common.Address, transactor bind.ContractTransactor) (*CallServiceTransactor, error) { + contract, err := bindCallService(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CallServiceTransactor{contract: contract}, nil +} + +// NewCallServiceFilterer creates a new log filterer instance of CallService, bound to a specific deployed contract. +func NewCallServiceFilterer(address common.Address, filterer bind.ContractFilterer) (*CallServiceFilterer, error) { + contract, err := bindCallService(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CallServiceFilterer{contract: contract}, nil +} + +// bindCallService binds a generic wrapper to an already deployed contract. +func bindCallService(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CallServiceMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CallService *CallServiceRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CallService.Contract.CallServiceCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CallService *CallServiceRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CallService.Contract.CallServiceTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CallService *CallServiceRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CallService.Contract.CallServiceTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CallService *CallServiceCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CallService.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CallService *CallServiceTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CallService.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CallService *CallServiceTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CallService.Contract.contract.Transact(opts, method, params...) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_CallService *CallServiceCaller) Admin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "admin") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_CallService *CallServiceSession) Admin() (common.Address, error) { + return _CallService.Contract.Admin(&_CallService.CallOpts) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_CallService *CallServiceCallerSession) Admin() (common.Address, error) { + return _CallService.Contract.Admin(&_CallService.CallOpts) +} + +// GetDefaultConnection is a free data retrieval call binding the contract method 0x9e553a4f. +// +// Solidity: function getDefaultConnection(string _nid) view returns(address) +func (_CallService *CallServiceCaller) GetDefaultConnection(opts *bind.CallOpts, _nid string) (common.Address, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "getDefaultConnection", _nid) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetDefaultConnection is a free data retrieval call binding the contract method 0x9e553a4f. +// +// Solidity: function getDefaultConnection(string _nid) view returns(address) +func (_CallService *CallServiceSession) GetDefaultConnection(_nid string) (common.Address, error) { + return _CallService.Contract.GetDefaultConnection(&_CallService.CallOpts, _nid) +} + +// GetDefaultConnection is a free data retrieval call binding the contract method 0x9e553a4f. +// +// Solidity: function getDefaultConnection(string _nid) view returns(address) +func (_CallService *CallServiceCallerSession) GetDefaultConnection(_nid string) (common.Address, error) { + return _CallService.Contract.GetDefaultConnection(&_CallService.CallOpts, _nid) +} + +// GetFee is a free data retrieval call binding the contract method 0x304a70b5. +// +// Solidity: function getFee(string _net, bool _rollback, string[] _sources) view returns(uint256) +func (_CallService *CallServiceCaller) GetFee(opts *bind.CallOpts, _net string, _rollback bool, _sources []string) (*big.Int, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "getFee", _net, _rollback, _sources) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetFee is a free data retrieval call binding the contract method 0x304a70b5. +// +// Solidity: function getFee(string _net, bool _rollback, string[] _sources) view returns(uint256) +func (_CallService *CallServiceSession) GetFee(_net string, _rollback bool, _sources []string) (*big.Int, error) { + return _CallService.Contract.GetFee(&_CallService.CallOpts, _net, _rollback, _sources) +} + +// GetFee is a free data retrieval call binding the contract method 0x304a70b5. +// +// Solidity: function getFee(string _net, bool _rollback, string[] _sources) view returns(uint256) +func (_CallService *CallServiceCallerSession) GetFee(_net string, _rollback bool, _sources []string) (*big.Int, error) { + return _CallService.Contract.GetFee(&_CallService.CallOpts, _net, _rollback, _sources) +} + +// GetFee0 is a free data retrieval call binding the contract method 0x7d4c4f4a. +// +// Solidity: function getFee(string _net, bool _rollback) view returns(uint256) +func (_CallService *CallServiceCaller) GetFee0(opts *bind.CallOpts, _net string, _rollback bool) (*big.Int, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "getFee0", _net, _rollback) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetFee0 is a free data retrieval call binding the contract method 0x7d4c4f4a. +// +// Solidity: function getFee(string _net, bool _rollback) view returns(uint256) +func (_CallService *CallServiceSession) GetFee0(_net string, _rollback bool) (*big.Int, error) { + return _CallService.Contract.GetFee0(&_CallService.CallOpts, _net, _rollback) +} + +// GetFee0 is a free data retrieval call binding the contract method 0x7d4c4f4a. +// +// Solidity: function getFee(string _net, bool _rollback) view returns(uint256) +func (_CallService *CallServiceCallerSession) GetFee0(_net string, _rollback bool) (*big.Int, error) { + return _CallService.Contract.GetFee0(&_CallService.CallOpts, _net, _rollback) +} + +// GetNetworkAddress is a free data retrieval call binding the contract method 0x6bf459cb. +// +// Solidity: function getNetworkAddress() view returns(string) +func (_CallService *CallServiceCaller) GetNetworkAddress(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "getNetworkAddress") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// GetNetworkAddress is a free data retrieval call binding the contract method 0x6bf459cb. +// +// Solidity: function getNetworkAddress() view returns(string) +func (_CallService *CallServiceSession) GetNetworkAddress() (string, error) { + return _CallService.Contract.GetNetworkAddress(&_CallService.CallOpts) +} + +// GetNetworkAddress is a free data retrieval call binding the contract method 0x6bf459cb. +// +// Solidity: function getNetworkAddress() view returns(string) +func (_CallService *CallServiceCallerSession) GetNetworkAddress() (string, error) { + return _CallService.Contract.GetNetworkAddress(&_CallService.CallOpts) +} + +// GetNetworkId is a free data retrieval call binding the contract method 0x39c5f3fc. +// +// Solidity: function getNetworkId() view returns(string) +func (_CallService *CallServiceCaller) GetNetworkId(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "getNetworkId") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// GetNetworkId is a free data retrieval call binding the contract method 0x39c5f3fc. +// +// Solidity: function getNetworkId() view returns(string) +func (_CallService *CallServiceSession) GetNetworkId() (string, error) { + return _CallService.Contract.GetNetworkId(&_CallService.CallOpts) +} + +// GetNetworkId is a free data retrieval call binding the contract method 0x39c5f3fc. +// +// Solidity: function getNetworkId() view returns(string) +func (_CallService *CallServiceCallerSession) GetNetworkId() (string, error) { + return _CallService.Contract.GetNetworkId(&_CallService.CallOpts) +} + +// GetProtocolFee is a free data retrieval call binding the contract method 0xa5a41031. +// +// Solidity: function getProtocolFee() view returns(uint256) +func (_CallService *CallServiceCaller) GetProtocolFee(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "getProtocolFee") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetProtocolFee is a free data retrieval call binding the contract method 0xa5a41031. +// +// Solidity: function getProtocolFee() view returns(uint256) +func (_CallService *CallServiceSession) GetProtocolFee() (*big.Int, error) { + return _CallService.Contract.GetProtocolFee(&_CallService.CallOpts) +} + +// GetProtocolFee is a free data retrieval call binding the contract method 0xa5a41031. +// +// Solidity: function getProtocolFee() view returns(uint256) +func (_CallService *CallServiceCallerSession) GetProtocolFee() (*big.Int, error) { + return _CallService.Contract.GetProtocolFee(&_CallService.CallOpts) +} + +// GetProtocolFeeHandler is a free data retrieval call binding the contract method 0x2eb71414. +// +// Solidity: function getProtocolFeeHandler() view returns(address) +func (_CallService *CallServiceCaller) GetProtocolFeeHandler(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "getProtocolFeeHandler") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetProtocolFeeHandler is a free data retrieval call binding the contract method 0x2eb71414. +// +// Solidity: function getProtocolFeeHandler() view returns(address) +func (_CallService *CallServiceSession) GetProtocolFeeHandler() (common.Address, error) { + return _CallService.Contract.GetProtocolFeeHandler(&_CallService.CallOpts) +} + +// GetProtocolFeeHandler is a free data retrieval call binding the contract method 0x2eb71414. +// +// Solidity: function getProtocolFeeHandler() view returns(address) +func (_CallService *CallServiceCallerSession) GetProtocolFeeHandler() (common.Address, error) { + return _CallService.Contract.GetProtocolFeeHandler(&_CallService.CallOpts) +} + +// VerifySuccess is a free data retrieval call binding the contract method 0xec05386b. +// +// Solidity: function verifySuccess(uint256 _sn) view returns(bool) +func (_CallService *CallServiceCaller) VerifySuccess(opts *bind.CallOpts, _sn *big.Int) (bool, error) { + var out []interface{} + err := _CallService.contract.Call(opts, &out, "verifySuccess", _sn) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// VerifySuccess is a free data retrieval call binding the contract method 0xec05386b. +// +// Solidity: function verifySuccess(uint256 _sn) view returns(bool) +func (_CallService *CallServiceSession) VerifySuccess(_sn *big.Int) (bool, error) { + return _CallService.Contract.VerifySuccess(&_CallService.CallOpts, _sn) +} + +// VerifySuccess is a free data retrieval call binding the contract method 0xec05386b. +// +// Solidity: function verifySuccess(uint256 _sn) view returns(bool) +func (_CallService *CallServiceCallerSession) VerifySuccess(_sn *big.Int) (bool, error) { + return _CallService.Contract.VerifySuccess(&_CallService.CallOpts, _sn) +} + +// ExecuteCall is a paid mutator transaction binding the contract method 0xbda8ce21. +// +// Solidity: function executeCall(uint256 _reqId, bytes _data) returns() +func (_CallService *CallServiceTransactor) ExecuteCall(opts *bind.TransactOpts, _reqId *big.Int, _data []byte) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "executeCall", _reqId, _data) +} + +// ExecuteCall is a paid mutator transaction binding the contract method 0xbda8ce21. +// +// Solidity: function executeCall(uint256 _reqId, bytes _data) returns() +func (_CallService *CallServiceSession) ExecuteCall(_reqId *big.Int, _data []byte) (*types.Transaction, error) { + return _CallService.Contract.ExecuteCall(&_CallService.TransactOpts, _reqId, _data) +} + +// ExecuteCall is a paid mutator transaction binding the contract method 0xbda8ce21. +// +// Solidity: function executeCall(uint256 _reqId, bytes _data) returns() +func (_CallService *CallServiceTransactorSession) ExecuteCall(_reqId *big.Int, _data []byte) (*types.Transaction, error) { + return _CallService.Contract.ExecuteCall(&_CallService.TransactOpts, _reqId, _data) +} + +// ExecuteMessage is a paid mutator transaction binding the contract method 0x313bf398. +// +// Solidity: function executeMessage(address to, string from, bytes data, string[] protocols) returns() +func (_CallService *CallServiceTransactor) ExecuteMessage(opts *bind.TransactOpts, to common.Address, from string, data []byte, protocols []string) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "executeMessage", to, from, data, protocols) +} + +// ExecuteMessage is a paid mutator transaction binding the contract method 0x313bf398. +// +// Solidity: function executeMessage(address to, string from, bytes data, string[] protocols) returns() +func (_CallService *CallServiceSession) ExecuteMessage(to common.Address, from string, data []byte, protocols []string) (*types.Transaction, error) { + return _CallService.Contract.ExecuteMessage(&_CallService.TransactOpts, to, from, data, protocols) +} + +// ExecuteMessage is a paid mutator transaction binding the contract method 0x313bf398. +// +// Solidity: function executeMessage(address to, string from, bytes data, string[] protocols) returns() +func (_CallService *CallServiceTransactorSession) ExecuteMessage(to common.Address, from string, data []byte, protocols []string) (*types.Transaction, error) { + return _CallService.Contract.ExecuteMessage(&_CallService.TransactOpts, to, from, data, protocols) +} + +// ExecuteRollback is a paid mutator transaction binding the contract method 0x2a84e1b0. +// +// Solidity: function executeRollback(uint256 _sn) returns() +func (_CallService *CallServiceTransactor) ExecuteRollback(opts *bind.TransactOpts, _sn *big.Int) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "executeRollback", _sn) +} + +// ExecuteRollback is a paid mutator transaction binding the contract method 0x2a84e1b0. +// +// Solidity: function executeRollback(uint256 _sn) returns() +func (_CallService *CallServiceSession) ExecuteRollback(_sn *big.Int) (*types.Transaction, error) { + return _CallService.Contract.ExecuteRollback(&_CallService.TransactOpts, _sn) +} + +// ExecuteRollback is a paid mutator transaction binding the contract method 0x2a84e1b0. +// +// Solidity: function executeRollback(uint256 _sn) returns() +func (_CallService *CallServiceTransactorSession) ExecuteRollback(_sn *big.Int) (*types.Transaction, error) { + return _CallService.Contract.ExecuteRollback(&_CallService.TransactOpts, _sn) +} + +// HandleBTPError is a paid mutator transaction binding the contract method 0x0a823dea. +// +// Solidity: function handleBTPError(string _src, string _svc, uint256 _sn, uint256 _code, string _msg) returns() +func (_CallService *CallServiceTransactor) HandleBTPError(opts *bind.TransactOpts, _src string, _svc string, _sn *big.Int, _code *big.Int, _msg string) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "handleBTPError", _src, _svc, _sn, _code, _msg) +} + +// HandleBTPError is a paid mutator transaction binding the contract method 0x0a823dea. +// +// Solidity: function handleBTPError(string _src, string _svc, uint256 _sn, uint256 _code, string _msg) returns() +func (_CallService *CallServiceSession) HandleBTPError(_src string, _svc string, _sn *big.Int, _code *big.Int, _msg string) (*types.Transaction, error) { + return _CallService.Contract.HandleBTPError(&_CallService.TransactOpts, _src, _svc, _sn, _code, _msg) +} + +// HandleBTPError is a paid mutator transaction binding the contract method 0x0a823dea. +// +// Solidity: function handleBTPError(string _src, string _svc, uint256 _sn, uint256 _code, string _msg) returns() +func (_CallService *CallServiceTransactorSession) HandleBTPError(_src string, _svc string, _sn *big.Int, _code *big.Int, _msg string) (*types.Transaction, error) { + return _CallService.Contract.HandleBTPError(&_CallService.TransactOpts, _src, _svc, _sn, _code, _msg) +} + +// HandleBTPMessage is a paid mutator transaction binding the contract method 0xb70eeb8d. +// +// Solidity: function handleBTPMessage(string _from, string _svc, uint256 _sn, bytes _msg) returns() +func (_CallService *CallServiceTransactor) HandleBTPMessage(opts *bind.TransactOpts, _from string, _svc string, _sn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "handleBTPMessage", _from, _svc, _sn, _msg) +} + +// HandleBTPMessage is a paid mutator transaction binding the contract method 0xb70eeb8d. +// +// Solidity: function handleBTPMessage(string _from, string _svc, uint256 _sn, bytes _msg) returns() +func (_CallService *CallServiceSession) HandleBTPMessage(_from string, _svc string, _sn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CallService.Contract.HandleBTPMessage(&_CallService.TransactOpts, _from, _svc, _sn, _msg) +} + +// HandleBTPMessage is a paid mutator transaction binding the contract method 0xb70eeb8d. +// +// Solidity: function handleBTPMessage(string _from, string _svc, uint256 _sn, bytes _msg) returns() +func (_CallService *CallServiceTransactorSession) HandleBTPMessage(_from string, _svc string, _sn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CallService.Contract.HandleBTPMessage(&_CallService.TransactOpts, _from, _svc, _sn, _msg) +} + +// HandleError is a paid mutator transaction binding the contract method 0xb070f9e5. +// +// Solidity: function handleError(uint256 _sn) returns() +func (_CallService *CallServiceTransactor) HandleError(opts *bind.TransactOpts, _sn *big.Int) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "handleError", _sn) +} + +// HandleError is a paid mutator transaction binding the contract method 0xb070f9e5. +// +// Solidity: function handleError(uint256 _sn) returns() +func (_CallService *CallServiceSession) HandleError(_sn *big.Int) (*types.Transaction, error) { + return _CallService.Contract.HandleError(&_CallService.TransactOpts, _sn) +} + +// HandleError is a paid mutator transaction binding the contract method 0xb070f9e5. +// +// Solidity: function handleError(uint256 _sn) returns() +func (_CallService *CallServiceTransactorSession) HandleError(_sn *big.Int) (*types.Transaction, error) { + return _CallService.Contract.HandleError(&_CallService.TransactOpts, _sn) +} + +// HandleMessage is a paid mutator transaction binding the contract method 0xbbc22efd. +// +// Solidity: function handleMessage(string _from, bytes _msg) returns() +func (_CallService *CallServiceTransactor) HandleMessage(opts *bind.TransactOpts, _from string, _msg []byte) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "handleMessage", _from, _msg) +} + +// HandleMessage is a paid mutator transaction binding the contract method 0xbbc22efd. +// +// Solidity: function handleMessage(string _from, bytes _msg) returns() +func (_CallService *CallServiceSession) HandleMessage(_from string, _msg []byte) (*types.Transaction, error) { + return _CallService.Contract.HandleMessage(&_CallService.TransactOpts, _from, _msg) +} + +// HandleMessage is a paid mutator transaction binding the contract method 0xbbc22efd. +// +// Solidity: function handleMessage(string _from, bytes _msg) returns() +func (_CallService *CallServiceTransactorSession) HandleMessage(_from string, _msg []byte) (*types.Transaction, error) { + return _CallService.Contract.HandleMessage(&_CallService.TransactOpts, _from, _msg) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf62d1888. +// +// Solidity: function initialize(string _nid) returns() +func (_CallService *CallServiceTransactor) Initialize(opts *bind.TransactOpts, _nid string) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "initialize", _nid) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf62d1888. +// +// Solidity: function initialize(string _nid) returns() +func (_CallService *CallServiceSession) Initialize(_nid string) (*types.Transaction, error) { + return _CallService.Contract.Initialize(&_CallService.TransactOpts, _nid) +} + +// Initialize is a paid mutator transaction binding the contract method 0xf62d1888. +// +// Solidity: function initialize(string _nid) returns() +func (_CallService *CallServiceTransactorSession) Initialize(_nid string) (*types.Transaction, error) { + return _CallService.Contract.Initialize(&_CallService.TransactOpts, _nid) +} + +// SendCall is a paid mutator transaction binding the contract method 0x17fd7a33. +// +// Solidity: function sendCall(string _to, bytes _data) payable returns(uint256) +func (_CallService *CallServiceTransactor) SendCall(opts *bind.TransactOpts, _to string, _data []byte) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "sendCall", _to, _data) +} + +// SendCall is a paid mutator transaction binding the contract method 0x17fd7a33. +// +// Solidity: function sendCall(string _to, bytes _data) payable returns(uint256) +func (_CallService *CallServiceSession) SendCall(_to string, _data []byte) (*types.Transaction, error) { + return _CallService.Contract.SendCall(&_CallService.TransactOpts, _to, _data) +} + +// SendCall is a paid mutator transaction binding the contract method 0x17fd7a33. +// +// Solidity: function sendCall(string _to, bytes _data) payable returns(uint256) +func (_CallService *CallServiceTransactorSession) SendCall(_to string, _data []byte) (*types.Transaction, error) { + return _CallService.Contract.SendCall(&_CallService.TransactOpts, _to, _data) +} + +// SendCallMessage is a paid mutator transaction binding the contract method 0x8ef378b8. +// +// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback) payable returns(uint256) +func (_CallService *CallServiceTransactor) SendCallMessage(opts *bind.TransactOpts, _to string, _data []byte, _rollback []byte) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "sendCallMessage", _to, _data, _rollback) +} + +// SendCallMessage is a paid mutator transaction binding the contract method 0x8ef378b8. +// +// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback) payable returns(uint256) +func (_CallService *CallServiceSession) SendCallMessage(_to string, _data []byte, _rollback []byte) (*types.Transaction, error) { + return _CallService.Contract.SendCallMessage(&_CallService.TransactOpts, _to, _data, _rollback) +} + +// SendCallMessage is a paid mutator transaction binding the contract method 0x8ef378b8. +// +// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback) payable returns(uint256) +func (_CallService *CallServiceTransactorSession) SendCallMessage(_to string, _data []byte, _rollback []byte) (*types.Transaction, error) { + return _CallService.Contract.SendCallMessage(&_CallService.TransactOpts, _to, _data, _rollback) +} + +// SendCallMessage0 is a paid mutator transaction binding the contract method 0xedc6afff. +// +// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback, string[] sources, string[] destinations) payable returns(uint256) +func (_CallService *CallServiceTransactor) SendCallMessage0(opts *bind.TransactOpts, _to string, _data []byte, _rollback []byte, sources []string, destinations []string) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "sendCallMessage0", _to, _data, _rollback, sources, destinations) +} + +// SendCallMessage0 is a paid mutator transaction binding the contract method 0xedc6afff. +// +// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback, string[] sources, string[] destinations) payable returns(uint256) +func (_CallService *CallServiceSession) SendCallMessage0(_to string, _data []byte, _rollback []byte, sources []string, destinations []string) (*types.Transaction, error) { + return _CallService.Contract.SendCallMessage0(&_CallService.TransactOpts, _to, _data, _rollback, sources, destinations) +} + +// SendCallMessage0 is a paid mutator transaction binding the contract method 0xedc6afff. +// +// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback, string[] sources, string[] destinations) payable returns(uint256) +func (_CallService *CallServiceTransactorSession) SendCallMessage0(_to string, _data []byte, _rollback []byte, sources []string, destinations []string) (*types.Transaction, error) { + return _CallService.Contract.SendCallMessage0(&_CallService.TransactOpts, _to, _data, _rollback, sources, destinations) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address _address) returns() +func (_CallService *CallServiceTransactor) SetAdmin(opts *bind.TransactOpts, _address common.Address) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "setAdmin", _address) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address _address) returns() +func (_CallService *CallServiceSession) SetAdmin(_address common.Address) (*types.Transaction, error) { + return _CallService.Contract.SetAdmin(&_CallService.TransactOpts, _address) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address _address) returns() +func (_CallService *CallServiceTransactorSession) SetAdmin(_address common.Address) (*types.Transaction, error) { + return _CallService.Contract.SetAdmin(&_CallService.TransactOpts, _address) +} + +// SetDefaultConnection is a paid mutator transaction binding the contract method 0x64f03757. +// +// Solidity: function setDefaultConnection(string _nid, address connection) returns() +func (_CallService *CallServiceTransactor) SetDefaultConnection(opts *bind.TransactOpts, _nid string, connection common.Address) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "setDefaultConnection", _nid, connection) +} + +// SetDefaultConnection is a paid mutator transaction binding the contract method 0x64f03757. +// +// Solidity: function setDefaultConnection(string _nid, address connection) returns() +func (_CallService *CallServiceSession) SetDefaultConnection(_nid string, connection common.Address) (*types.Transaction, error) { + return _CallService.Contract.SetDefaultConnection(&_CallService.TransactOpts, _nid, connection) +} + +// SetDefaultConnection is a paid mutator transaction binding the contract method 0x64f03757. +// +// Solidity: function setDefaultConnection(string _nid, address connection) returns() +func (_CallService *CallServiceTransactorSession) SetDefaultConnection(_nid string, connection common.Address) (*types.Transaction, error) { + return _CallService.Contract.SetDefaultConnection(&_CallService.TransactOpts, _nid, connection) +} + +// SetProtocolFee is a paid mutator transaction binding the contract method 0x787dce3d. +// +// Solidity: function setProtocolFee(uint256 _value) returns() +func (_CallService *CallServiceTransactor) SetProtocolFee(opts *bind.TransactOpts, _value *big.Int) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "setProtocolFee", _value) +} + +// SetProtocolFee is a paid mutator transaction binding the contract method 0x787dce3d. +// +// Solidity: function setProtocolFee(uint256 _value) returns() +func (_CallService *CallServiceSession) SetProtocolFee(_value *big.Int) (*types.Transaction, error) { + return _CallService.Contract.SetProtocolFee(&_CallService.TransactOpts, _value) +} + +// SetProtocolFee is a paid mutator transaction binding the contract method 0x787dce3d. +// +// Solidity: function setProtocolFee(uint256 _value) returns() +func (_CallService *CallServiceTransactorSession) SetProtocolFee(_value *big.Int) (*types.Transaction, error) { + return _CallService.Contract.SetProtocolFee(&_CallService.TransactOpts, _value) +} + +// SetProtocolFeeHandler is a paid mutator transaction binding the contract method 0x502bf8e0. +// +// Solidity: function setProtocolFeeHandler(address _addr) returns() +func (_CallService *CallServiceTransactor) SetProtocolFeeHandler(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { + return _CallService.contract.Transact(opts, "setProtocolFeeHandler", _addr) +} + +// SetProtocolFeeHandler is a paid mutator transaction binding the contract method 0x502bf8e0. +// +// Solidity: function setProtocolFeeHandler(address _addr) returns() +func (_CallService *CallServiceSession) SetProtocolFeeHandler(_addr common.Address) (*types.Transaction, error) { + return _CallService.Contract.SetProtocolFeeHandler(&_CallService.TransactOpts, _addr) +} + +// SetProtocolFeeHandler is a paid mutator transaction binding the contract method 0x502bf8e0. +// +// Solidity: function setProtocolFeeHandler(address _addr) returns() +func (_CallService *CallServiceTransactorSession) SetProtocolFeeHandler(_addr common.Address) (*types.Transaction, error) { + return _CallService.Contract.SetProtocolFeeHandler(&_CallService.TransactOpts, _addr) +} + +// CallServiceCallExecutedIterator is returned from FilterCallExecuted and is used to iterate over the raw logs and unpacked data for CallExecuted events raised by the CallService contract. +type CallServiceCallExecutedIterator struct { + Event *CallServiceCallExecuted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CallServiceCallExecutedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CallServiceCallExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CallServiceCallExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CallServiceCallExecutedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CallServiceCallExecutedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CallServiceCallExecuted represents a CallExecuted event raised by the CallService contract. +type CallServiceCallExecuted struct { + ReqId *big.Int + Code *big.Int + Msg string + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCallExecuted is a free log retrieval operation binding the contract event 0xc7391e04887f8b3c16fa20877e028e8163139a478c8447e7d449eba1905caa51. +// +// Solidity: event CallExecuted(uint256 indexed _reqId, int256 _code, string _msg) +func (_CallService *CallServiceFilterer) FilterCallExecuted(opts *bind.FilterOpts, _reqId []*big.Int) (*CallServiceCallExecutedIterator, error) { + + var _reqIdRule []interface{} + for _, _reqIdItem := range _reqId { + _reqIdRule = append(_reqIdRule, _reqIdItem) + } + + logs, sub, err := _CallService.contract.FilterLogs(opts, "CallExecuted", _reqIdRule) + if err != nil { + return nil, err + } + return &CallServiceCallExecutedIterator{contract: _CallService.contract, event: "CallExecuted", logs: logs, sub: sub}, nil +} + +// WatchCallExecuted is a free log subscription operation binding the contract event 0xc7391e04887f8b3c16fa20877e028e8163139a478c8447e7d449eba1905caa51. +// +// Solidity: event CallExecuted(uint256 indexed _reqId, int256 _code, string _msg) +func (_CallService *CallServiceFilterer) WatchCallExecuted(opts *bind.WatchOpts, sink chan<- *CallServiceCallExecuted, _reqId []*big.Int) (event.Subscription, error) { + + var _reqIdRule []interface{} + for _, _reqIdItem := range _reqId { + _reqIdRule = append(_reqIdRule, _reqIdItem) + } + + logs, sub, err := _CallService.contract.WatchLogs(opts, "CallExecuted", _reqIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CallServiceCallExecuted) + if err := _CallService.contract.UnpackLog(event, "CallExecuted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseCallExecuted is a log parse operation binding the contract event 0xc7391e04887f8b3c16fa20877e028e8163139a478c8447e7d449eba1905caa51. +// +// Solidity: event CallExecuted(uint256 indexed _reqId, int256 _code, string _msg) +func (_CallService *CallServiceFilterer) ParseCallExecuted(log types.Log) (*CallServiceCallExecuted, error) { + event := new(CallServiceCallExecuted) + if err := _CallService.contract.UnpackLog(event, "CallExecuted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CallServiceCallMessageIterator is returned from FilterCallMessage and is used to iterate over the raw logs and unpacked data for CallMessage events raised by the CallService contract. +type CallServiceCallMessageIterator struct { + Event *CallServiceCallMessage // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CallServiceCallMessageIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CallServiceCallMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CallServiceCallMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CallServiceCallMessageIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CallServiceCallMessageIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CallServiceCallMessage represents a CallMessage event raised by the CallService contract. +type CallServiceCallMessage struct { + From common.Hash + To common.Hash + Sn *big.Int + ReqId *big.Int + Data []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCallMessage is a free log retrieval operation binding the contract event 0x2cbc78425621c181f9f8a25fc06e44a0ac2b67cd6a31f8ed7918934187f8cc59. +// +// Solidity: event CallMessage(string indexed _from, string indexed _to, uint256 indexed _sn, uint256 _reqId, bytes _data) +func (_CallService *CallServiceFilterer) FilterCallMessage(opts *bind.FilterOpts, _from []string, _to []string, _sn []*big.Int) (*CallServiceCallMessageIterator, error) { + + var _fromRule []interface{} + for _, _fromItem := range _from { + _fromRule = append(_fromRule, _fromItem) + } + var _toRule []interface{} + for _, _toItem := range _to { + _toRule = append(_toRule, _toItem) + } + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.FilterLogs(opts, "CallMessage", _fromRule, _toRule, _snRule) + if err != nil { + return nil, err + } + return &CallServiceCallMessageIterator{contract: _CallService.contract, event: "CallMessage", logs: logs, sub: sub}, nil +} + +// WatchCallMessage is a free log subscription operation binding the contract event 0x2cbc78425621c181f9f8a25fc06e44a0ac2b67cd6a31f8ed7918934187f8cc59. +// +// Solidity: event CallMessage(string indexed _from, string indexed _to, uint256 indexed _sn, uint256 _reqId, bytes _data) +func (_CallService *CallServiceFilterer) WatchCallMessage(opts *bind.WatchOpts, sink chan<- *CallServiceCallMessage, _from []string, _to []string, _sn []*big.Int) (event.Subscription, error) { + + var _fromRule []interface{} + for _, _fromItem := range _from { + _fromRule = append(_fromRule, _fromItem) + } + var _toRule []interface{} + for _, _toItem := range _to { + _toRule = append(_toRule, _toItem) + } + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.WatchLogs(opts, "CallMessage", _fromRule, _toRule, _snRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CallServiceCallMessage) + if err := _CallService.contract.UnpackLog(event, "CallMessage", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseCallMessage is a log parse operation binding the contract event 0x2cbc78425621c181f9f8a25fc06e44a0ac2b67cd6a31f8ed7918934187f8cc59. +// +// Solidity: event CallMessage(string indexed _from, string indexed _to, uint256 indexed _sn, uint256 _reqId, bytes _data) +func (_CallService *CallServiceFilterer) ParseCallMessage(log types.Log) (*CallServiceCallMessage, error) { + event := new(CallServiceCallMessage) + if err := _CallService.contract.UnpackLog(event, "CallMessage", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CallServiceCallMessageSentIterator is returned from FilterCallMessageSent and is used to iterate over the raw logs and unpacked data for CallMessageSent events raised by the CallService contract. +type CallServiceCallMessageSentIterator struct { + Event *CallServiceCallMessageSent // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CallServiceCallMessageSentIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CallServiceCallMessageSent) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CallServiceCallMessageSent) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CallServiceCallMessageSentIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CallServiceCallMessageSentIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CallServiceCallMessageSent represents a CallMessageSent event raised by the CallService contract. +type CallServiceCallMessageSent struct { + From common.Address + To common.Hash + Sn *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCallMessageSent is a free log retrieval operation binding the contract event 0x69e53ea70fdf945f6d035b3979748bc999151691fb1dc69d66f8017f8840ae28. +// +// Solidity: event CallMessageSent(address indexed _from, string indexed _to, uint256 indexed _sn) +func (_CallService *CallServiceFilterer) FilterCallMessageSent(opts *bind.FilterOpts, _from []common.Address, _to []string, _sn []*big.Int) (*CallServiceCallMessageSentIterator, error) { + + var _fromRule []interface{} + for _, _fromItem := range _from { + _fromRule = append(_fromRule, _fromItem) + } + var _toRule []interface{} + for _, _toItem := range _to { + _toRule = append(_toRule, _toItem) + } + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.FilterLogs(opts, "CallMessageSent", _fromRule, _toRule, _snRule) + if err != nil { + return nil, err + } + return &CallServiceCallMessageSentIterator{contract: _CallService.contract, event: "CallMessageSent", logs: logs, sub: sub}, nil +} + +// WatchCallMessageSent is a free log subscription operation binding the contract event 0x69e53ea70fdf945f6d035b3979748bc999151691fb1dc69d66f8017f8840ae28. +// +// Solidity: event CallMessageSent(address indexed _from, string indexed _to, uint256 indexed _sn) +func (_CallService *CallServiceFilterer) WatchCallMessageSent(opts *bind.WatchOpts, sink chan<- *CallServiceCallMessageSent, _from []common.Address, _to []string, _sn []*big.Int) (event.Subscription, error) { + + var _fromRule []interface{} + for _, _fromItem := range _from { + _fromRule = append(_fromRule, _fromItem) + } + var _toRule []interface{} + for _, _toItem := range _to { + _toRule = append(_toRule, _toItem) + } + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.WatchLogs(opts, "CallMessageSent", _fromRule, _toRule, _snRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CallServiceCallMessageSent) + if err := _CallService.contract.UnpackLog(event, "CallMessageSent", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseCallMessageSent is a log parse operation binding the contract event 0x69e53ea70fdf945f6d035b3979748bc999151691fb1dc69d66f8017f8840ae28. +// +// Solidity: event CallMessageSent(address indexed _from, string indexed _to, uint256 indexed _sn) +func (_CallService *CallServiceFilterer) ParseCallMessageSent(log types.Log) (*CallServiceCallMessageSent, error) { + event := new(CallServiceCallMessageSent) + if err := _CallService.contract.UnpackLog(event, "CallMessageSent", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CallServiceInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the CallService contract. +type CallServiceInitializedIterator struct { + Event *CallServiceInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CallServiceInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CallServiceInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CallServiceInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CallServiceInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CallServiceInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CallServiceInitialized represents a Initialized event raised by the CallService contract. +type CallServiceInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_CallService *CallServiceFilterer) FilterInitialized(opts *bind.FilterOpts) (*CallServiceInitializedIterator, error) { + + logs, sub, err := _CallService.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &CallServiceInitializedIterator{contract: _CallService.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_CallService *CallServiceFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *CallServiceInitialized) (event.Subscription, error) { + + logs, sub, err := _CallService.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CallServiceInitialized) + if err := _CallService.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_CallService *CallServiceFilterer) ParseInitialized(log types.Log) (*CallServiceInitialized, error) { + event := new(CallServiceInitialized) + if err := _CallService.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CallServiceResponseMessageIterator is returned from FilterResponseMessage and is used to iterate over the raw logs and unpacked data for ResponseMessage events raised by the CallService contract. +type CallServiceResponseMessageIterator struct { + Event *CallServiceResponseMessage // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CallServiceResponseMessageIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CallServiceResponseMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CallServiceResponseMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CallServiceResponseMessageIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CallServiceResponseMessageIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CallServiceResponseMessage represents a ResponseMessage event raised by the CallService contract. +type CallServiceResponseMessage struct { + Sn *big.Int + Code *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterResponseMessage is a free log retrieval operation binding the contract event 0xbeacafd006c5e60667f6f04aec3a498f81c8e94142b4e95b5a5a763de43ca0ab. +// +// Solidity: event ResponseMessage(uint256 indexed _sn, int256 _code) +func (_CallService *CallServiceFilterer) FilterResponseMessage(opts *bind.FilterOpts, _sn []*big.Int) (*CallServiceResponseMessageIterator, error) { + + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.FilterLogs(opts, "ResponseMessage", _snRule) + if err != nil { + return nil, err + } + return &CallServiceResponseMessageIterator{contract: _CallService.contract, event: "ResponseMessage", logs: logs, sub: sub}, nil +} + +// WatchResponseMessage is a free log subscription operation binding the contract event 0xbeacafd006c5e60667f6f04aec3a498f81c8e94142b4e95b5a5a763de43ca0ab. +// +// Solidity: event ResponseMessage(uint256 indexed _sn, int256 _code) +func (_CallService *CallServiceFilterer) WatchResponseMessage(opts *bind.WatchOpts, sink chan<- *CallServiceResponseMessage, _sn []*big.Int) (event.Subscription, error) { + + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.WatchLogs(opts, "ResponseMessage", _snRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CallServiceResponseMessage) + if err := _CallService.contract.UnpackLog(event, "ResponseMessage", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseResponseMessage is a log parse operation binding the contract event 0xbeacafd006c5e60667f6f04aec3a498f81c8e94142b4e95b5a5a763de43ca0ab. +// +// Solidity: event ResponseMessage(uint256 indexed _sn, int256 _code) +func (_CallService *CallServiceFilterer) ParseResponseMessage(log types.Log) (*CallServiceResponseMessage, error) { + event := new(CallServiceResponseMessage) + if err := _CallService.contract.UnpackLog(event, "ResponseMessage", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CallServiceRollbackExecutedIterator is returned from FilterRollbackExecuted and is used to iterate over the raw logs and unpacked data for RollbackExecuted events raised by the CallService contract. +type CallServiceRollbackExecutedIterator struct { + Event *CallServiceRollbackExecuted // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CallServiceRollbackExecutedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CallServiceRollbackExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CallServiceRollbackExecuted) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CallServiceRollbackExecutedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CallServiceRollbackExecutedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CallServiceRollbackExecuted represents a RollbackExecuted event raised by the CallService contract. +type CallServiceRollbackExecuted struct { + Sn *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRollbackExecuted is a free log retrieval operation binding the contract event 0x08f0ac7aef6da8bbe43bee8b1444a1883f1359566618bc379ce5abba44883837. +// +// Solidity: event RollbackExecuted(uint256 indexed _sn) +func (_CallService *CallServiceFilterer) FilterRollbackExecuted(opts *bind.FilterOpts, _sn []*big.Int) (*CallServiceRollbackExecutedIterator, error) { + + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.FilterLogs(opts, "RollbackExecuted", _snRule) + if err != nil { + return nil, err + } + return &CallServiceRollbackExecutedIterator{contract: _CallService.contract, event: "RollbackExecuted", logs: logs, sub: sub}, nil +} + +// WatchRollbackExecuted is a free log subscription operation binding the contract event 0x08f0ac7aef6da8bbe43bee8b1444a1883f1359566618bc379ce5abba44883837. +// +// Solidity: event RollbackExecuted(uint256 indexed _sn) +func (_CallService *CallServiceFilterer) WatchRollbackExecuted(opts *bind.WatchOpts, sink chan<- *CallServiceRollbackExecuted, _sn []*big.Int) (event.Subscription, error) { + + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.WatchLogs(opts, "RollbackExecuted", _snRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CallServiceRollbackExecuted) + if err := _CallService.contract.UnpackLog(event, "RollbackExecuted", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRollbackExecuted is a log parse operation binding the contract event 0x08f0ac7aef6da8bbe43bee8b1444a1883f1359566618bc379ce5abba44883837. +// +// Solidity: event RollbackExecuted(uint256 indexed _sn) +func (_CallService *CallServiceFilterer) ParseRollbackExecuted(log types.Log) (*CallServiceRollbackExecuted, error) { + event := new(CallServiceRollbackExecuted) + if err := _CallService.contract.UnpackLog(event, "RollbackExecuted", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CallServiceRollbackMessageIterator is returned from FilterRollbackMessage and is used to iterate over the raw logs and unpacked data for RollbackMessage events raised by the CallService contract. +type CallServiceRollbackMessageIterator struct { + Event *CallServiceRollbackMessage // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CallServiceRollbackMessageIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CallServiceRollbackMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CallServiceRollbackMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CallServiceRollbackMessageIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CallServiceRollbackMessageIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CallServiceRollbackMessage represents a RollbackMessage event raised by the CallService contract. +type CallServiceRollbackMessage struct { + Sn *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterRollbackMessage is a free log retrieval operation binding the contract event 0x38934ab923f985814047679ba041577b8203ddd15fe9910d3fc6a7aa6001e9c7. +// +// Solidity: event RollbackMessage(uint256 indexed _sn) +func (_CallService *CallServiceFilterer) FilterRollbackMessage(opts *bind.FilterOpts, _sn []*big.Int) (*CallServiceRollbackMessageIterator, error) { + + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.FilterLogs(opts, "RollbackMessage", _snRule) + if err != nil { + return nil, err + } + return &CallServiceRollbackMessageIterator{contract: _CallService.contract, event: "RollbackMessage", logs: logs, sub: sub}, nil +} + +// WatchRollbackMessage is a free log subscription operation binding the contract event 0x38934ab923f985814047679ba041577b8203ddd15fe9910d3fc6a7aa6001e9c7. +// +// Solidity: event RollbackMessage(uint256 indexed _sn) +func (_CallService *CallServiceFilterer) WatchRollbackMessage(opts *bind.WatchOpts, sink chan<- *CallServiceRollbackMessage, _sn []*big.Int) (event.Subscription, error) { + + var _snRule []interface{} + for _, _snItem := range _sn { + _snRule = append(_snRule, _snItem) + } + + logs, sub, err := _CallService.contract.WatchLogs(opts, "RollbackMessage", _snRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CallServiceRollbackMessage) + if err := _CallService.contract.UnpackLog(event, "RollbackMessage", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseRollbackMessage is a log parse operation binding the contract event 0x38934ab923f985814047679ba041577b8203ddd15fe9910d3fc6a7aa6001e9c7. +// +// Solidity: event RollbackMessage(uint256 indexed _sn) +func (_CallService *CallServiceFilterer) ParseRollbackMessage(log types.Log) (*CallServiceRollbackMessage, error) { + event := new(CallServiceRollbackMessage) + if err := _CallService.contract.UnpackLog(event, "RollbackMessage", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/relayer/chains/bitcoin/abi/icentralized_connection.go b/relayer/chains/bitcoin/abi/icentralized_connection.go new file mode 100644 index 00000000..9842ab51 --- /dev/null +++ b/relayer/chains/bitcoin/abi/icentralized_connection.go @@ -0,0 +1,722 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package abi + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// CentralizedConnectionMetaData contains all meta data concerning the CentralizedConnection contract. +var CentralizedConnectionMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"admin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimFees\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"connSn\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"response\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[{\"name\":\"fee\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getReceipt\",\"inputs\":[{\"name\":\"srcNetwork\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_connSn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_relayer\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_xCall\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"recvMessage\",\"inputs\":[{\"name\":\"srcNetwork\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_connSn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revertMessage\",\"inputs\":[{\"name\":\"sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendMessage\",\"inputs\":[{\"name\":\"to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"svc\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sn\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"setAdmin\",\"inputs\":[{\"name\":\"_address\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setFee\",\"inputs\":[{\"name\":\"networkId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"messageFee\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"responseFee\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Message\",\"inputs\":[{\"name\":\"targetNetwork\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"sn\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]}]", +} + +// CentralizedConnectionABI is the input ABI used to generate the binding from. +// Deprecated: Use CentralizedConnectionMetaData.ABI instead. +var CentralizedConnectionABI = CentralizedConnectionMetaData.ABI + +// CentralizedConnection is an auto generated Go binding around an Ethereum contract. +type CentralizedConnection struct { + CentralizedConnectionCaller // Read-only binding to the contract + CentralizedConnectionTransactor // Write-only binding to the contract + CentralizedConnectionFilterer // Log filterer for contract events +} + +// CentralizedConnectionCaller is an auto generated read-only Go binding around an Ethereum contract. +type CentralizedConnectionCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CentralizedConnectionTransactor is an auto generated write-only Go binding around an Ethereum contract. +type CentralizedConnectionTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CentralizedConnectionFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type CentralizedConnectionFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// CentralizedConnectionSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type CentralizedConnectionSession struct { + Contract *CentralizedConnection // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CentralizedConnectionCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type CentralizedConnectionCallerSession struct { + Contract *CentralizedConnectionCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// CentralizedConnectionTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type CentralizedConnectionTransactorSession struct { + Contract *CentralizedConnectionTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// CentralizedConnectionRaw is an auto generated low-level Go binding around an Ethereum contract. +type CentralizedConnectionRaw struct { + Contract *CentralizedConnection // Generic contract binding to access the raw methods on +} + +// CentralizedConnectionCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type CentralizedConnectionCallerRaw struct { + Contract *CentralizedConnectionCaller // Generic read-only contract binding to access the raw methods on +} + +// CentralizedConnectionTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type CentralizedConnectionTransactorRaw struct { + Contract *CentralizedConnectionTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewCentralizedConnection creates a new instance of CentralizedConnection, bound to a specific deployed contract. +func NewCentralizedConnection(address common.Address, backend bind.ContractBackend) (*CentralizedConnection, error) { + contract, err := bindCentralizedConnection(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CentralizedConnection{CentralizedConnectionCaller: CentralizedConnectionCaller{contract: contract}, CentralizedConnectionTransactor: CentralizedConnectionTransactor{contract: contract}, CentralizedConnectionFilterer: CentralizedConnectionFilterer{contract: contract}}, nil +} + +// NewCentralizedConnectionCaller creates a new read-only instance of CentralizedConnection, bound to a specific deployed contract. +func NewCentralizedConnectionCaller(address common.Address, caller bind.ContractCaller) (*CentralizedConnectionCaller, error) { + contract, err := bindCentralizedConnection(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CentralizedConnectionCaller{contract: contract}, nil +} + +// NewCentralizedConnectionTransactor creates a new write-only instance of CentralizedConnection, bound to a specific deployed contract. +func NewCentralizedConnectionTransactor(address common.Address, transactor bind.ContractTransactor) (*CentralizedConnectionTransactor, error) { + contract, err := bindCentralizedConnection(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CentralizedConnectionTransactor{contract: contract}, nil +} + +// NewCentralizedConnectionFilterer creates a new log filterer instance of CentralizedConnection, bound to a specific deployed contract. +func NewCentralizedConnectionFilterer(address common.Address, filterer bind.ContractFilterer) (*CentralizedConnectionFilterer, error) { + contract, err := bindCentralizedConnection(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CentralizedConnectionFilterer{contract: contract}, nil +} + +// bindCentralizedConnection binds a generic wrapper to an already deployed contract. +func bindCentralizedConnection(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CentralizedConnectionMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CentralizedConnection *CentralizedConnectionRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CentralizedConnection.Contract.CentralizedConnectionCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CentralizedConnection *CentralizedConnectionRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CentralizedConnection.Contract.CentralizedConnectionTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CentralizedConnection *CentralizedConnectionRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CentralizedConnection.Contract.CentralizedConnectionTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_CentralizedConnection *CentralizedConnectionCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CentralizedConnection.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_CentralizedConnection *CentralizedConnectionTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CentralizedConnection.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_CentralizedConnection *CentralizedConnectionTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CentralizedConnection.Contract.contract.Transact(opts, method, params...) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_CentralizedConnection *CentralizedConnectionCaller) Admin(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CentralizedConnection.contract.Call(opts, &out, "admin") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_CentralizedConnection *CentralizedConnectionSession) Admin() (common.Address, error) { + return _CentralizedConnection.Contract.Admin(&_CentralizedConnection.CallOpts) +} + +// Admin is a free data retrieval call binding the contract method 0xf851a440. +// +// Solidity: function admin() view returns(address) +func (_CentralizedConnection *CentralizedConnectionCallerSession) Admin() (common.Address, error) { + return _CentralizedConnection.Contract.Admin(&_CentralizedConnection.CallOpts) +} + +// ConnSn is a free data retrieval call binding the contract method 0x99f1fca7. +// +// Solidity: function connSn() view returns(uint256) +func (_CentralizedConnection *CentralizedConnectionCaller) ConnSn(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _CentralizedConnection.contract.Call(opts, &out, "connSn") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// ConnSn is a free data retrieval call binding the contract method 0x99f1fca7. +// +// Solidity: function connSn() view returns(uint256) +func (_CentralizedConnection *CentralizedConnectionSession) ConnSn() (*big.Int, error) { + return _CentralizedConnection.Contract.ConnSn(&_CentralizedConnection.CallOpts) +} + +// ConnSn is a free data retrieval call binding the contract method 0x99f1fca7. +// +// Solidity: function connSn() view returns(uint256) +func (_CentralizedConnection *CentralizedConnectionCallerSession) ConnSn() (*big.Int, error) { + return _CentralizedConnection.Contract.ConnSn(&_CentralizedConnection.CallOpts) +} + +// GetFee is a free data retrieval call binding the contract method 0x7d4c4f4a. +// +// Solidity: function getFee(string to, bool response) view returns(uint256 fee) +func (_CentralizedConnection *CentralizedConnectionCaller) GetFee(opts *bind.CallOpts, to string, response bool) (*big.Int, error) { + var out []interface{} + err := _CentralizedConnection.contract.Call(opts, &out, "getFee", to, response) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// GetFee is a free data retrieval call binding the contract method 0x7d4c4f4a. +// +// Solidity: function getFee(string to, bool response) view returns(uint256 fee) +func (_CentralizedConnection *CentralizedConnectionSession) GetFee(to string, response bool) (*big.Int, error) { + return _CentralizedConnection.Contract.GetFee(&_CentralizedConnection.CallOpts, to, response) +} + +// GetFee is a free data retrieval call binding the contract method 0x7d4c4f4a. +// +// Solidity: function getFee(string to, bool response) view returns(uint256 fee) +func (_CentralizedConnection *CentralizedConnectionCallerSession) GetFee(to string, response bool) (*big.Int, error) { + return _CentralizedConnection.Contract.GetFee(&_CentralizedConnection.CallOpts, to, response) +} + +// GetReceipt is a free data retrieval call binding the contract method 0x9664da0e. +// +// Solidity: function getReceipt(string srcNetwork, uint256 _connSn) view returns(bool) +func (_CentralizedConnection *CentralizedConnectionCaller) GetReceipt(opts *bind.CallOpts, srcNetwork string, _connSn *big.Int) (bool, error) { + var out []interface{} + err := _CentralizedConnection.contract.Call(opts, &out, "getReceipt", srcNetwork, _connSn) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// GetReceipt is a free data retrieval call binding the contract method 0x9664da0e. +// +// Solidity: function getReceipt(string srcNetwork, uint256 _connSn) view returns(bool) +func (_CentralizedConnection *CentralizedConnectionSession) GetReceipt(srcNetwork string, _connSn *big.Int) (bool, error) { + return _CentralizedConnection.Contract.GetReceipt(&_CentralizedConnection.CallOpts, srcNetwork, _connSn) +} + +// GetReceipt is a free data retrieval call binding the contract method 0x9664da0e. +// +// Solidity: function getReceipt(string srcNetwork, uint256 _connSn) view returns(bool) +func (_CentralizedConnection *CentralizedConnectionCallerSession) GetReceipt(srcNetwork string, _connSn *big.Int) (bool, error) { + return _CentralizedConnection.Contract.GetReceipt(&_CentralizedConnection.CallOpts, srcNetwork, _connSn) +} + +// ClaimFees is a paid mutator transaction binding the contract method 0xd294f093. +// +// Solidity: function claimFees() returns() +func (_CentralizedConnection *CentralizedConnectionTransactor) ClaimFees(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CentralizedConnection.contract.Transact(opts, "claimFees") +} + +// ClaimFees is a paid mutator transaction binding the contract method 0xd294f093. +// +// Solidity: function claimFees() returns() +func (_CentralizedConnection *CentralizedConnectionSession) ClaimFees() (*types.Transaction, error) { + return _CentralizedConnection.Contract.ClaimFees(&_CentralizedConnection.TransactOpts) +} + +// ClaimFees is a paid mutator transaction binding the contract method 0xd294f093. +// +// Solidity: function claimFees() returns() +func (_CentralizedConnection *CentralizedConnectionTransactorSession) ClaimFees() (*types.Transaction, error) { + return _CentralizedConnection.Contract.ClaimFees(&_CentralizedConnection.TransactOpts) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address _relayer, address _xCall) returns() +func (_CentralizedConnection *CentralizedConnectionTransactor) Initialize(opts *bind.TransactOpts, _relayer common.Address, _xCall common.Address) (*types.Transaction, error) { + return _CentralizedConnection.contract.Transact(opts, "initialize", _relayer, _xCall) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address _relayer, address _xCall) returns() +func (_CentralizedConnection *CentralizedConnectionSession) Initialize(_relayer common.Address, _xCall common.Address) (*types.Transaction, error) { + return _CentralizedConnection.Contract.Initialize(&_CentralizedConnection.TransactOpts, _relayer, _xCall) +} + +// Initialize is a paid mutator transaction binding the contract method 0x485cc955. +// +// Solidity: function initialize(address _relayer, address _xCall) returns() +func (_CentralizedConnection *CentralizedConnectionTransactorSession) Initialize(_relayer common.Address, _xCall common.Address) (*types.Transaction, error) { + return _CentralizedConnection.Contract.Initialize(&_CentralizedConnection.TransactOpts, _relayer, _xCall) +} + +// RecvMessage is a paid mutator transaction binding the contract method 0xb58b4cec. +// +// Solidity: function recvMessage(string srcNetwork, uint256 _connSn, bytes _msg) returns() +func (_CentralizedConnection *CentralizedConnectionTransactor) RecvMessage(opts *bind.TransactOpts, srcNetwork string, _connSn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CentralizedConnection.contract.Transact(opts, "recvMessage", srcNetwork, _connSn, _msg) +} + +// RecvMessage is a paid mutator transaction binding the contract method 0xb58b4cec. +// +// Solidity: function recvMessage(string srcNetwork, uint256 _connSn, bytes _msg) returns() +func (_CentralizedConnection *CentralizedConnectionSession) RecvMessage(srcNetwork string, _connSn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CentralizedConnection.Contract.RecvMessage(&_CentralizedConnection.TransactOpts, srcNetwork, _connSn, _msg) +} + +// RecvMessage is a paid mutator transaction binding the contract method 0xb58b4cec. +// +// Solidity: function recvMessage(string srcNetwork, uint256 _connSn, bytes _msg) returns() +func (_CentralizedConnection *CentralizedConnectionTransactorSession) RecvMessage(srcNetwork string, _connSn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CentralizedConnection.Contract.RecvMessage(&_CentralizedConnection.TransactOpts, srcNetwork, _connSn, _msg) +} + +// RevertMessage is a paid mutator transaction binding the contract method 0x2d3fb823. +// +// Solidity: function revertMessage(uint256 sn) returns() +func (_CentralizedConnection *CentralizedConnectionTransactor) RevertMessage(opts *bind.TransactOpts, sn *big.Int) (*types.Transaction, error) { + return _CentralizedConnection.contract.Transact(opts, "revertMessage", sn) +} + +// RevertMessage is a paid mutator transaction binding the contract method 0x2d3fb823. +// +// Solidity: function revertMessage(uint256 sn) returns() +func (_CentralizedConnection *CentralizedConnectionSession) RevertMessage(sn *big.Int) (*types.Transaction, error) { + return _CentralizedConnection.Contract.RevertMessage(&_CentralizedConnection.TransactOpts, sn) +} + +// RevertMessage is a paid mutator transaction binding the contract method 0x2d3fb823. +// +// Solidity: function revertMessage(uint256 sn) returns() +func (_CentralizedConnection *CentralizedConnectionTransactorSession) RevertMessage(sn *big.Int) (*types.Transaction, error) { + return _CentralizedConnection.Contract.RevertMessage(&_CentralizedConnection.TransactOpts, sn) +} + +// SendMessage is a paid mutator transaction binding the contract method 0x522a901e. +// +// Solidity: function sendMessage(string to, string svc, int256 sn, bytes _msg) payable returns() +func (_CentralizedConnection *CentralizedConnectionTransactor) SendMessage(opts *bind.TransactOpts, to string, svc string, sn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CentralizedConnection.contract.Transact(opts, "sendMessage", to, svc, sn, _msg) +} + +// SendMessage is a paid mutator transaction binding the contract method 0x522a901e. +// +// Solidity: function sendMessage(string to, string svc, int256 sn, bytes _msg) payable returns() +func (_CentralizedConnection *CentralizedConnectionSession) SendMessage(to string, svc string, sn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CentralizedConnection.Contract.SendMessage(&_CentralizedConnection.TransactOpts, to, svc, sn, _msg) +} + +// SendMessage is a paid mutator transaction binding the contract method 0x522a901e. +// +// Solidity: function sendMessage(string to, string svc, int256 sn, bytes _msg) payable returns() +func (_CentralizedConnection *CentralizedConnectionTransactorSession) SendMessage(to string, svc string, sn *big.Int, _msg []byte) (*types.Transaction, error) { + return _CentralizedConnection.Contract.SendMessage(&_CentralizedConnection.TransactOpts, to, svc, sn, _msg) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address _address) returns() +func (_CentralizedConnection *CentralizedConnectionTransactor) SetAdmin(opts *bind.TransactOpts, _address common.Address) (*types.Transaction, error) { + return _CentralizedConnection.contract.Transact(opts, "setAdmin", _address) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address _address) returns() +func (_CentralizedConnection *CentralizedConnectionSession) SetAdmin(_address common.Address) (*types.Transaction, error) { + return _CentralizedConnection.Contract.SetAdmin(&_CentralizedConnection.TransactOpts, _address) +} + +// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. +// +// Solidity: function setAdmin(address _address) returns() +func (_CentralizedConnection *CentralizedConnectionTransactorSession) SetAdmin(_address common.Address) (*types.Transaction, error) { + return _CentralizedConnection.Contract.SetAdmin(&_CentralizedConnection.TransactOpts, _address) +} + +// SetFee is a paid mutator transaction binding the contract method 0x43f08a89. +// +// Solidity: function setFee(string networkId, uint256 messageFee, uint256 responseFee) returns() +func (_CentralizedConnection *CentralizedConnectionTransactor) SetFee(opts *bind.TransactOpts, networkId string, messageFee *big.Int, responseFee *big.Int) (*types.Transaction, error) { + return _CentralizedConnection.contract.Transact(opts, "setFee", networkId, messageFee, responseFee) +} + +// SetFee is a paid mutator transaction binding the contract method 0x43f08a89. +// +// Solidity: function setFee(string networkId, uint256 messageFee, uint256 responseFee) returns() +func (_CentralizedConnection *CentralizedConnectionSession) SetFee(networkId string, messageFee *big.Int, responseFee *big.Int) (*types.Transaction, error) { + return _CentralizedConnection.Contract.SetFee(&_CentralizedConnection.TransactOpts, networkId, messageFee, responseFee) +} + +// SetFee is a paid mutator transaction binding the contract method 0x43f08a89. +// +// Solidity: function setFee(string networkId, uint256 messageFee, uint256 responseFee) returns() +func (_CentralizedConnection *CentralizedConnectionTransactorSession) SetFee(networkId string, messageFee *big.Int, responseFee *big.Int) (*types.Transaction, error) { + return _CentralizedConnection.Contract.SetFee(&_CentralizedConnection.TransactOpts, networkId, messageFee, responseFee) +} + +// CentralizedConnectionInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the CentralizedConnection contract. +type CentralizedConnectionInitializedIterator struct { + Event *CentralizedConnectionInitialized // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CentralizedConnectionInitializedIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CentralizedConnectionInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CentralizedConnectionInitialized) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CentralizedConnectionInitializedIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CentralizedConnectionInitializedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CentralizedConnectionInitialized represents a Initialized event raised by the CentralizedConnection contract. +type CentralizedConnectionInitialized struct { + Version uint64 + Raw types.Log // Blockchain specific contextual infos +} + +// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_CentralizedConnection *CentralizedConnectionFilterer) FilterInitialized(opts *bind.FilterOpts) (*CentralizedConnectionInitializedIterator, error) { + + logs, sub, err := _CentralizedConnection.contract.FilterLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return &CentralizedConnectionInitializedIterator{contract: _CentralizedConnection.contract, event: "Initialized", logs: logs, sub: sub}, nil +} + +// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_CentralizedConnection *CentralizedConnectionFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *CentralizedConnectionInitialized) (event.Subscription, error) { + + logs, sub, err := _CentralizedConnection.contract.WatchLogs(opts, "Initialized") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CentralizedConnectionInitialized) + if err := _CentralizedConnection.contract.UnpackLog(event, "Initialized", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. +// +// Solidity: event Initialized(uint64 version) +func (_CentralizedConnection *CentralizedConnectionFilterer) ParseInitialized(log types.Log) (*CentralizedConnectionInitialized, error) { + event := new(CentralizedConnectionInitialized) + if err := _CentralizedConnection.contract.UnpackLog(event, "Initialized", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// CentralizedConnectionMessageIterator is returned from FilterMessage and is used to iterate over the raw logs and unpacked data for Message events raised by the CentralizedConnection contract. +type CentralizedConnectionMessageIterator struct { + Event *CentralizedConnectionMessage // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *CentralizedConnectionMessageIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(CentralizedConnectionMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(CentralizedConnectionMessage) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *CentralizedConnectionMessageIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *CentralizedConnectionMessageIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// CentralizedConnectionMessage represents a Message event raised by the CentralizedConnection contract. +type CentralizedConnectionMessage struct { + TargetNetwork string + Sn *big.Int + Msg []byte + Raw types.Log // Blockchain specific contextual infos +} + +// FilterMessage is a free log retrieval operation binding the contract event 0x37be353f216cf7e33639101fd610c542e6a0c0109173fa1c1d8b04d34edb7c1b. +// +// Solidity: event Message(string targetNetwork, uint256 sn, bytes _msg) +func (_CentralizedConnection *CentralizedConnectionFilterer) FilterMessage(opts *bind.FilterOpts) (*CentralizedConnectionMessageIterator, error) { + + logs, sub, err := _CentralizedConnection.contract.FilterLogs(opts, "Message") + if err != nil { + return nil, err + } + return &CentralizedConnectionMessageIterator{contract: _CentralizedConnection.contract, event: "Message", logs: logs, sub: sub}, nil +} + +// WatchMessage is a free log subscription operation binding the contract event 0x37be353f216cf7e33639101fd610c542e6a0c0109173fa1c1d8b04d34edb7c1b. +// +// Solidity: event Message(string targetNetwork, uint256 sn, bytes _msg) +func (_CentralizedConnection *CentralizedConnectionFilterer) WatchMessage(opts *bind.WatchOpts, sink chan<- *CentralizedConnectionMessage) (event.Subscription, error) { + + logs, sub, err := _CentralizedConnection.contract.WatchLogs(opts, "Message") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(CentralizedConnectionMessage) + if err := _CentralizedConnection.contract.UnpackLog(event, "Message", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseMessage is a log parse operation binding the contract event 0x37be353f216cf7e33639101fd610c542e6a0c0109173fa1c1d8b04d34edb7c1b. +// +// Solidity: event Message(string targetNetwork, uint256 sn, bytes _msg) +func (_CentralizedConnection *CentralizedConnectionFilterer) ParseMessage(log types.Log) (*CentralizedConnectionMessage, error) { + event := new(CentralizedConnectionMessage) + if err := _CentralizedConnection.contract.UnpackLog(event, "Message", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/relayer/chains/bitcoin/abi/inonfungible_token.go b/relayer/chains/bitcoin/abi/inonfungible_token.go new file mode 100644 index 00000000..b4d22c64 --- /dev/null +++ b/relayer/chains/bitcoin/abi/inonfungible_token.go @@ -0,0 +1,2017 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package abi + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// INonfungiblePositionManagerCollectParams is an auto generated low-level Go binding around an user-defined struct. +type INonfungiblePositionManagerCollectParams struct { + TokenId *big.Int + Recipient common.Address + Amount0Max *big.Int + Amount1Max *big.Int +} + +// INonfungiblePositionManagerDecreaseLiquidityParams is an auto generated low-level Go binding around an user-defined struct. +type INonfungiblePositionManagerDecreaseLiquidityParams struct { + TokenId *big.Int + Liquidity *big.Int + Amount0Min *big.Int + Amount1Min *big.Int + Deadline *big.Int +} + +// INonfungiblePositionManagerIncreaseLiquidityParams is an auto generated low-level Go binding around an user-defined struct. +type INonfungiblePositionManagerIncreaseLiquidityParams struct { + TokenId *big.Int + Amount0Desired *big.Int + Amount1Desired *big.Int + Amount0Min *big.Int + Amount1Min *big.Int + Deadline *big.Int +} + +// INonfungiblePositionManagerMintParams is an auto generated low-level Go binding around an user-defined struct. +type INonfungiblePositionManagerMintParams struct { + Token0 common.Address + Token1 common.Address + Fee *big.Int + TickLower *big.Int + TickUpper *big.Int + Amount0Desired *big.Int + Amount1Desired *big.Int + Amount0Min *big.Int + Amount1Min *big.Int + Recipient common.Address + Deadline *big.Int +} + +// InonfungibleTokenMetaData contains all meta data concerning the InonfungibleToken contract. +var InonfungibleTokenMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"DOMAIN_SEPARATOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PERMIT_TYPEHASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"WETH9\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"collect\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.CollectParams\",\"components\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount0Max\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount1Max\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"createAndInitializePoolIfNecessary\",\"inputs\":[{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"sqrtPriceX96\",\"type\":\"uint160\",\"internalType\":\"uint160\"}],\"outputs\":[{\"name\":\"pool\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"decreaseLiquidity\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.DecreaseLiquidityParams\",\"components\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount0Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"factory\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getApproved\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"increaseLiquidity\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.IncreaseLiquidityParams\",\"components\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount0Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount0Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"isApprovedForAll\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.MintParams\",\"components\":[{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"tickLower\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"tickUpper\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"amount0Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount0Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ownerOf\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"permit\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"positions\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"nonce\",\"type\":\"uint96\",\"internalType\":\"uint96\"},{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"tickLower\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"tickUpper\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"feeGrowthInside0LastX128\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"feeGrowthInside1LastX128\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokensOwed0\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"tokensOwed1\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundETH\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"safeTransferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"safeTransferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setApprovalForAll\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_approved\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"sweepToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amountMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokenByIndex\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokenOfOwnerByIndex\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokenURI\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unwrapWETH9\",\"inputs\":[{\"name\":\"amountMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"approved\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApprovalForAll\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"approved\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Collect\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DecreaseLiquidity\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"IncreaseLiquidity\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false}]", +} + +// InonfungibleTokenABI is the input ABI used to generate the binding from. +// Deprecated: Use InonfungibleTokenMetaData.ABI instead. +var InonfungibleTokenABI = InonfungibleTokenMetaData.ABI + +// InonfungibleToken is an auto generated Go binding around an Ethereum contract. +type InonfungibleToken struct { + InonfungibleTokenCaller // Read-only binding to the contract + InonfungibleTokenTransactor // Write-only binding to the contract + InonfungibleTokenFilterer // Log filterer for contract events +} + +// InonfungibleTokenCaller is an auto generated read-only Go binding around an Ethereum contract. +type InonfungibleTokenCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InonfungibleTokenTransactor is an auto generated write-only Go binding around an Ethereum contract. +type InonfungibleTokenTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InonfungibleTokenFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type InonfungibleTokenFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// InonfungibleTokenSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type InonfungibleTokenSession struct { + Contract *InonfungibleToken // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// InonfungibleTokenCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type InonfungibleTokenCallerSession struct { + Contract *InonfungibleTokenCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// InonfungibleTokenTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type InonfungibleTokenTransactorSession struct { + Contract *InonfungibleTokenTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// InonfungibleTokenRaw is an auto generated low-level Go binding around an Ethereum contract. +type InonfungibleTokenRaw struct { + Contract *InonfungibleToken // Generic contract binding to access the raw methods on +} + +// InonfungibleTokenCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type InonfungibleTokenCallerRaw struct { + Contract *InonfungibleTokenCaller // Generic read-only contract binding to access the raw methods on +} + +// InonfungibleTokenTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type InonfungibleTokenTransactorRaw struct { + Contract *InonfungibleTokenTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewInonfungibleToken creates a new instance of InonfungibleToken, bound to a specific deployed contract. +func NewInonfungibleToken(address common.Address, backend bind.ContractBackend) (*InonfungibleToken, error) { + contract, err := bindInonfungibleToken(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &InonfungibleToken{InonfungibleTokenCaller: InonfungibleTokenCaller{contract: contract}, InonfungibleTokenTransactor: InonfungibleTokenTransactor{contract: contract}, InonfungibleTokenFilterer: InonfungibleTokenFilterer{contract: contract}}, nil +} + +// NewInonfungibleTokenCaller creates a new read-only instance of InonfungibleToken, bound to a specific deployed contract. +func NewInonfungibleTokenCaller(address common.Address, caller bind.ContractCaller) (*InonfungibleTokenCaller, error) { + contract, err := bindInonfungibleToken(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &InonfungibleTokenCaller{contract: contract}, nil +} + +// NewInonfungibleTokenTransactor creates a new write-only instance of InonfungibleToken, bound to a specific deployed contract. +func NewInonfungibleTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*InonfungibleTokenTransactor, error) { + contract, err := bindInonfungibleToken(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &InonfungibleTokenTransactor{contract: contract}, nil +} + +// NewInonfungibleTokenFilterer creates a new log filterer instance of InonfungibleToken, bound to a specific deployed contract. +func NewInonfungibleTokenFilterer(address common.Address, filterer bind.ContractFilterer) (*InonfungibleTokenFilterer, error) { + contract, err := bindInonfungibleToken(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &InonfungibleTokenFilterer{contract: contract}, nil +} + +// bindInonfungibleToken binds a generic wrapper to an already deployed contract. +func bindInonfungibleToken(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := InonfungibleTokenMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_InonfungibleToken *InonfungibleTokenRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _InonfungibleToken.Contract.InonfungibleTokenCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_InonfungibleToken *InonfungibleTokenRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _InonfungibleToken.Contract.InonfungibleTokenTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_InonfungibleToken *InonfungibleTokenRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _InonfungibleToken.Contract.InonfungibleTokenTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_InonfungibleToken *InonfungibleTokenCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _InonfungibleToken.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_InonfungibleToken *InonfungibleTokenTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _InonfungibleToken.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_InonfungibleToken *InonfungibleTokenTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _InonfungibleToken.Contract.contract.Transact(opts, method, params...) +} + +// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. +// +// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) +func (_InonfungibleToken *InonfungibleTokenCaller) DOMAINSEPARATOR(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "DOMAIN_SEPARATOR") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. +// +// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) +func (_InonfungibleToken *InonfungibleTokenSession) DOMAINSEPARATOR() ([32]byte, error) { + return _InonfungibleToken.Contract.DOMAINSEPARATOR(&_InonfungibleToken.CallOpts) +} + +// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. +// +// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) +func (_InonfungibleToken *InonfungibleTokenCallerSession) DOMAINSEPARATOR() ([32]byte, error) { + return _InonfungibleToken.Contract.DOMAINSEPARATOR(&_InonfungibleToken.CallOpts) +} + +// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x30adf81f. +// +// Solidity: function PERMIT_TYPEHASH() pure returns(bytes32) +func (_InonfungibleToken *InonfungibleTokenCaller) PERMITTYPEHASH(opts *bind.CallOpts) ([32]byte, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "PERMIT_TYPEHASH") + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x30adf81f. +// +// Solidity: function PERMIT_TYPEHASH() pure returns(bytes32) +func (_InonfungibleToken *InonfungibleTokenSession) PERMITTYPEHASH() ([32]byte, error) { + return _InonfungibleToken.Contract.PERMITTYPEHASH(&_InonfungibleToken.CallOpts) +} + +// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x30adf81f. +// +// Solidity: function PERMIT_TYPEHASH() pure returns(bytes32) +func (_InonfungibleToken *InonfungibleTokenCallerSession) PERMITTYPEHASH() ([32]byte, error) { + return _InonfungibleToken.Contract.PERMITTYPEHASH(&_InonfungibleToken.CallOpts) +} + +// WETH9 is a free data retrieval call binding the contract method 0x4aa4a4fc. +// +// Solidity: function WETH9() view returns(address) +func (_InonfungibleToken *InonfungibleTokenCaller) WETH9(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "WETH9") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// WETH9 is a free data retrieval call binding the contract method 0x4aa4a4fc. +// +// Solidity: function WETH9() view returns(address) +func (_InonfungibleToken *InonfungibleTokenSession) WETH9() (common.Address, error) { + return _InonfungibleToken.Contract.WETH9(&_InonfungibleToken.CallOpts) +} + +// WETH9 is a free data retrieval call binding the contract method 0x4aa4a4fc. +// +// Solidity: function WETH9() view returns(address) +func (_InonfungibleToken *InonfungibleTokenCallerSession) WETH9() (common.Address, error) { + return _InonfungibleToken.Contract.WETH9(&_InonfungibleToken.CallOpts) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address owner) view returns(uint256 balance) +func (_InonfungibleToken *InonfungibleTokenCaller) BalanceOf(opts *bind.CallOpts, owner common.Address) (*big.Int, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "balanceOf", owner) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address owner) view returns(uint256 balance) +func (_InonfungibleToken *InonfungibleTokenSession) BalanceOf(owner common.Address) (*big.Int, error) { + return _InonfungibleToken.Contract.BalanceOf(&_InonfungibleToken.CallOpts, owner) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address owner) view returns(uint256 balance) +func (_InonfungibleToken *InonfungibleTokenCallerSession) BalanceOf(owner common.Address) (*big.Int, error) { + return _InonfungibleToken.Contract.BalanceOf(&_InonfungibleToken.CallOpts, owner) +} + +// Factory is a free data retrieval call binding the contract method 0xc45a0155. +// +// Solidity: function factory() view returns(address) +func (_InonfungibleToken *InonfungibleTokenCaller) Factory(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "factory") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// Factory is a free data retrieval call binding the contract method 0xc45a0155. +// +// Solidity: function factory() view returns(address) +func (_InonfungibleToken *InonfungibleTokenSession) Factory() (common.Address, error) { + return _InonfungibleToken.Contract.Factory(&_InonfungibleToken.CallOpts) +} + +// Factory is a free data retrieval call binding the contract method 0xc45a0155. +// +// Solidity: function factory() view returns(address) +func (_InonfungibleToken *InonfungibleTokenCallerSession) Factory() (common.Address, error) { + return _InonfungibleToken.Contract.Factory(&_InonfungibleToken.CallOpts) +} + +// GetApproved is a free data retrieval call binding the contract method 0x081812fc. +// +// Solidity: function getApproved(uint256 tokenId) view returns(address operator) +func (_InonfungibleToken *InonfungibleTokenCaller) GetApproved(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "getApproved", tokenId) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// GetApproved is a free data retrieval call binding the contract method 0x081812fc. +// +// Solidity: function getApproved(uint256 tokenId) view returns(address operator) +func (_InonfungibleToken *InonfungibleTokenSession) GetApproved(tokenId *big.Int) (common.Address, error) { + return _InonfungibleToken.Contract.GetApproved(&_InonfungibleToken.CallOpts, tokenId) +} + +// GetApproved is a free data retrieval call binding the contract method 0x081812fc. +// +// Solidity: function getApproved(uint256 tokenId) view returns(address operator) +func (_InonfungibleToken *InonfungibleTokenCallerSession) GetApproved(tokenId *big.Int) (common.Address, error) { + return _InonfungibleToken.Contract.GetApproved(&_InonfungibleToken.CallOpts, tokenId) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_InonfungibleToken *InonfungibleTokenCaller) IsApprovedForAll(opts *bind.CallOpts, owner common.Address, operator common.Address) (bool, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "isApprovedForAll", owner, operator) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_InonfungibleToken *InonfungibleTokenSession) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { + return _InonfungibleToken.Contract.IsApprovedForAll(&_InonfungibleToken.CallOpts, owner, operator) +} + +// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. +// +// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) +func (_InonfungibleToken *InonfungibleTokenCallerSession) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { + return _InonfungibleToken.Contract.IsApprovedForAll(&_InonfungibleToken.CallOpts, owner, operator) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_InonfungibleToken *InonfungibleTokenCaller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "name") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_InonfungibleToken *InonfungibleTokenSession) Name() (string, error) { + return _InonfungibleToken.Contract.Name(&_InonfungibleToken.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_InonfungibleToken *InonfungibleTokenCallerSession) Name() (string, error) { + return _InonfungibleToken.Contract.Name(&_InonfungibleToken.CallOpts) +} + +// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. +// +// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) +func (_InonfungibleToken *InonfungibleTokenCaller) OwnerOf(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "ownerOf", tokenId) + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. +// +// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) +func (_InonfungibleToken *InonfungibleTokenSession) OwnerOf(tokenId *big.Int) (common.Address, error) { + return _InonfungibleToken.Contract.OwnerOf(&_InonfungibleToken.CallOpts, tokenId) +} + +// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. +// +// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) +func (_InonfungibleToken *InonfungibleTokenCallerSession) OwnerOf(tokenId *big.Int) (common.Address, error) { + return _InonfungibleToken.Contract.OwnerOf(&_InonfungibleToken.CallOpts, tokenId) +} + +// Positions is a free data retrieval call binding the contract method 0x99fbab88. +// +// Solidity: function positions(uint256 tokenId) view returns(uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1) +func (_InonfungibleToken *InonfungibleTokenCaller) Positions(opts *bind.CallOpts, tokenId *big.Int) (struct { + Nonce *big.Int + Operator common.Address + Token0 common.Address + Token1 common.Address + Fee *big.Int + TickLower *big.Int + TickUpper *big.Int + Liquidity *big.Int + FeeGrowthInside0LastX128 *big.Int + FeeGrowthInside1LastX128 *big.Int + TokensOwed0 *big.Int + TokensOwed1 *big.Int +}, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "positions", tokenId) + + outstruct := new(struct { + Nonce *big.Int + Operator common.Address + Token0 common.Address + Token1 common.Address + Fee *big.Int + TickLower *big.Int + TickUpper *big.Int + Liquidity *big.Int + FeeGrowthInside0LastX128 *big.Int + FeeGrowthInside1LastX128 *big.Int + TokensOwed0 *big.Int + TokensOwed1 *big.Int + }) + if err != nil { + return *outstruct, err + } + + outstruct.Nonce = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + outstruct.Operator = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) + outstruct.Token0 = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) + outstruct.Token1 = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) + outstruct.Fee = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) + outstruct.TickLower = *abi.ConvertType(out[5], new(*big.Int)).(**big.Int) + outstruct.TickUpper = *abi.ConvertType(out[6], new(*big.Int)).(**big.Int) + outstruct.Liquidity = *abi.ConvertType(out[7], new(*big.Int)).(**big.Int) + outstruct.FeeGrowthInside0LastX128 = *abi.ConvertType(out[8], new(*big.Int)).(**big.Int) + outstruct.FeeGrowthInside1LastX128 = *abi.ConvertType(out[9], new(*big.Int)).(**big.Int) + outstruct.TokensOwed0 = *abi.ConvertType(out[10], new(*big.Int)).(**big.Int) + outstruct.TokensOwed1 = *abi.ConvertType(out[11], new(*big.Int)).(**big.Int) + + return *outstruct, err + +} + +// Positions is a free data retrieval call binding the contract method 0x99fbab88. +// +// Solidity: function positions(uint256 tokenId) view returns(uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1) +func (_InonfungibleToken *InonfungibleTokenSession) Positions(tokenId *big.Int) (struct { + Nonce *big.Int + Operator common.Address + Token0 common.Address + Token1 common.Address + Fee *big.Int + TickLower *big.Int + TickUpper *big.Int + Liquidity *big.Int + FeeGrowthInside0LastX128 *big.Int + FeeGrowthInside1LastX128 *big.Int + TokensOwed0 *big.Int + TokensOwed1 *big.Int +}, error) { + return _InonfungibleToken.Contract.Positions(&_InonfungibleToken.CallOpts, tokenId) +} + +// Positions is a free data retrieval call binding the contract method 0x99fbab88. +// +// Solidity: function positions(uint256 tokenId) view returns(uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1) +func (_InonfungibleToken *InonfungibleTokenCallerSession) Positions(tokenId *big.Int) (struct { + Nonce *big.Int + Operator common.Address + Token0 common.Address + Token1 common.Address + Fee *big.Int + TickLower *big.Int + TickUpper *big.Int + Liquidity *big.Int + FeeGrowthInside0LastX128 *big.Int + FeeGrowthInside1LastX128 *big.Int + TokensOwed0 *big.Int + TokensOwed1 *big.Int +}, error) { + return _InonfungibleToken.Contract.Positions(&_InonfungibleToken.CallOpts, tokenId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_InonfungibleToken *InonfungibleTokenCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "supportsInterface", interfaceId) + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_InonfungibleToken *InonfungibleTokenSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _InonfungibleToken.Contract.SupportsInterface(&_InonfungibleToken.CallOpts, interfaceId) +} + +// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. +// +// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) +func (_InonfungibleToken *InonfungibleTokenCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { + return _InonfungibleToken.Contract.SupportsInterface(&_InonfungibleToken.CallOpts, interfaceId) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_InonfungibleToken *InonfungibleTokenCaller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "symbol") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_InonfungibleToken *InonfungibleTokenSession) Symbol() (string, error) { + return _InonfungibleToken.Contract.Symbol(&_InonfungibleToken.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_InonfungibleToken *InonfungibleTokenCallerSession) Symbol() (string, error) { + return _InonfungibleToken.Contract.Symbol(&_InonfungibleToken.CallOpts) +} + +// TokenByIndex is a free data retrieval call binding the contract method 0x4f6ccce7. +// +// Solidity: function tokenByIndex(uint256 index) view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenCaller) TokenByIndex(opts *bind.CallOpts, index *big.Int) (*big.Int, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "tokenByIndex", index) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TokenByIndex is a free data retrieval call binding the contract method 0x4f6ccce7. +// +// Solidity: function tokenByIndex(uint256 index) view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenSession) TokenByIndex(index *big.Int) (*big.Int, error) { + return _InonfungibleToken.Contract.TokenByIndex(&_InonfungibleToken.CallOpts, index) +} + +// TokenByIndex is a free data retrieval call binding the contract method 0x4f6ccce7. +// +// Solidity: function tokenByIndex(uint256 index) view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenCallerSession) TokenByIndex(index *big.Int) (*big.Int, error) { + return _InonfungibleToken.Contract.TokenByIndex(&_InonfungibleToken.CallOpts, index) +} + +// TokenOfOwnerByIndex is a free data retrieval call binding the contract method 0x2f745c59. +// +// Solidity: function tokenOfOwnerByIndex(address owner, uint256 index) view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenCaller) TokenOfOwnerByIndex(opts *bind.CallOpts, owner common.Address, index *big.Int) (*big.Int, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "tokenOfOwnerByIndex", owner, index) + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TokenOfOwnerByIndex is a free data retrieval call binding the contract method 0x2f745c59. +// +// Solidity: function tokenOfOwnerByIndex(address owner, uint256 index) view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenSession) TokenOfOwnerByIndex(owner common.Address, index *big.Int) (*big.Int, error) { + return _InonfungibleToken.Contract.TokenOfOwnerByIndex(&_InonfungibleToken.CallOpts, owner, index) +} + +// TokenOfOwnerByIndex is a free data retrieval call binding the contract method 0x2f745c59. +// +// Solidity: function tokenOfOwnerByIndex(address owner, uint256 index) view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenCallerSession) TokenOfOwnerByIndex(owner common.Address, index *big.Int) (*big.Int, error) { + return _InonfungibleToken.Contract.TokenOfOwnerByIndex(&_InonfungibleToken.CallOpts, owner, index) +} + +// TokenURI is a free data retrieval call binding the contract method 0xc87b56dd. +// +// Solidity: function tokenURI(uint256 tokenId) view returns(string) +func (_InonfungibleToken *InonfungibleTokenCaller) TokenURI(opts *bind.CallOpts, tokenId *big.Int) (string, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "tokenURI", tokenId) + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +// TokenURI is a free data retrieval call binding the contract method 0xc87b56dd. +// +// Solidity: function tokenURI(uint256 tokenId) view returns(string) +func (_InonfungibleToken *InonfungibleTokenSession) TokenURI(tokenId *big.Int) (string, error) { + return _InonfungibleToken.Contract.TokenURI(&_InonfungibleToken.CallOpts, tokenId) +} + +// TokenURI is a free data retrieval call binding the contract method 0xc87b56dd. +// +// Solidity: function tokenURI(uint256 tokenId) view returns(string) +func (_InonfungibleToken *InonfungibleTokenCallerSession) TokenURI(tokenId *big.Int) (string, error) { + return _InonfungibleToken.Contract.TokenURI(&_InonfungibleToken.CallOpts, tokenId) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _InonfungibleToken.contract.Call(opts, &out, "totalSupply") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenSession) TotalSupply() (*big.Int, error) { + return _InonfungibleToken.Contract.TotalSupply(&_InonfungibleToken.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_InonfungibleToken *InonfungibleTokenCallerSession) TotalSupply() (*big.Int, error) { + return _InonfungibleToken.Contract.TotalSupply(&_InonfungibleToken.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) Approve(opts *bind.TransactOpts, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "approve", to, tokenId) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenSession) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Approve(&_InonfungibleToken.TransactOpts, to, tokenId) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Approve(&_InonfungibleToken.TransactOpts, to, tokenId) +} + +// Burn is a paid mutator transaction binding the contract method 0x42966c68. +// +// Solidity: function burn(uint256 tokenId) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) Burn(opts *bind.TransactOpts, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "burn", tokenId) +} + +// Burn is a paid mutator transaction binding the contract method 0x42966c68. +// +// Solidity: function burn(uint256 tokenId) payable returns() +func (_InonfungibleToken *InonfungibleTokenSession) Burn(tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Burn(&_InonfungibleToken.TransactOpts, tokenId) +} + +// Burn is a paid mutator transaction binding the contract method 0x42966c68. +// +// Solidity: function burn(uint256 tokenId) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) Burn(tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Burn(&_InonfungibleToken.TransactOpts, tokenId) +} + +// Collect is a paid mutator transaction binding the contract method 0xfc6f7865. +// +// Solidity: function collect((uint256,address,uint128,uint128) params) payable returns(uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactor) Collect(opts *bind.TransactOpts, params INonfungiblePositionManagerCollectParams) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "collect", params) +} + +// Collect is a paid mutator transaction binding the contract method 0xfc6f7865. +// +// Solidity: function collect((uint256,address,uint128,uint128) params) payable returns(uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenSession) Collect(params INonfungiblePositionManagerCollectParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Collect(&_InonfungibleToken.TransactOpts, params) +} + +// Collect is a paid mutator transaction binding the contract method 0xfc6f7865. +// +// Solidity: function collect((uint256,address,uint128,uint128) params) payable returns(uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactorSession) Collect(params INonfungiblePositionManagerCollectParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Collect(&_InonfungibleToken.TransactOpts, params) +} + +// CreateAndInitializePoolIfNecessary is a paid mutator transaction binding the contract method 0x13ead562. +// +// Solidity: function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96) payable returns(address pool) +func (_InonfungibleToken *InonfungibleTokenTransactor) CreateAndInitializePoolIfNecessary(opts *bind.TransactOpts, token0 common.Address, token1 common.Address, fee *big.Int, sqrtPriceX96 *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "createAndInitializePoolIfNecessary", token0, token1, fee, sqrtPriceX96) +} + +// CreateAndInitializePoolIfNecessary is a paid mutator transaction binding the contract method 0x13ead562. +// +// Solidity: function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96) payable returns(address pool) +func (_InonfungibleToken *InonfungibleTokenSession) CreateAndInitializePoolIfNecessary(token0 common.Address, token1 common.Address, fee *big.Int, sqrtPriceX96 *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.CreateAndInitializePoolIfNecessary(&_InonfungibleToken.TransactOpts, token0, token1, fee, sqrtPriceX96) +} + +// CreateAndInitializePoolIfNecessary is a paid mutator transaction binding the contract method 0x13ead562. +// +// Solidity: function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96) payable returns(address pool) +func (_InonfungibleToken *InonfungibleTokenTransactorSession) CreateAndInitializePoolIfNecessary(token0 common.Address, token1 common.Address, fee *big.Int, sqrtPriceX96 *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.CreateAndInitializePoolIfNecessary(&_InonfungibleToken.TransactOpts, token0, token1, fee, sqrtPriceX96) +} + +// DecreaseLiquidity is a paid mutator transaction binding the contract method 0x0c49ccbe. +// +// Solidity: function decreaseLiquidity((uint256,uint128,uint256,uint256,uint256) params) payable returns(uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactor) DecreaseLiquidity(opts *bind.TransactOpts, params INonfungiblePositionManagerDecreaseLiquidityParams) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "decreaseLiquidity", params) +} + +// DecreaseLiquidity is a paid mutator transaction binding the contract method 0x0c49ccbe. +// +// Solidity: function decreaseLiquidity((uint256,uint128,uint256,uint256,uint256) params) payable returns(uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenSession) DecreaseLiquidity(params INonfungiblePositionManagerDecreaseLiquidityParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.DecreaseLiquidity(&_InonfungibleToken.TransactOpts, params) +} + +// DecreaseLiquidity is a paid mutator transaction binding the contract method 0x0c49ccbe. +// +// Solidity: function decreaseLiquidity((uint256,uint128,uint256,uint256,uint256) params) payable returns(uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactorSession) DecreaseLiquidity(params INonfungiblePositionManagerDecreaseLiquidityParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.DecreaseLiquidity(&_InonfungibleToken.TransactOpts, params) +} + +// IncreaseLiquidity is a paid mutator transaction binding the contract method 0x219f5d17. +// +// Solidity: function increaseLiquidity((uint256,uint256,uint256,uint256,uint256,uint256) params) payable returns(uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactor) IncreaseLiquidity(opts *bind.TransactOpts, params INonfungiblePositionManagerIncreaseLiquidityParams) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "increaseLiquidity", params) +} + +// IncreaseLiquidity is a paid mutator transaction binding the contract method 0x219f5d17. +// +// Solidity: function increaseLiquidity((uint256,uint256,uint256,uint256,uint256,uint256) params) payable returns(uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenSession) IncreaseLiquidity(params INonfungiblePositionManagerIncreaseLiquidityParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.IncreaseLiquidity(&_InonfungibleToken.TransactOpts, params) +} + +// IncreaseLiquidity is a paid mutator transaction binding the contract method 0x219f5d17. +// +// Solidity: function increaseLiquidity((uint256,uint256,uint256,uint256,uint256,uint256) params) payable returns(uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactorSession) IncreaseLiquidity(params INonfungiblePositionManagerIncreaseLiquidityParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.IncreaseLiquidity(&_InonfungibleToken.TransactOpts, params) +} + +// Mint is a paid mutator transaction binding the contract method 0x88316456. +// +// Solidity: function mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256) params) payable returns(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactor) Mint(opts *bind.TransactOpts, params INonfungiblePositionManagerMintParams) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "mint", params) +} + +// Mint is a paid mutator transaction binding the contract method 0x88316456. +// +// Solidity: function mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256) params) payable returns(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenSession) Mint(params INonfungiblePositionManagerMintParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Mint(&_InonfungibleToken.TransactOpts, params) +} + +// Mint is a paid mutator transaction binding the contract method 0x88316456. +// +// Solidity: function mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256) params) payable returns(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenTransactorSession) Mint(params INonfungiblePositionManagerMintParams) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Mint(&_InonfungibleToken.TransactOpts, params) +} + +// Permit is a paid mutator transaction binding the contract method 0x7ac2ff7b. +// +// Solidity: function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) Permit(opts *bind.TransactOpts, spender common.Address, tokenId *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "permit", spender, tokenId, deadline, v, r, s) +} + +// Permit is a paid mutator transaction binding the contract method 0x7ac2ff7b. +// +// Solidity: function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) payable returns() +func (_InonfungibleToken *InonfungibleTokenSession) Permit(spender common.Address, tokenId *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Permit(&_InonfungibleToken.TransactOpts, spender, tokenId, deadline, v, r, s) +} + +// Permit is a paid mutator transaction binding the contract method 0x7ac2ff7b. +// +// Solidity: function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) Permit(spender common.Address, tokenId *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { + return _InonfungibleToken.Contract.Permit(&_InonfungibleToken.TransactOpts, spender, tokenId, deadline, v, r, s) +} + +// RefundETH is a paid mutator transaction binding the contract method 0x12210e8a. +// +// Solidity: function refundETH() payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) RefundETH(opts *bind.TransactOpts) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "refundETH") +} + +// RefundETH is a paid mutator transaction binding the contract method 0x12210e8a. +// +// Solidity: function refundETH() payable returns() +func (_InonfungibleToken *InonfungibleTokenSession) RefundETH() (*types.Transaction, error) { + return _InonfungibleToken.Contract.RefundETH(&_InonfungibleToken.TransactOpts) +} + +// RefundETH is a paid mutator transaction binding the contract method 0x12210e8a. +// +// Solidity: function refundETH() payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) RefundETH() (*types.Transaction, error) { + return _InonfungibleToken.Contract.RefundETH(&_InonfungibleToken.TransactOpts) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) SafeTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "safeTransferFrom", from, to, tokenId) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenSession) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SafeTransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) +} + +// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SafeTransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) +} + +// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) SafeTransferFrom0(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "safeTransferFrom0", from, to, tokenId, data) +} + +// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() +func (_InonfungibleToken *InonfungibleTokenSession) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SafeTransferFrom0(&_InonfungibleToken.TransactOpts, from, to, tokenId, data) +} + +// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. +// +// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SafeTransferFrom0(&_InonfungibleToken.TransactOpts, from, to, tokenId, data) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool _approved) returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) SetApprovalForAll(opts *bind.TransactOpts, operator common.Address, _approved bool) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "setApprovalForAll", operator, _approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool _approved) returns() +func (_InonfungibleToken *InonfungibleTokenSession) SetApprovalForAll(operator common.Address, _approved bool) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SetApprovalForAll(&_InonfungibleToken.TransactOpts, operator, _approved) +} + +// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. +// +// Solidity: function setApprovalForAll(address operator, bool _approved) returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) SetApprovalForAll(operator common.Address, _approved bool) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SetApprovalForAll(&_InonfungibleToken.TransactOpts, operator, _approved) +} + +// SweepToken is a paid mutator transaction binding the contract method 0xdf2ab5bb. +// +// Solidity: function sweepToken(address token, uint256 amountMinimum, address recipient) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) SweepToken(opts *bind.TransactOpts, token common.Address, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "sweepToken", token, amountMinimum, recipient) +} + +// SweepToken is a paid mutator transaction binding the contract method 0xdf2ab5bb. +// +// Solidity: function sweepToken(address token, uint256 amountMinimum, address recipient) payable returns() +func (_InonfungibleToken *InonfungibleTokenSession) SweepToken(token common.Address, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SweepToken(&_InonfungibleToken.TransactOpts, token, amountMinimum, recipient) +} + +// SweepToken is a paid mutator transaction binding the contract method 0xdf2ab5bb. +// +// Solidity: function sweepToken(address token, uint256 amountMinimum, address recipient) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) SweepToken(token common.Address, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { + return _InonfungibleToken.Contract.SweepToken(&_InonfungibleToken.TransactOpts, token, amountMinimum, recipient) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "transferFrom", from, to, tokenId) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenSession) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.TransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) +} + +// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. +// +// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { + return _InonfungibleToken.Contract.TransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) +} + +// UnwrapWETH9 is a paid mutator transaction binding the contract method 0x49404b7c. +// +// Solidity: function unwrapWETH9(uint256 amountMinimum, address recipient) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactor) UnwrapWETH9(opts *bind.TransactOpts, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { + return _InonfungibleToken.contract.Transact(opts, "unwrapWETH9", amountMinimum, recipient) +} + +// UnwrapWETH9 is a paid mutator transaction binding the contract method 0x49404b7c. +// +// Solidity: function unwrapWETH9(uint256 amountMinimum, address recipient) payable returns() +func (_InonfungibleToken *InonfungibleTokenSession) UnwrapWETH9(amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { + return _InonfungibleToken.Contract.UnwrapWETH9(&_InonfungibleToken.TransactOpts, amountMinimum, recipient) +} + +// UnwrapWETH9 is a paid mutator transaction binding the contract method 0x49404b7c. +// +// Solidity: function unwrapWETH9(uint256 amountMinimum, address recipient) payable returns() +func (_InonfungibleToken *InonfungibleTokenTransactorSession) UnwrapWETH9(amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { + return _InonfungibleToken.Contract.UnwrapWETH9(&_InonfungibleToken.TransactOpts, amountMinimum, recipient) +} + +// InonfungibleTokenApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the InonfungibleToken contract. +type InonfungibleTokenApprovalIterator struct { + Event *InonfungibleTokenApproval // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *InonfungibleTokenApprovalIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenApproval) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *InonfungibleTokenApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *InonfungibleTokenApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// InonfungibleTokenApproval represents a Approval event raised by the InonfungibleToken contract. +type InonfungibleTokenApproval struct { + Owner common.Address + Approved common.Address + TokenId *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) +func (_InonfungibleToken *InonfungibleTokenFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, approved []common.Address, tokenId []*big.Int) (*InonfungibleTokenApprovalIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var approvedRule []interface{} + for _, approvedItem := range approved { + approvedRule = append(approvedRule, approvedItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) + if err != nil { + return nil, err + } + return &InonfungibleTokenApprovalIterator{contract: _InonfungibleToken.contract, event: "Approval", logs: logs, sub: sub}, nil +} + +// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) +func (_InonfungibleToken *InonfungibleTokenFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenApproval, owner []common.Address, approved []common.Address, tokenId []*big.Int) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var approvedRule []interface{} + for _, approvedItem := range approved { + approvedRule = append(approvedRule, approvedItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(InonfungibleTokenApproval) + if err := _InonfungibleToken.contract.UnpackLog(event, "Approval", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. +// +// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) +func (_InonfungibleToken *InonfungibleTokenFilterer) ParseApproval(log types.Log) (*InonfungibleTokenApproval, error) { + event := new(InonfungibleTokenApproval) + if err := _InonfungibleToken.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// InonfungibleTokenApprovalForAllIterator is returned from FilterApprovalForAll and is used to iterate over the raw logs and unpacked data for ApprovalForAll events raised by the InonfungibleToken contract. +type InonfungibleTokenApprovalForAllIterator struct { + Event *InonfungibleTokenApprovalForAll // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *InonfungibleTokenApprovalForAllIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenApprovalForAll) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *InonfungibleTokenApprovalForAllIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *InonfungibleTokenApprovalForAllIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// InonfungibleTokenApprovalForAll represents a ApprovalForAll event raised by the InonfungibleToken contract. +type InonfungibleTokenApprovalForAll struct { + Owner common.Address + Operator common.Address + Approved bool + Raw types.Log // Blockchain specific contextual infos +} + +// FilterApprovalForAll is a free log retrieval operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) +func (_InonfungibleToken *InonfungibleTokenFilterer) FilterApprovalForAll(opts *bind.FilterOpts, owner []common.Address, operator []common.Address) (*InonfungibleTokenApprovalForAllIterator, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "ApprovalForAll", ownerRule, operatorRule) + if err != nil { + return nil, err + } + return &InonfungibleTokenApprovalForAllIterator{contract: _InonfungibleToken.contract, event: "ApprovalForAll", logs: logs, sub: sub}, nil +} + +// WatchApprovalForAll is a free log subscription operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) +func (_InonfungibleToken *InonfungibleTokenFilterer) WatchApprovalForAll(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenApprovalForAll, owner []common.Address, operator []common.Address) (event.Subscription, error) { + + var ownerRule []interface{} + for _, ownerItem := range owner { + ownerRule = append(ownerRule, ownerItem) + } + var operatorRule []interface{} + for _, operatorItem := range operator { + operatorRule = append(operatorRule, operatorItem) + } + + logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "ApprovalForAll", ownerRule, operatorRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(InonfungibleTokenApprovalForAll) + if err := _InonfungibleToken.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseApprovalForAll is a log parse operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. +// +// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) +func (_InonfungibleToken *InonfungibleTokenFilterer) ParseApprovalForAll(log types.Log) (*InonfungibleTokenApprovalForAll, error) { + event := new(InonfungibleTokenApprovalForAll) + if err := _InonfungibleToken.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// InonfungibleTokenCollectIterator is returned from FilterCollect and is used to iterate over the raw logs and unpacked data for Collect events raised by the InonfungibleToken contract. +type InonfungibleTokenCollectIterator struct { + Event *InonfungibleTokenCollect // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *InonfungibleTokenCollectIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenCollect) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenCollect) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *InonfungibleTokenCollectIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *InonfungibleTokenCollectIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// InonfungibleTokenCollect represents a Collect event raised by the InonfungibleToken contract. +type InonfungibleTokenCollect struct { + TokenId *big.Int + Recipient common.Address + Amount0 *big.Int + Amount1 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterCollect is a free log retrieval operation binding the contract event 0x40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f01. +// +// Solidity: event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) FilterCollect(opts *bind.FilterOpts, tokenId []*big.Int) (*InonfungibleTokenCollectIterator, error) { + + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "Collect", tokenIdRule) + if err != nil { + return nil, err + } + return &InonfungibleTokenCollectIterator{contract: _InonfungibleToken.contract, event: "Collect", logs: logs, sub: sub}, nil +} + +// WatchCollect is a free log subscription operation binding the contract event 0x40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f01. +// +// Solidity: event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) WatchCollect(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenCollect, tokenId []*big.Int) (event.Subscription, error) { + + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "Collect", tokenIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(InonfungibleTokenCollect) + if err := _InonfungibleToken.contract.UnpackLog(event, "Collect", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseCollect is a log parse operation binding the contract event 0x40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f01. +// +// Solidity: event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) ParseCollect(log types.Log) (*InonfungibleTokenCollect, error) { + event := new(InonfungibleTokenCollect) + if err := _InonfungibleToken.contract.UnpackLog(event, "Collect", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// InonfungibleTokenDecreaseLiquidityIterator is returned from FilterDecreaseLiquidity and is used to iterate over the raw logs and unpacked data for DecreaseLiquidity events raised by the InonfungibleToken contract. +type InonfungibleTokenDecreaseLiquidityIterator struct { + Event *InonfungibleTokenDecreaseLiquidity // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *InonfungibleTokenDecreaseLiquidityIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenDecreaseLiquidity) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenDecreaseLiquidity) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *InonfungibleTokenDecreaseLiquidityIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *InonfungibleTokenDecreaseLiquidityIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// InonfungibleTokenDecreaseLiquidity represents a DecreaseLiquidity event raised by the InonfungibleToken contract. +type InonfungibleTokenDecreaseLiquidity struct { + TokenId *big.Int + Liquidity *big.Int + Amount0 *big.Int + Amount1 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterDecreaseLiquidity is a free log retrieval operation binding the contract event 0x26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b4. +// +// Solidity: event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) FilterDecreaseLiquidity(opts *bind.FilterOpts, tokenId []*big.Int) (*InonfungibleTokenDecreaseLiquidityIterator, error) { + + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "DecreaseLiquidity", tokenIdRule) + if err != nil { + return nil, err + } + return &InonfungibleTokenDecreaseLiquidityIterator{contract: _InonfungibleToken.contract, event: "DecreaseLiquidity", logs: logs, sub: sub}, nil +} + +// WatchDecreaseLiquidity is a free log subscription operation binding the contract event 0x26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b4. +// +// Solidity: event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) WatchDecreaseLiquidity(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenDecreaseLiquidity, tokenId []*big.Int) (event.Subscription, error) { + + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "DecreaseLiquidity", tokenIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(InonfungibleTokenDecreaseLiquidity) + if err := _InonfungibleToken.contract.UnpackLog(event, "DecreaseLiquidity", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseDecreaseLiquidity is a log parse operation binding the contract event 0x26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b4. +// +// Solidity: event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) ParseDecreaseLiquidity(log types.Log) (*InonfungibleTokenDecreaseLiquidity, error) { + event := new(InonfungibleTokenDecreaseLiquidity) + if err := _InonfungibleToken.contract.UnpackLog(event, "DecreaseLiquidity", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// InonfungibleTokenIncreaseLiquidityIterator is returned from FilterIncreaseLiquidity and is used to iterate over the raw logs and unpacked data for IncreaseLiquidity events raised by the InonfungibleToken contract. +type InonfungibleTokenIncreaseLiquidityIterator struct { + Event *InonfungibleTokenIncreaseLiquidity // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *InonfungibleTokenIncreaseLiquidityIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenIncreaseLiquidity) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenIncreaseLiquidity) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *InonfungibleTokenIncreaseLiquidityIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *InonfungibleTokenIncreaseLiquidityIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// InonfungibleTokenIncreaseLiquidity represents a IncreaseLiquidity event raised by the InonfungibleToken contract. +type InonfungibleTokenIncreaseLiquidity struct { + TokenId *big.Int + Liquidity *big.Int + Amount0 *big.Int + Amount1 *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterIncreaseLiquidity is a free log retrieval operation binding the contract event 0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f. +// +// Solidity: event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) FilterIncreaseLiquidity(opts *bind.FilterOpts, tokenId []*big.Int) (*InonfungibleTokenIncreaseLiquidityIterator, error) { + + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "IncreaseLiquidity", tokenIdRule) + if err != nil { + return nil, err + } + return &InonfungibleTokenIncreaseLiquidityIterator{contract: _InonfungibleToken.contract, event: "IncreaseLiquidity", logs: logs, sub: sub}, nil +} + +// WatchIncreaseLiquidity is a free log subscription operation binding the contract event 0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f. +// +// Solidity: event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) WatchIncreaseLiquidity(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenIncreaseLiquidity, tokenId []*big.Int) (event.Subscription, error) { + + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "IncreaseLiquidity", tokenIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(InonfungibleTokenIncreaseLiquidity) + if err := _InonfungibleToken.contract.UnpackLog(event, "IncreaseLiquidity", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseIncreaseLiquidity is a log parse operation binding the contract event 0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f. +// +// Solidity: event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) +func (_InonfungibleToken *InonfungibleTokenFilterer) ParseIncreaseLiquidity(log types.Log) (*InonfungibleTokenIncreaseLiquidity, error) { + event := new(InonfungibleTokenIncreaseLiquidity) + if err := _InonfungibleToken.contract.UnpackLog(event, "IncreaseLiquidity", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// InonfungibleTokenTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the InonfungibleToken contract. +type InonfungibleTokenTransferIterator struct { + Event *InonfungibleTokenTransfer // Event containing the contract specifics and raw log + + contract *bind.BoundContract // Generic contract to use for unpacking event data + event string // Event name to use for unpacking event data + + logs chan types.Log // Log channel receiving the found contract events + sub ethereum.Subscription // Subscription for errors, completion and termination + done bool // Whether the subscription completed delivering logs + fail error // Occurred error to stop iteration +} + +// Next advances the iterator to the subsequent event, returning whether there +// are any more events found. In case of a retrieval or parsing error, false is +// returned and Error() can be queried for the exact failure. +func (it *InonfungibleTokenTransferIterator) Next() bool { + // If the iterator failed, stop iterating + if it.fail != nil { + return false + } + // If the iterator completed, deliver directly whatever's available + if it.done { + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + // Iterator still in progress, wait for either a data or an error event + select { + case log := <-it.logs: + it.Event = new(InonfungibleTokenTransfer) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +// Error returns any retrieval or parsing error occurred during filtering. +func (it *InonfungibleTokenTransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *InonfungibleTokenTransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// InonfungibleTokenTransfer represents a Transfer event raised by the InonfungibleToken contract. +type InonfungibleTokenTransfer struct { + From common.Address + To common.Address + TokenId *big.Int + Raw types.Log // Blockchain specific contextual infos +} + +// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) +func (_InonfungibleToken *InonfungibleTokenFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address, tokenId []*big.Int) (*InonfungibleTokenTransferIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) + if err != nil { + return nil, err + } + return &InonfungibleTokenTransferIterator{contract: _InonfungibleToken.contract, event: "Transfer", logs: logs, sub: sub}, nil +} + +// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) +func (_InonfungibleToken *InonfungibleTokenFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenTransfer, from []common.Address, to []common.Address, tokenId []*big.Int) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + var tokenIdRule []interface{} + for _, tokenIdItem := range tokenId { + tokenIdRule = append(tokenIdRule, tokenIdItem) + } + + logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + // New log arrived, parse the event and forward to the user + event := new(InonfungibleTokenTransfer) + if err := _InonfungibleToken.contract.UnpackLog(event, "Transfer", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. +// +// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) +func (_InonfungibleToken *InonfungibleTokenFilterer) ParseTransfer(log types.Log) (*InonfungibleTokenTransfer, error) { + event := new(InonfungibleTokenTransfer) + if err := _InonfungibleToken.contract.UnpackLog(event, "Transfer", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} diff --git a/relayer/chains/bitcoin/abi/iswap_router.go b/relayer/chains/bitcoin/abi/iswap_router.go new file mode 100644 index 00000000..6fdd712f --- /dev/null +++ b/relayer/chains/bitcoin/abi/iswap_router.go @@ -0,0 +1,328 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package abi + +import ( + "errors" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "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/event" +) + +// Reference imports to suppress errors if they are not otherwise used. +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +// ISwapRouterExactInputParams is an auto generated low-level Go binding around an user-defined struct. +type ISwapRouterExactInputParams struct { + Path []byte + Recipient common.Address + Deadline *big.Int + AmountIn *big.Int + AmountOutMinimum *big.Int +} + +// ISwapRouterExactInputSingleParams is an auto generated low-level Go binding around an user-defined struct. +type ISwapRouterExactInputSingleParams struct { + TokenIn common.Address + TokenOut common.Address + Fee *big.Int + Recipient common.Address + Deadline *big.Int + AmountIn *big.Int + AmountOutMinimum *big.Int + SqrtPriceLimitX96 *big.Int +} + +// ISwapRouterExactOutputParams is an auto generated low-level Go binding around an user-defined struct. +type ISwapRouterExactOutputParams struct { + Path []byte + Recipient common.Address + Deadline *big.Int + AmountOut *big.Int + AmountInMaximum *big.Int +} + +// ISwapRouterExactOutputSingleParams is an auto generated low-level Go binding around an user-defined struct. +type ISwapRouterExactOutputSingleParams struct { + TokenIn common.Address + TokenOut common.Address + Fee *big.Int + Recipient common.Address + Deadline *big.Int + AmountOut *big.Int + AmountInMaximum *big.Int + SqrtPriceLimitX96 *big.Int +} + +// IswaprouterMetaData contains all meta data concerning the Iswaprouter contract. +var IswaprouterMetaData = &bind.MetaData{ + ABI: "[{\"type\":\"function\",\"name\":\"exactInput\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactInputParams\",\"components\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOutMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"exactInputSingle\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactInputSingleParams\",\"components\":[{\"name\":\"tokenIn\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenOut\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOutMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\",\"internalType\":\"uint160\"}]}],\"outputs\":[{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"exactOutput\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactOutputParams\",\"components\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountInMaximum\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"exactOutputSingle\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactOutputSingleParams\",\"components\":[{\"name\":\"tokenIn\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenOut\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountInMaximum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\",\"internalType\":\"uint160\"}]}],\"outputs\":[{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"uniswapV3SwapCallback\",\"inputs\":[{\"name\":\"amount0Delta\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"amount1Delta\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"}]", +} + +// IswaprouterABI is the input ABI used to generate the binding from. +// Deprecated: Use IswaprouterMetaData.ABI instead. +var IswaprouterABI = IswaprouterMetaData.ABI + +// Iswaprouter is an auto generated Go binding around an Ethereum contract. +type Iswaprouter struct { + IswaprouterCaller // Read-only binding to the contract + IswaprouterTransactor // Write-only binding to the contract + IswaprouterFilterer // Log filterer for contract events +} + +// IswaprouterCaller is an auto generated read-only Go binding around an Ethereum contract. +type IswaprouterCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IswaprouterTransactor is an auto generated write-only Go binding around an Ethereum contract. +type IswaprouterTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IswaprouterFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type IswaprouterFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// IswaprouterSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type IswaprouterSession struct { + Contract *Iswaprouter // Generic contract binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IswaprouterCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type IswaprouterCallerSession struct { + Contract *IswaprouterCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// IswaprouterTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type IswaprouterTransactorSession struct { + Contract *IswaprouterTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// IswaprouterRaw is an auto generated low-level Go binding around an Ethereum contract. +type IswaprouterRaw struct { + Contract *Iswaprouter // Generic contract binding to access the raw methods on +} + +// IswaprouterCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type IswaprouterCallerRaw struct { + Contract *IswaprouterCaller // Generic read-only contract binding to access the raw methods on +} + +// IswaprouterTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type IswaprouterTransactorRaw struct { + Contract *IswaprouterTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewIswaprouter creates a new instance of Iswaprouter, bound to a specific deployed contract. +func NewIswaprouter(address common.Address, backend bind.ContractBackend) (*Iswaprouter, error) { + contract, err := bindIswaprouter(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Iswaprouter{IswaprouterCaller: IswaprouterCaller{contract: contract}, IswaprouterTransactor: IswaprouterTransactor{contract: contract}, IswaprouterFilterer: IswaprouterFilterer{contract: contract}}, nil +} + +// NewIswaprouterCaller creates a new read-only instance of Iswaprouter, bound to a specific deployed contract. +func NewIswaprouterCaller(address common.Address, caller bind.ContractCaller) (*IswaprouterCaller, error) { + contract, err := bindIswaprouter(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &IswaprouterCaller{contract: contract}, nil +} + +// NewIswaprouterTransactor creates a new write-only instance of Iswaprouter, bound to a specific deployed contract. +func NewIswaprouterTransactor(address common.Address, transactor bind.ContractTransactor) (*IswaprouterTransactor, error) { + contract, err := bindIswaprouter(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &IswaprouterTransactor{contract: contract}, nil +} + +// NewIswaprouterFilterer creates a new log filterer instance of Iswaprouter, bound to a specific deployed contract. +func NewIswaprouterFilterer(address common.Address, filterer bind.ContractFilterer) (*IswaprouterFilterer, error) { + contract, err := bindIswaprouter(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &IswaprouterFilterer{contract: contract}, nil +} + +// bindIswaprouter binds a generic wrapper to an already deployed contract. +func bindIswaprouter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := IswaprouterMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Iswaprouter *IswaprouterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Iswaprouter.Contract.IswaprouterCaller.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Iswaprouter *IswaprouterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Iswaprouter.Contract.IswaprouterTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Iswaprouter *IswaprouterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Iswaprouter.Contract.IswaprouterTransactor.contract.Transact(opts, method, params...) +} + +// Call invokes the (constant) contract method with params as input values and +// sets the output to result. The result type might be a single field for simple +// returns, a slice of interfaces for anonymous returns and a struct for named +// returns. +func (_Iswaprouter *IswaprouterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Iswaprouter.Contract.contract.Call(opts, result, method, params...) +} + +// Transfer initiates a plain transaction to move funds to the contract, calling +// its default method if one is available. +func (_Iswaprouter *IswaprouterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Iswaprouter.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Iswaprouter *IswaprouterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Iswaprouter.Contract.contract.Transact(opts, method, params...) +} + +// ExactInput is a paid mutator transaction binding the contract method 0xc04b8d59. +// +// Solidity: function exactInput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountOut) +func (_Iswaprouter *IswaprouterTransactor) ExactInput(opts *bind.TransactOpts, params ISwapRouterExactInputParams) (*types.Transaction, error) { + return _Iswaprouter.contract.Transact(opts, "exactInput", params) +} + +// ExactInput is a paid mutator transaction binding the contract method 0xc04b8d59. +// +// Solidity: function exactInput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountOut) +func (_Iswaprouter *IswaprouterSession) ExactInput(params ISwapRouterExactInputParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactInput(&_Iswaprouter.TransactOpts, params) +} + +// ExactInput is a paid mutator transaction binding the contract method 0xc04b8d59. +// +// Solidity: function exactInput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountOut) +func (_Iswaprouter *IswaprouterTransactorSession) ExactInput(params ISwapRouterExactInputParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactInput(&_Iswaprouter.TransactOpts, params) +} + +// ExactInputSingle is a paid mutator transaction binding the contract method 0x414bf389. +// +// Solidity: function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountOut) +func (_Iswaprouter *IswaprouterTransactor) ExactInputSingle(opts *bind.TransactOpts, params ISwapRouterExactInputSingleParams) (*types.Transaction, error) { + return _Iswaprouter.contract.Transact(opts, "exactInputSingle", params) +} + +// ExactInputSingle is a paid mutator transaction binding the contract method 0x414bf389. +// +// Solidity: function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountOut) +func (_Iswaprouter *IswaprouterSession) ExactInputSingle(params ISwapRouterExactInputSingleParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactInputSingle(&_Iswaprouter.TransactOpts, params) +} + +// ExactInputSingle is a paid mutator transaction binding the contract method 0x414bf389. +// +// Solidity: function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountOut) +func (_Iswaprouter *IswaprouterTransactorSession) ExactInputSingle(params ISwapRouterExactInputSingleParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactInputSingle(&_Iswaprouter.TransactOpts, params) +} + +// ExactOutput is a paid mutator transaction binding the contract method 0xf28c0498. +// +// Solidity: function exactOutput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountIn) +func (_Iswaprouter *IswaprouterTransactor) ExactOutput(opts *bind.TransactOpts, params ISwapRouterExactOutputParams) (*types.Transaction, error) { + return _Iswaprouter.contract.Transact(opts, "exactOutput", params) +} + +// ExactOutput is a paid mutator transaction binding the contract method 0xf28c0498. +// +// Solidity: function exactOutput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountIn) +func (_Iswaprouter *IswaprouterSession) ExactOutput(params ISwapRouterExactOutputParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactOutput(&_Iswaprouter.TransactOpts, params) +} + +// ExactOutput is a paid mutator transaction binding the contract method 0xf28c0498. +// +// Solidity: function exactOutput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountIn) +func (_Iswaprouter *IswaprouterTransactorSession) ExactOutput(params ISwapRouterExactOutputParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactOutput(&_Iswaprouter.TransactOpts, params) +} + +// ExactOutputSingle is a paid mutator transaction binding the contract method 0xdb3e2198. +// +// Solidity: function exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountIn) +func (_Iswaprouter *IswaprouterTransactor) ExactOutputSingle(opts *bind.TransactOpts, params ISwapRouterExactOutputSingleParams) (*types.Transaction, error) { + return _Iswaprouter.contract.Transact(opts, "exactOutputSingle", params) +} + +// ExactOutputSingle is a paid mutator transaction binding the contract method 0xdb3e2198. +// +// Solidity: function exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountIn) +func (_Iswaprouter *IswaprouterSession) ExactOutputSingle(params ISwapRouterExactOutputSingleParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactOutputSingle(&_Iswaprouter.TransactOpts, params) +} + +// ExactOutputSingle is a paid mutator transaction binding the contract method 0xdb3e2198. +// +// Solidity: function exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountIn) +func (_Iswaprouter *IswaprouterTransactorSession) ExactOutputSingle(params ISwapRouterExactOutputSingleParams) (*types.Transaction, error) { + return _Iswaprouter.Contract.ExactOutputSingle(&_Iswaprouter.TransactOpts, params) +} + +// UniswapV3SwapCallback is a paid mutator transaction binding the contract method 0xfa461e33. +// +// Solidity: function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes data) returns() +func (_Iswaprouter *IswaprouterTransactor) UniswapV3SwapCallback(opts *bind.TransactOpts, amount0Delta *big.Int, amount1Delta *big.Int, data []byte) (*types.Transaction, error) { + return _Iswaprouter.contract.Transact(opts, "uniswapV3SwapCallback", amount0Delta, amount1Delta, data) +} + +// UniswapV3SwapCallback is a paid mutator transaction binding the contract method 0xfa461e33. +// +// Solidity: function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes data) returns() +func (_Iswaprouter *IswaprouterSession) UniswapV3SwapCallback(amount0Delta *big.Int, amount1Delta *big.Int, data []byte) (*types.Transaction, error) { + return _Iswaprouter.Contract.UniswapV3SwapCallback(&_Iswaprouter.TransactOpts, amount0Delta, amount1Delta, data) +} + +// UniswapV3SwapCallback is a paid mutator transaction binding the contract method 0xfa461e33. +// +// Solidity: function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes data) returns() +func (_Iswaprouter *IswaprouterTransactorSession) UniswapV3SwapCallback(amount0Delta *big.Int, amount1Delta *big.Int, data []byte) (*types.Transaction, error) { + return _Iswaprouter.Contract.UniswapV3SwapCallback(&_Iswaprouter.TransactOpts, amount0Delta, amount1Delta, data) +} diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index 674240e3..879ca89b 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -1,44 +1,50 @@ package bitcoin import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "strconv" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strconv" ) func GetRuneTxIndex(endpoint, method, bearToken, txId string, index int) (*RuneTxIndexResponse, error) { - client := &http.Client{} - endpoint = endpoint + "/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" - fmt.Println(endpoint) - req, err := http.NewRequest(method, endpoint, nil) - - if err != nil { - fmt.Println(err) - return nil, err - } - req.Header.Add("Authorization", bearToken) - - res, err := client.Do(req) - if err != nil { - fmt.Println(err) - return nil, err - } - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - fmt.Println(err) - return nil, err - } - - var resp *RuneTxIndexResponse - err = json.Unmarshal(body, &resp) - if err != nil { - fmt.Println(err) - return nil, err - } - - return resp, nil + client := &http.Client{} + endpoint = endpoint + "/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" + fmt.Println(endpoint) + req, err := http.NewRequest(method, endpoint, nil) + + if err != nil { + fmt.Println(err) + return nil, err + } + req.Header.Add("Authorization", bearToken) + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return nil, err + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return nil, err + } + + var resp *RuneTxIndexResponse + err = json.Unmarshal(body, &resp) + if err != nil { + fmt.Println(err) + return nil, err + } + + return resp, nil +} + +func ConvertBtcMessageToXCallMessage() ([]byte, error) { + // get message + + return nil, nil } diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index cd7b7ecd..c92b294a 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -1,45 +1,56 @@ package bitcoin import ( - "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/wire" +) + +type Action int + +const ( + AddLiquidity Action = iota + Swap + WithdrawLiquidity + CollectFee + IncreaseLiquidity + DecreaseLiquidity ) type TxSearchParam struct { - StartHeight, EndHeight uint64 - BitcoinScript []byte - OPReturnPrefix int + StartHeight, EndHeight uint64 + BitcoinScript []byte + OPReturnPrefix int } type TxSearchRes struct { - Tx *wire.MsgTx - Height uint64 + Tx *wire.MsgTx + Height uint64 } // HightRange is a struct to represent a range of heights type HeightRange struct { - Start uint64 - End uint64 + Start uint64 + End uint64 } type XCallMessage struct { - Action string - TokenAddress string - From string - To string - Amount []byte - Data []byte + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte } type RuneInfo struct { - Rune string `json:"rune"` - RuneId string `json:"runeId"` - SpaceRune string `json:"spaceRune"` - Amount string `json:"amount"` - Symbol string `json:"symbol"` - Divisibility int `json:"divisibility"` + Rune string `json:"rune"` + RuneId string `json:"runeId"` + SpaceRune string `json:"spaceRune"` + Amount string `json:"amount"` + Symbol string `json:"symbol"` + Divisibility int `json:"divisibility"` } type RuneTxIndexResponse struct { - Code int `json:"code"` - Data []RuneInfo `json:"data"` + Code int `json:"code"` + Data []RuneInfo `json:"data"` } From 1367c441a62727e8c9e20de66b33717f05b0bf1c Mon Sep 17 00:00:00 2001 From: homelander Date: Fri, 9 Aug 2024 15:37:41 +0700 Subject: [PATCH 042/113] converted to xcall message --- relayer/chains/bitcoin/decode_test.go | 38 ++++++ relayer/chains/bitcoin/helper.go | 188 ++++++++++++++++++++------ relayer/chains/bitcoin/types.go | 77 +++++++---- 3 files changed, 234 insertions(+), 69 deletions(-) diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index 452d14a1..b26b34f3 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -3,11 +3,14 @@ package bitcoin import ( "encoding/hex" "fmt" + "github.com/ethereum/go-ethereum/common" + "github.com/icon-project/centralized-relay/utils/multisig" "log" "os" "testing" "github.com/icon-project/icon-bridge/common/codec" + "github.com/stretchr/testify/assert" ) func TestDecode(t *testing.T) { @@ -30,3 +33,38 @@ func TestGetRuneBalanceAtIndex(t *testing.T) { fmt.Printf("%+v", res) } + +func TestEncodeToXcallMessage(t *testing.T) { + // + test1 := multisig.RadFiProvideLiquidityMsg{ + Fee: 30, + UpperTick: -173940, + LowerTick: -178320, + Min0: 0, + Min1: 0, + } + + protocols := []string{ + "0x932e088453515720B8eD50c1999C4Bc7bc11991F", + "0x526C5Bcd376FAD738780e099E9723A62044D0319", + } + + res, err := ToXCallMessage( + test1, + "0x3.BTC/bc1qvqkshkdj67uwvlwschyq8wja6df4juhewkg5fg", + "0x2a68F967bFA230780a385175d0c86AE4048d3096", + 2, + protocols, + common.HexToAddress("0x000013938B55EDFBF3380656CC321770cCF470E1"), + common.HexToAddress("0x66f2A9220C8479d73eE84df0932f38C496e8E9e3"), + common.HexToAddress("0x7a4a1aF7B59c5FF522D5F11336d5b20d5116c7cb"), + ) + if err != nil { + log.Fatal(err.Error()) + } + + resReadable := hex.EncodeToString(res) + fmt.Printf("%+v", resReadable) + + assert.Equal(t, resReadable, "f902a201b9029ef9029bb23078332e4254432f6263317176716b73686b646a36377577766c77736368797138776a61366466346a756865776b67356667aa3078326136384639363762464132333037383061333835313735643063383641453430343864333039360200b901e0000000000000000000000000000013938b55edfbf3380656cc321770ccf470e1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001648831645600000000000000000000000066f2a9220c8479d73ee84df0932f38c496e8e9e30000000000000000000000007a4a1af7b59c5ff522d5f11336d5b20d5116c7cb0000000000000000000000000000000000000000000000000000000000000bb8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4770fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd588c0000000000000000000000000000000000000000000fb768105935a2f1a5b649000000000000000000000000000000000000000000000000077cf984c325302e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68f967bfa230780a385175d0c86ae4048d3096000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000f856aa307839333265303838343533353135373230423865443530633139393943344263376263313139393146aa307835323643354263643337364641443733383738306530393945393732334136323034344430333139") +} diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index 879ca89b..7a09e70a 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -1,50 +1,158 @@ package bitcoin import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "strconv" + "encoding/json" + "fmt" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "io/ioutil" + "math/big" + "net/http" + "strconv" + "strings" + + bitcoinABI "github.com/icon-project/centralized-relay/relayer/chains/bitcoin/abi" + "github.com/icon-project/centralized-relay/utils/multisig" + "github.com/icon-project/icon-bridge/common/codec" ) func GetRuneTxIndex(endpoint, method, bearToken, txId string, index int) (*RuneTxIndexResponse, error) { - client := &http.Client{} - endpoint = endpoint + "/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" - fmt.Println(endpoint) - req, err := http.NewRequest(method, endpoint, nil) - - if err != nil { - fmt.Println(err) - return nil, err - } - req.Header.Add("Authorization", bearToken) - - res, err := client.Do(req) - if err != nil { - fmt.Println(err) - return nil, err - } - defer res.Body.Close() - - body, err := ioutil.ReadAll(res.Body) - if err != nil { - fmt.Println(err) - return nil, err - } - - var resp *RuneTxIndexResponse - err = json.Unmarshal(body, &resp) - if err != nil { - fmt.Println(err) - return nil, err - } - - return resp, nil + client := &http.Client{} + endpoint = endpoint + "/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" + fmt.Println(endpoint) + req, err := http.NewRequest(method, endpoint, nil) + + if err != nil { + fmt.Println(err) + return nil, err + } + req.Header.Add("Authorization", bearToken) + + res, err := client.Do(req) + if err != nil { + fmt.Println(err) + return nil, err + } + defer res.Body.Close() + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + fmt.Println(err) + return nil, err + } + + var resp *RuneTxIndexResponse + err = json.Unmarshal(body, &resp) + if err != nil { + fmt.Println(err) + return nil, err + } + + return resp, nil } -func ConvertBtcMessageToXCallMessage() ([]byte, error) { - // get message +func ToXCallMessage(data interface{}, from, to string, sn uint, protocols []string, requester, token0, token1 common.Address) ([]byte, error) { + var res []byte + + //bitcoinStateAbi, _ := abi.JSON(strings.NewReader(bitcoinABI.BitcoinStateMetaData.ABI)) + nonfungibleABI, _ := abi.JSON(strings.NewReader(bitcoinABI.InonfungibleTokenMetaData.ABI)) + addressTy, _ := abi.NewType("address", "", nil) + bytes, _ := abi.NewType("bytes", "", nil) + + arguments := abi.Arguments{ + { + Type: addressTy, + }, + { + Type: bytes, + }, + } + + amount0, _ := big.NewInt(0).SetString("18999999999999999977305673", 10) + + switch data.(type) { + case multisig.RadFiProvideLiquidityMsg: + dataMint := data.(multisig.RadFiProvideLiquidityMsg) + mintParams := bitcoinABI.INonfungiblePositionManagerMintParams{ + Token0: token0, + Token1: token1, + Fee: big.NewInt(int64(dataMint.Fee) * 100), + TickLower: big.NewInt(int64(dataMint.LowerTick)), + TickUpper: big.NewInt(int64(dataMint.UpperTick)), + Amount0Desired: amount0, + Amount1Desired: big.NewInt(539580403982610478), + Recipient: common.HexToAddress(to), + Deadline: big.NewInt(1000000000), + } + + mintParams.Amount0Min = mulDiv(mintParams.Amount0Desired, big.NewInt(int64(dataMint.Min0)), big.NewInt(1e4)) + mintParams.Amount1Min = mulDiv(mintParams.Amount1Desired, big.NewInt(int64(dataMint.Min1)), big.NewInt(1e4)) + + // encode + // todo: for init pool + //initPoolCalldata, err := bitcoinStateAbi.Pack("initPool", mintParams, "btc", "rad", 1e0) + //if err != nil { + // return nil, err + //} + + provideLiquidity, err := nonfungibleABI.Pack("mint", mintParams) + if err != nil { + return nil, err + } + + // encode with requester + provideLiquidity, err = arguments.Pack(requester, provideLiquidity) + if err != nil { + return nil, err + } + + //from := "0x3.BTC/bc1qvqkshkdj67uwvlwschyq8wja6df4juhewkg5fg" + + // encode to xcall format + res, err = XcallFormat(provideLiquidity, from, to, sn, protocols) + if err != nil { + return nil, err + } + + case multisig.RadFiWithdrawLiquidityMsg: + + default: + return nil, fmt.Errorf("not supported") + } + return res, nil +} + +func XcallFormat(callData []byte, from, to string, sn uint, protocols []string) ([]byte, error) { + // + csV2 := CSMessageRequestV2{ + From: from, + To: to, + Sn: big.NewInt(int64(sn)).Bytes(), + MessageType: uint8(CALL_MESSAGE_TYPE), + Data: callData, + Protocols: protocols, + } + + // + cvV2EncodeMsg, err := codec.RLP.MarshalToBytes(csV2) + if err != nil { + return nil, err + } + + message := CSMessage{ + MsgType: big.NewInt(int64(CS_REQUEST)).Bytes(), + Payload: cvV2EncodeMsg, + } + + // + finalMessage, err := codec.RLP.MarshalToBytes(message) + if err != nil { + return nil, err + } + + return finalMessage, nil +} - return nil, nil +func mulDiv(a, nNumerator, nDenominator *big.Int) *big.Int { + return big.NewInt(0).Div(big.NewInt(0).Mul(a, nNumerator), nDenominator) } diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index c92b294a..eddb0d35 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -1,56 +1,75 @@ package bitcoin import ( - "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcd/wire" ) -type Action int +type MessageType int const ( - AddLiquidity Action = iota - Swap - WithdrawLiquidity - CollectFee - IncreaseLiquidity - DecreaseLiquidity + CS_REQUEST MessageType = iota + 1 + CS_RESPONSE + CS_RESULT +) + +type CallMessageType int + +const ( + CALL_MESSAGE_TYPE MessageType = iota + CALL_MESSAGE_ROLLBACK_TYPE + PERSISTENT_MESSAGE_TYPE ) type TxSearchParam struct { - StartHeight, EndHeight uint64 - BitcoinScript []byte - OPReturnPrefix int + StartHeight, EndHeight uint64 + BitcoinScript []byte + OPReturnPrefix int } type TxSearchRes struct { - Tx *wire.MsgTx - Height uint64 + Tx *wire.MsgTx + Height uint64 } // HightRange is a struct to represent a range of heights type HeightRange struct { - Start uint64 - End uint64 + Start uint64 + End uint64 } type XCallMessage struct { - Action string - TokenAddress string - From string - To string - Amount []byte - Data []byte + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte } type RuneInfo struct { - Rune string `json:"rune"` - RuneId string `json:"runeId"` - SpaceRune string `json:"spaceRune"` - Amount string `json:"amount"` - Symbol string `json:"symbol"` - Divisibility int `json:"divisibility"` + Rune string `json:"rune"` + RuneId string `json:"runeId"` + SpaceRune string `json:"spaceRune"` + Amount string `json:"amount"` + Symbol string `json:"symbol"` + Divisibility int `json:"divisibility"` } type RuneTxIndexResponse struct { - Code int `json:"code"` - Data []RuneInfo `json:"data"` + Code int `json:"code"` + Data []RuneInfo `json:"data"` +} + +type CSMessageRequestV2 struct { + From string `json:"from"` + To string `json:"to"` + Sn []byte `json:"sn"` + MessageType uint8 `json:"messageType"` + Data []byte `json:"data"` + Protocols []string `json:"protocols"` +} + +type CSMessage struct { + MsgType []byte `json:"msgType"` + Payload []byte `json:"payload"` } From b6cdc41c726ff7b9b15216daf9e55ea4e792f4c1 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 12 Aug 2024 17:24:24 +0700 Subject: [PATCH 043/113] BB-71 update encoder and decoder for RadFi swap OP_RETURN --- utils/multisig/multisig_test.go | 73 +++++++++++++++++++++++++++++++++ utils/multisig/op_message.go | 70 +++++++++++++++++++++++++++++-- 2 files changed, 140 insertions(+), 3 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index e47ed6c4..9bccd3b7 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -513,6 +513,79 @@ func TestRadFiProvideLiquidity(t *testing.T) { fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Min1) } +func TestRadFiSwap(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + // Add Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 0 + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + msgTx.AddTxOut(wire.NewTxOut(0, script1)) + + // Add RadFi Swap Message + radfiMsg := RadFiSwapMsg { + IsExactInOut: true, + TokenOutIndex: 123, + } + script2, _ := CreateSwapScript(&radfiMsg) + fmt.Println("OP_RETURN script: ", script2) + msgTx.AddTxOut(wire.NewTxOut(0, script2)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decode Radfi message + decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) + + fmt.Println("err decode: ", err) + fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) + fmt.Println("decoded message - IsExactInOut : ", decodedRadFiMessage.SwapMsg.IsExactInOut) + fmt.Println("decoded message - TokenOutIndex : ", decodedRadFiMessage.SwapMsg.TokenOutIndex) +} + func TestRadFiWithdrawLiquidity(t *testing.T) { chainParam := &chaincfg.SigNetParams diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index d7b6a8e1..f0a41b90 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -29,6 +29,13 @@ type RadFiProvideLiquidityMsg struct { Min1 uint16 } +type RadFiSwapMsg struct { + IsExactInOut bool + TokenOutIndex uint32 + // TokenOutId *Rune + // TokenOutAmount *uint256.Int +} + type RadFiWithdrawLiquidityMsg struct { RecipientIndex uint32 LiquidityValue *uint256.Int @@ -42,6 +49,7 @@ type RadFiCollectFeesMsg struct { type RadFiDecodedMsg struct { Flag byte ProvideLiquidityMsg *RadFiProvideLiquidityMsg + SwapMsg *RadFiSwapMsg WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg CollectFeesMsg *RadFiCollectFeesMsg } @@ -94,6 +102,40 @@ func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) return builder.AddData(buf.Bytes()).Script() } +func CreateSwapScript(msg *RadFiSwapMsg) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_RADFI_IDENT) + builder.AddOp(OP_RADFI_SWAP) + // encode message content + var isExactInOutUint8 uint8 + if msg.IsExactInOut { + isExactInOutUint8 = 1 + } + + // tokenOutIdBlockNumberByte := make([]byte, 8) + // binary.BigEndian.PutUint64(tokenOutIdBlockNumberByte, msg.TokenOutId.BlockNumber) + // tokenOutIdBlockNumberLen := uint8(bits.Len64(msg.TokenOutId.BlockNumber)) + + // tokenOutIdTxIndexByte := make([]byte, 4) + // binary.BigEndian.PutUint32(tokenOutIdTxIndexByte, msg.TokenOutId.TxIndex) + // tokenOutIdTxIndexLen := uint8(bits.Len32(msg.TokenOutId.TxIndex)) + + // fmt.Println("tokenOutIdBlockNumberLen: ", tokenOutIdBlockNumberLen) + // singleByte := byte((isExactInOutUint8 << 7) ^ (tokenOutIdBlockNumberLen << 3) ^ tokenOutIdTxIndexLen) + // fmt.Println("singleByte: ", singleByte) + // data := append([]byte{singleByte}, tokenOutIdBlockNumberByte[8-tokenOutIdBlockNumberLen:]...) + // data = append(data, tokenOutIdTxIndexByte[4-tokenOutIdTxIndexLen:]...) + // data = append(data, msg.TokenOutAmount.Bytes()...) + + TokenOutIndexByte := make([]byte, 4) + binary.BigEndian.PutUint32(TokenOutIndexByte, msg.TokenOutIndex) + data := append([]byte{isExactInOutUint8}, TokenOutIndexByte...) + + return builder.AddData(data).Script() +} + func CreateWithdrawLiquidityScript(msg *RadFiWithdrawLiquidityMsg) ([]byte, error) { builder := txscript.NewScriptBuilder() @@ -207,7 +249,31 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { }, nil case OP_RADFI_SWAP: - fmt.Println("OP_RADFI_SWAP") + // singleByte := uint8(payload[0]) + // isExactInOut := (singleByte >> 7) != 0 + // tokenOutIdBlockNumberLen := singleByte << 1 >> 4 + // tokenOutIdTxIndexLen := singleByte << 5 >> 5 + + // payload = payload[1:] + // tokenOutIdBlockNumber := binary.BigEndian.Uint64(payload[:tokenOutIdBlockNumberLen]) + + // payload = payload[tokenOutIdBlockNumberLen:] + // tokenOutIdTxIndex := binary.BigEndian.Uint32(payload[:tokenOutIdTxIndexLen]) + + // TokenOutAmount := new(uint256.Int).SetBytes(payload[tokenOutIdTxIndexLen:]) + + return &RadFiDecodedMsg { + Flag : flag, + SwapMsg: &RadFiSwapMsg{ + IsExactInOut : payload[0] != 0, + TokenOutIndex : binary.BigEndian.Uint32(payload[1:]), + // TokenOutId : &Rune{ + // BlockNumber : tokenOutIdBlockNumber, + // TxIndex : tokenOutIdTxIndex, + // }, + // TokenOutAmount : TokenOutAmount, + }, + }, nil case OP_RADFI_WITHDRAW_LIQUIDITY: // singleByte := uint8(payload[0]) @@ -247,6 +313,4 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { default: return nil, fmt.Errorf("ReadRadFiMessage - invalid flag") } - - return nil, fmt.Errorf("ReadRadFiMessage - no RadFi message found") } From abd88980ff266177a7a8fd3e8656c867250bc4a3 Mon Sep 17 00:00:00 2001 From: Shall Date: Wed, 14 Aug 2024 11:35:08 +0700 Subject: [PATCH 044/113] feat: update logic to run btc relay --- .vscode/launch.json | 18 +++ cmd/config.go | 3 + relayer/chains/bitcoin/client.go | 15 +- relayer/chains/bitcoin/key.go | 26 +++ .../bitcoin/{provide.go => provider.go} | 148 +++++++++++------- relayer/chains/bitcoin/types.go | 49 ++++++ relayer/chains/icon/client.go | 1 + 7 files changed, 198 insertions(+), 62 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 relayer/chains/bitcoin/key.go rename relayer/chains/bitcoin/{provide.go => provider.go} (88%) diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..33b4dca6 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,18 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Launch App", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}", + "args": [ + "start", + ], + "env": { + "RELAY_HOME": "/Users/Corgi/Corgi/workspace/lydia/centralized-relay" + } + } + ] +} \ No newline at end of file diff --git a/cmd/config.go b/cmd/config.go index eb77d05d..6da3a5a4 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -9,6 +9,7 @@ import ( jsoniter "github.com/json-iterator/go" + "github.com/icon-project/centralized-relay/relayer/chains/bitcoin" "github.com/icon-project/centralized-relay/relayer/chains/wasm" "github.com/icon-project/centralized-relay/relayer" @@ -255,6 +256,8 @@ func (iw *ProviderConfigYAMLWrapper) UnmarshalYAML(n *yaml.Node) error { iw.Value = new(evm.Config) case "cosmos": iw.Value = new(wasm.Config) + case "bitcoin": + iw.Value = new(bitcoin.Config) default: return fmt.Errorf("%s is an invalid chain type, check your config file", iw.Type) } diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 12b50fc9..af4e8503 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -3,13 +3,15 @@ package bitcoin import ( "bytes" "context" + "os" + "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" "go.uber.org/zap" - "os" + // "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/chaincfg/chainhash" ) @@ -45,12 +47,12 @@ type Client struct { } // create new client -func newClient(rpcUrl, user, pass string, httpPostMode, disableTLS bool, l *zap.Logger, chainParam *chaincfg.Params) (IClient, error) { +func newClient(ctx context.Context, rpcUrl string, httpPostMode, disableTLS bool, l *zap.Logger) (IClient, error) { // Connect to the Bitcoin Core RPC server connConfig := &rpcclient.ConnConfig{ Host: rpcUrl, - User: user, - Pass: pass, + User: "123", + Pass: "123", HTTPPostMode: httpPostMode, DisableTLS: disableTLS, } @@ -63,9 +65,8 @@ func newClient(rpcUrl, user, pass string, httpPostMode, disableTLS bool, l *zap. // ws return &Client{ - log: l, - client: client, - chainParam: chainParam, + log: l, + client: client, }, nil } diff --git a/relayer/chains/bitcoin/key.go b/relayer/chains/bitcoin/key.go new file mode 100644 index 00000000..bfbb5497 --- /dev/null +++ b/relayer/chains/bitcoin/key.go @@ -0,0 +1,26 @@ +package bitcoin + +import ( + "context" + "path" +) + +func (p *Provider) RestoreKeystore(ctx context.Context) error { + + return nil +} + +func (p *Provider) NewKeystore(password string) (string, error) { + + return "", nil +} + +// ImportKeystore imports a keystore from a file +func (p *Provider) ImportKeystore(ctx context.Context, keyPath, passphrase string) (string, error) { + return "", nil +} + +// keystorePath is the path to the keystore file +func (p *Provider) keystorePath(addr string) string { + return path.Join(p.cfg.HomeDir, "keystore", p.NID(), addr) +} diff --git a/relayer/chains/bitcoin/provide.go b/relayer/chains/bitcoin/provider.go similarity index 88% rename from relayer/chains/bitcoin/provide.go rename to relayer/chains/bitcoin/provider.go index c79f5098..045605d3 100644 --- a/relayer/chains/bitcoin/provide.go +++ b/relayer/chains/bitcoin/provider.go @@ -4,22 +4,20 @@ import ( "bytes" "context" "fmt" - "github.com/btcsuite/btcd/txscript" - "github.com/icon-project/centralized-relay/utils/multisig" "math/big" "runtime" - "strings" "sync" "time" wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/btcsuite/btcd/txscript" sdkTypes "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/errors" "github.com/icon-project/centralized-relay/relayer/chains/wasm/types" "github.com/icon-project/centralized-relay/relayer/events" "github.com/icon-project/centralized-relay/relayer/kms" "github.com/icon-project/centralized-relay/relayer/provider" relayTypes "github.com/icon-project/centralized-relay/relayer/types" + "github.com/icon-project/centralized-relay/utils/multisig" "github.com/icon-project/icon-bridge/common/codec" jsoniter "github.com/json-iterator/go" "go.uber.org/zap" @@ -28,13 +26,9 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) type Provider struct { - logger *zap.Logger - // cfg *Config + logger *zap.Logger + cfg *Config client IClient - kms kms.KMS - wallet sdkTypes.AccountI - contracts map[string]relayTypes.EventMap - eventList []sdkTypes.Event LastSavedHeightFunc func() uint64 LastSerialNumFunc func() *big.Int multisigAddrScript []byte // @@ -43,6 +37,37 @@ type Provider struct { unitsatEndpoint string } +type Config struct { + provider.CommonConfig `json:",inline" yaml:",inline"` + StepMin int64 `json:"step-min" yaml:"step-min"` + StepLimit int64 `json:"step-limit" yaml:"step-limit"` + StepAdjustment int64 `json:"step-adjustment" yaml:"step-adjustment"` +} + +// NewProvider returns new Icon provider +func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath string, debug bool, chainName string) (provider.ChainProvider, error) { + if err := c.Validate(); err != nil { + return nil, err + } + if err := c.sanitize(); err != nil { + return nil, err + } + + client, err := newClient(ctx, c.RPCUrl, true, false, log) + if err != nil { + return nil, fmt.Errorf("failed to create new client: %v", err) + } + + c.ChainName = chainName + c.HomeDir = homepath + + return &Provider{ + logger: log.With(zap.Stringp("nid", &c.NID), zap.Stringp("name", &c.ChainName)), + cfg: c, + client: client, + }, nil +} + func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { return p.client.GetLatestBlockHeight(ctx) } @@ -79,7 +104,7 @@ func (p *Provider) Init(ctx context.Context, homePath string, kms kms.KMS) error } // Wallet returns the wallet of the provider -func (p *Provider) Wallet() sdkTypes.AccAddress { +func (p *Provider) Wallet() error { return nil } @@ -134,54 +159,55 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb if err != nil { return err } - seq := p.wallet.GetSequence() + 1 - if err := p.wallet.SetSequence(seq); err != nil { - p.logger.Error("failed to set sequence", zap.Error(err)) - } - p.waitForTxResult(ctx, message.MessageKey(), res.TxHash, callback) + // seq := p.wallet.GetSequence() + 1 + // if err := p.wallet.SetSequence(seq); err != nil { + // p.logger.Error("failed to set sequence", zap.Error(err)) + // } + p.waitForTxResult(ctx, message.MessageKey(), res, callback) return nil } // call the smart contract to send the message -func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (*sdkTypes.TxResponse, error) { - rawMsg, err := p.getRawContractMessage(message) - if err != nil { - return nil, err - } - - var contract string - - switch message.EventType { - case events.EmitMessage, events.RevertMessage, events.SetAdmin, events.ClaimFee, events.SetFee: - //contract = p.cfg.Contracts[relayTypes.ConnectionContract] - case events.CallMessage, events.RollbackMessage: - //contract = p.cfg.Contracts[relayTypes.XcallContract] - default: - return nil, fmt.Errorf("unknown event type: %s ", message.EventType) - } - - msg := &wasmTypes.MsgExecuteContract{ - Sender: p.Wallet().String(), - Contract: contract, - Msg: rawMsg, - } - - msgs := []sdkTypes.Msg{msg} - - res, err := p.sendMessage(ctx, msgs...) - if err != nil { - if strings.Contains(err.Error(), errors.ErrWrongSequence.Error()) { - if mmErr := p.handleSequence(ctx); mmErr != nil { - return res, fmt.Errorf("failed to handle sequence mismatch error: %v || %v", mmErr, err) - } - return p.sendMessage(ctx, msgs...) - } - } - return res, err -} - -func (p *Provider) sendMessage(ctx context.Context, msgs ...sdkTypes.Msg) (*sdkTypes.TxResponse, error) { - return p.prepareAndPushTxToMemPool(ctx, p.wallet.GetAccountNumber(), p.wallet.GetSequence(), msgs...) +func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (string, error) { + // rawMsg, err := p.getRawContractMessage(message) + // if err != nil { + // return nil, err + // } + + // var contract string + + // switch message.EventType { + // case events.EmitMessage, events.RevertMessage, events.SetAdmin, events.ClaimFee, events.SetFee: + // //contract = p.cfg.Contracts[relayTypes.ConnectionContract] + // case events.CallMessage, events.RollbackMessage: + // //contract = p.cfg.Contracts[relayTypes.XcallContract] + // default: + // return nil, fmt.Errorf("unknown event type: %s ", message.EventType) + // } + + // msg := &wasmTypes.MsgExecuteContract{ + // Sender: p.Wallet().String(), + // Contract: contract, + // Msg: rawMsg, + // } + + // msgs := []sdkTypes.Msg{msg} + + // res, err := p.sendMessage(ctx, msgs...) + // if err != nil { + // if strings.Contains(err.Error(), errors.ErrWrongSequence.Error()) { + // if mmErr := p.handleSequence(ctx); mmErr != nil { + // return res, fmt.Errorf("failed to handle sequence mismatch error: %v || %v", mmErr, err) + // } + // return p.sendMessage(ctx, msgs...) + // } + // } + return "", nil +} + +func (p *Provider) sendMessage(ctx context.Context, msgs ...sdkTypes.Msg) (string, error) { + // return p.prepareAndPushTxToMemPool(ctx, p.wallet.GetAccountNumber(), p.wallet.GetSequence(), msgs...) + return "", nil } func (p *Provider) handleSequence(ctx context.Context) error { @@ -736,3 +762,15 @@ func (p *Provider) SetSerialNumberFunc(f func() *big.Int) { func (p *Provider) GetSerialNumber() *big.Int { return p.LastSerialNumFunc() } + +func (p *Config) sanitize() error { + // TODO: + return nil +} + +func (c *Config) Validate() error { + if c.RPCUrl == "" { + return fmt.Errorf("bitcoin provider rpc endpoint is empty") + } + return nil +} diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index eddb0d35..e6df91a1 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -73,3 +73,52 @@ type CSMessage struct { MsgType []byte `json:"msgType"` Payload []byte `json:"payload"` } + +type Block struct { + Hash string `json:"hash"` + Height int `json:"height"` + Tx []Transaction `json:"tx"` +} + +// Transaction represents the structure of a Bitcoin transaction. +type Transaction struct { + TxID string `json:"txid"` + Vout []Vout `json:"vout"` +} + +// Vout represents the transaction output. +type Vout struct { + Value float64 `json:"value"` + N int `json:"n"` + ScriptPubKey ScriptPubKey `json:"scriptPubKey"` +} + +// ScriptPubKey represents the script public key. +type ScriptPubKey struct { + Hex string `json:"hex"` + Addresses []string `json:"addresses"` + Type string `json:"type"` + Asm string `json:"asm"` +} + +// BlockchainInfo represents the information returned by getblockchaininfo. +type BlockchainInfo struct { + Chain string `json:"chain"` + Blocks int `json:"blocks"` + Headers int `json:"headers"` + BestBlockHash string `json:"bestblockhash"` + Difficulty float64 `json:"difficulty"` + Mediantime int64 `json:"mediantime"` + VerificationProgress float64 `json:"verificationprogress"` + InitialBlockDownload bool `json:"initialblockdownload"` + Chainwork string `json:"chainwork"` + SizeOnDisk int64 `json:"size_on_disk"` + Pruned bool `json:"pruned"` + Warnings string `json:"warnings"` +} + +// QuicknodeRequest represents a JSON-RPC request payload. +type QuicknodeRequest struct { + Method string `json:"method"` + Params []interface{} `json:"params"` +} diff --git a/relayer/chains/icon/client.go b/relayer/chains/icon/client.go index c7765bb3..2bba2865 100644 --- a/relayer/chains/icon/client.go +++ b/relayer/chains/icon/client.go @@ -268,6 +268,7 @@ func (c *Client) Monitor(ctx context.Context, reqUrl string, reqPtr, respPtr int c.log.Debug(fmt.Sprintf("Monitor finish %s", conn.RemoteAddr().String())) c.wsClose(conn) }() + if err = c.wsRequest(conn, reqPtr); err != nil { return err } From bfaaa5f7b6f08cb4148c4e10dd6f0f5d43076e26 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 14 Aug 2024 18:19:18 +0700 Subject: [PATCH 045/113] BB-68 update code read the bitcoin and rune utxos relayers received in tx --- utils/multisig/multisig_test.go | 33 +++++++++++++++++-- utils/multisig/structure.go | 6 ++++ utils/multisig/tx.go | 57 +++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 3 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 9bccd3b7..2823658d 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -442,7 +442,7 @@ func TestRadFiProvideLiquidity(t *testing.T) { IsRelayersMultisig: false, TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", OutputIdx: 1, - OutputAmount: 3808, + OutputAmount: 10000, }, } @@ -451,6 +451,18 @@ func TestRadFiProvideLiquidity(t *testing.T) { ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", Amount: 1000, }, + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 2000, + }, + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 2100, + }, } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) @@ -461,7 +473,7 @@ func TestRadFiProvideLiquidity(t *testing.T) { // Add Rune transfering // rune id 840000:3, amount 10000 (5 decimals), to output id 0 - script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 2) msgTx.AddTxOut(wire.NewTxOut(0, script1)) // Add RadFi Provive Liquidity Message @@ -503,7 +515,6 @@ func TestRadFiProvideLiquidity(t *testing.T) { // Decode Radfi message decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) - fmt.Println("err decode: ", err) fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) fmt.Println("decoded message - Fee : ", decodedRadFiMessage.ProvideLiquidityMsg.Fee) @@ -511,6 +522,22 @@ func TestRadFiProvideLiquidity(t *testing.T) { fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.LowerTick) fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.ProvideLiquidityMsg.Min0) fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Min1) + + // get list of Relayer bitcoin an rune UTXOs + relayerScriptAddress := signedMsgTx.TxOut[0].PkScript + sequenceNumberUTXO, bitcoinUTXOs, runeUTXOs, err := GetRelayerReceivedUTXO(signedMsgTx, 0, relayerScriptAddress) + fmt.Println("-------------GetRelayerReceivedUTXO:") + fmt.Println("relayerScriptAddress: ", relayerScriptAddress) + fmt.Println("err: ", err) + fmt.Println("sequenceNumberUTXO: ", sequenceNumberUTXO.IsRelayersMultisig, sequenceNumberUTXO.OutputIdx, sequenceNumberUTXO.OutputAmount, sequenceNumberUTXO.TxHash) + fmt.Println("bitcoinUTXOs: ") + for _, utxo := range bitcoinUTXOs { + fmt.Println("bitcoinUTXO: ", utxo.IsRelayersMultisig, utxo.OutputIdx, utxo.OutputAmount, utxo.TxHash) + } + fmt.Println("runeUTXOs: ") + for _, utxo := range runeUTXOs { + fmt.Println("runeUTXO: ", utxo.edict, utxo.edictUTXO.IsRelayersMultisig, utxo.edictUTXO.OutputIdx, utxo.edictUTXO.OutputAmount, utxo.edictUTXO.TxHash) + } } func TestRadFiSwap(t *testing.T) { diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 6c102102..80a5130a 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -4,6 +4,7 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/txscript" + "github.com/bxelab/runestone" ) type MultisigInfo struct { @@ -33,6 +34,11 @@ type UTXO struct { OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` } +type RuneUTXO struct { + edict runestone.Edict + edictUTXO *UTXO +} + type TapSigParams struct { TxSigHashes *txscript.TxSigHashes `bson:"tx_sig_hashes" json:"txSigHashes"` RelayersPKScript []byte `bson:"relayers_PK_script" json:"relayersPKScript"` diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 3a694229..8b618a93 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/bxelab/runestone" ) // create unsigned multisig transaction @@ -243,3 +244,59 @@ func ParseTx(data string) (*wire.MsgTx, error) { } return tx, nil } + +// filter the relayer UTXO from tx +// input: tx, id of sequence number in output (0 is default, -1 if not existed), relayer script address +// output: sequence number UTXO, bitcoin UTXOs, rune UTXOs +func GetRelayerReceivedUTXO( + msgTx *wire.MsgTx, + sequenceNumberIdx int, + relayerScriptAddress []byte, +) (*UTXO, []*UTXO, []*RuneUTXO, error) { + // Decipher runestone + r := &runestone.Runestone{} + artifact, err := r.Decipher(msgTx) + if err != nil { + return nil, nil, nil, err + } + edictOutputs := []uint32{} + for _, edict := range artifact.Runestone.Edicts { + edictOutputs = append(edictOutputs, edict.Output) + } + + var sequenceNumberUTXO *UTXO + bitcoinUTXOs := []*UTXO{} + runeUTXOs := []*RuneUTXO{} + Exit: + for idx, output := range msgTx.TxOut { + // Skip non-relayer received UTXO + if !bytes.Equal(output.PkScript, relayerScriptAddress) { + continue + } + currentUTXO := &UTXO{ + IsRelayersMultisig: true, + TxHash: msgTx.TxHash().String(), + OutputIdx: uint32(idx), + OutputAmount: uint64(output.Value), + } + // check if is sequenceNumber UTXO + if idx == sequenceNumberIdx { + sequenceNumberUTXO = currentUTXO + continue + } + // check if is rune UTXO + for edictIdx, edictOutput := range edictOutputs { + if idx == int(edictOutput) { + runeUTXOs = append(runeUTXOs, &RuneUTXO{ + edict: artifact.Runestone.Edicts[edictIdx], + edictUTXO: currentUTXO, + }) + continue Exit + } + } + // or else it will be bitcoin UTXO + bitcoinUTXOs = append(bitcoinUTXOs, currentUTXO) + } + + return sequenceNumberUTXO, bitcoinUTXOs, runeUTXOs, nil +} From 1e5fcd326271b3bc9dd2c58a6ec8dac33c148de0 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Thu, 15 Aug 2024 18:09:27 +0700 Subject: [PATCH 046/113] BB-183 Update code encode and decode OP_RETURN Init pool --- utils/multisig/multisig_test.go | 75 +++++++++++++++++++++++++++++++++ utils/multisig/op_message.go | 52 ++++++++++++++++++++++- 2 files changed, 126 insertions(+), 1 deletion(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 2823658d..beddc202 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -434,6 +434,81 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { fmt.Println("decoded message : ", string(decodedMessage)) } +func TestRadFiInitPool(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 10000, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + // Add RadFi Init pool Message + radfiMsg := RadFiInitPoolMsg { + Fee: 30, + UpperTick: 12345, + LowerTick: -12345, + Min0: 0, + Min1: 10000, + InitPrice: uint256.MustFromDecimal("123456789"), + } + script2, _ := CreateInitPoolScript(&radfiMsg) + fmt.Println("OP_RETURN script: ", script2) + msgTx.AddTxOut(wire.NewTxOut(0, script2)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decode Radfi message + decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) + fmt.Println("err decode: ", err) + fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) + fmt.Println("decoded message - Fee : ", decodedRadFiMessage.InitPoolMsg.Fee) + fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.InitPoolMsg.UpperTick) + fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.InitPoolMsg.LowerTick) + fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.InitPoolMsg.Min0) + fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.InitPoolMsg.Min1) + fmt.Println("decoded message - InitPrice: ", decodedRadFiMessage.InitPoolMsg.InitPrice) +} + func TestRadFiProvideLiquidity(t *testing.T) { chainParam := &chaincfg.SigNetParams diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index f0a41b90..43a92883 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -15,12 +15,22 @@ const ( OP_RUNE_IDENT = txscript.OP_13 OP_BRIDGE_IDENT = txscript.OP_14 + OP_RADFI_INIT_POOL = txscript.OP_11 OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 OP_RADFI_SWAP = txscript.OP_2 OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 OP_RADFI_COLLECT_FEES = txscript.OP_4 ) +type RadFiInitPoolMsg struct { + Fee uint8 + UpperTick int32 + LowerTick int32 + Min0 uint16 + Min1 uint16 + InitPrice *uint256.Int +} + type RadFiProvideLiquidityMsg struct { Fee uint8 UpperTick int32 @@ -48,6 +58,7 @@ type RadFiCollectFeesMsg struct { } type RadFiDecodedMsg struct { Flag byte + InitPoolMsg *RadFiInitPoolMsg ProvideLiquidityMsg *RadFiProvideLiquidityMsg SwapMsg *RadFiSwapMsg WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg @@ -83,6 +94,25 @@ func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) return scripts, nil } +func CreateInitPoolScript(msg *RadFiInitPoolMsg) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_RADFI_IDENT) + builder.AddOp(OP_RADFI_INIT_POOL) + // encode message content + buf := new(bytes.Buffer) + var data = []any{ msg.Fee, msg.UpperTick, msg.LowerTick, msg.Min0, msg.Min1 } + for _, v := range data { + err := binary.Write(buf, binary.BigEndian, v) + if err != nil { + fmt.Println("CreateProvideLiquidityScript encode data failed:", err) + } + } + + return builder.AddData(append(buf.Bytes(), msg.InitPrice.Bytes()...)).Script() +} + func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) { builder := txscript.NewScriptBuilder() @@ -236,11 +266,31 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { // Decode RadFi message switch flag { + case OP_RADFI_INIT_POOL: + r := bytes.NewReader(payload[:13]) + var provideLiquidityMsg RadFiProvideLiquidityMsg + if err := binary.Read(r, binary.BigEndian, &provideLiquidityMsg); err != nil { + return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_INIT_POOL Read failed") + } + + initPrice := new(uint256.Int).SetBytes(payload[13:]) + return &RadFiDecodedMsg { + Flag : flag, + InitPoolMsg : &RadFiInitPoolMsg{ + Fee : provideLiquidityMsg.Fee, + UpperTick : provideLiquidityMsg.UpperTick, + LowerTick : provideLiquidityMsg.LowerTick, + Min0 : provideLiquidityMsg.Min0, + Min1 : provideLiquidityMsg.Min1, + InitPrice : initPrice, + }, + }, nil + case OP_RADFI_PROVIDE_LIQUIDITY: r := bytes.NewReader(payload) var provideLiquidityMsg RadFiProvideLiquidityMsg if err := binary.Read(r, binary.BigEndian, &provideLiquidityMsg); err != nil { - fmt.Println("OP_RADFI_PROVIDE_LIQUIDITY Read failed:", err) + return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_PROVIDE_LIQUIDITY Read failed") } return &RadFiDecodedMsg { From 7a5e4d1e93c70a5e44d88452e75b99775d823470 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Thu, 15 Aug 2024 18:26:40 +0700 Subject: [PATCH 047/113] BB-184 Update code encode and decode for OP_RETURN Radfi Increase Liquidity --- utils/multisig/multisig_test.go | 75 +++++++++++++++++++++++++++++++++ utils/multisig/op_message.go | 40 +++++++++++++++++- 2 files changed, 114 insertions(+), 1 deletion(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index beddc202..78da9388 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -834,4 +834,79 @@ func TestRadFiCollectFees(t *testing.T) { fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) fmt.Println("decoded message - RecipientIndex : ", decodedRadFiMessage.CollectFeesMsg.RecipientIndex) fmt.Println("decoded message - NftId : ", decodedRadFiMessage.CollectFeesMsg.NftId) +} + +func TestRadFiIncreaseLiquidity(t *testing.T) { + chainParam := &chaincfg.SigNetParams + + inputs := []*UTXO{ + { + IsRelayersMultisig: false, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, + }, + } + + outputs := []*OutputTx{ + { + ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + Amount: 1000, + }, + } + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + // Add Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 0 + script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) + msgTx.AddTxOut(wire.NewTxOut(0, script1)) + + // Add RadFi Withdraw Liquidity Message + radfiMsg := RadFiIncreaseLiquidityMsg { + Min0: 0, + Min1: 10000, + NftId: uint256.MustFromDecimal("123456789"), + } + script2, _ := CreateIncreaseLiquidityScript(&radfiMsg) + fmt.Println("OP_RETURN script: ", script2) + msgTx.AddTxOut(wire.NewTxOut(0, script2)) + + tapSigParams := TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + + // COMBINE SIGNS + signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decode Radfi message + decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) + + fmt.Println("err decode: ", err) + fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) + fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.IncreaseLiquidityMsg.Min0) + fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.IncreaseLiquidityMsg.Min1) + fmt.Println("decoded message - NftId : ", decodedRadFiMessage.IncreaseLiquidityMsg.NftId) } \ No newline at end of file diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index 43a92883..e3275dc8 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -20,6 +20,7 @@ const ( OP_RADFI_SWAP = txscript.OP_2 OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 OP_RADFI_COLLECT_FEES = txscript.OP_4 + OP_RADFI_INCREASE_LIQUIDITY = txscript.OP_5 ) type RadFiInitPoolMsg struct { @@ -56,6 +57,13 @@ type RadFiCollectFeesMsg struct { RecipientIndex uint32 NftId *uint256.Int } + +type RadFiIncreaseLiquidityMsg struct { + Min0 uint16 + Min1 uint16 + NftId *uint256.Int +} + type RadFiDecodedMsg struct { Flag byte InitPoolMsg *RadFiInitPoolMsg @@ -63,6 +71,7 @@ type RadFiDecodedMsg struct { SwapMsg *RadFiSwapMsg WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg CollectFeesMsg *RadFiCollectFeesMsg + IncreaseLiquidityMsg *RadFiIncreaseLiquidityMsg } func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { @@ -205,6 +214,25 @@ func CreateCollectFeesScript(msg *RadFiCollectFeesMsg) ([]byte, error) { return builder.AddData(data).Script() } +func CreateIncreaseLiquidityScript(msg *RadFiIncreaseLiquidityMsg) ([]byte, error) { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_RADFI_IDENT) + builder.AddOp(OP_RADFI_INCREASE_LIQUIDITY) + // encode message content + buf := new(bytes.Buffer) + var data = []any{ msg.Min0, msg.Min1 } + for _, v := range data { + err := binary.Write(buf, binary.BigEndian, v) + if err != nil { + fmt.Println("CreateIncreaseLiquidityScript encode data failed:", err) + } + } + + return builder.AddData(append(buf.Bytes(), msg.NftId.Bytes()...)).Script() +} + func ReadBridgeMessage(transaction *wire.MsgTx) ([]byte, error) { payload := []byte{} for _, output := range transaction.TxOut { @@ -354,12 +382,22 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { return &RadFiDecodedMsg { Flag : flag, - CollectFeesMsg: &RadFiCollectFeesMsg{ + CollectFeesMsg : &RadFiCollectFeesMsg{ RecipientIndex : recipientIndex, NftId : nftId, }, }, nil + case OP_RADFI_INCREASE_LIQUIDITY: + return &RadFiDecodedMsg { + Flag : flag, + IncreaseLiquidityMsg: &RadFiIncreaseLiquidityMsg{ + Min0 : binary.BigEndian.Uint16(payload[:2]), + Min1 : binary.BigEndian.Uint16(payload[2:4]), + NftId : new(uint256.Int).SetBytes(payload[4:]), + }, + }, nil + default: return nil, fmt.Errorf("ReadRadFiMessage - invalid flag") } From 5e455070076aedf0a6d43ff93a5f3ad0ee415f87 Mon Sep 17 00:00:00 2001 From: Shall Date: Mon, 19 Aug 2024 09:26:19 +0700 Subject: [PATCH 048/113] feat: update bitcoin relayer config --- config.yaml | 35 +++++++++++++++++++++++ relayer/chains/bitcoin/client.go | 16 ++--------- relayer/chains/bitcoin/helper.go | 11 +++---- relayer/chains/bitcoin/provider.go | 46 ++++++++++++++++++++---------- 4 files changed, 75 insertions(+), 33 deletions(-) create mode 100644 config.yaml diff --git a/config.yaml b/config.yaml new file mode 100644 index 00000000..e1118940 --- /dev/null +++ b/config.yaml @@ -0,0 +1,35 @@ +global: + timeout: 10s + kms-key-id: f5c550ca-a6f2-4597-895c-4846ab8e4ad2 +chains: + # icon: + # type: icon + # value: + # rpc-url: https://lisbon.net.solidwallet.io/api/v3/ + # address: hxb6b5791be0b5ef67063b3c10b840fb81514db2fd + # start-height: 42066559 + # step-min: 1 + # step-limit: 2000000000000000000 + # contracts: + # xcall: cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 + # connection: cx8d02efb10359105f7e033149556eaea531a3740e + # network-id: 2 + # finality-block: 10 + # nid: 0x2.icon + + bitcoin: + type: bitcoin + value: + rpc-url: thrumming-light-mountain.btc.quiknode.pro:443/9010506d85a546fd92e68fff9b9af3478f0708a6/ + rpc-user: 123 + rpc-password: 123 + address: tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd + unisat-url: https://open-api.unisat.io/v1/indexer + start-height: 847735 + network-id: 1 + finality-block: 10 + nid: 0x1.btc + chain-name: bitcoin + mode: slave + port: 8082 + api-key: key diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index af4e8503..6d087aff 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -3,7 +3,6 @@ package bitcoin import ( "bytes" "context" - "os" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/btcutil" @@ -16,15 +15,6 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" ) -func RunApp() { - goEnv := os.Getenv("GO_ENV") - if goEnv == "master" { - startMaster() - } else { - startSlave() - } -} - type IClient interface { // IsConnected() bool // Reconnect() error @@ -47,12 +37,12 @@ type Client struct { } // create new client -func newClient(ctx context.Context, rpcUrl string, httpPostMode, disableTLS bool, l *zap.Logger) (IClient, error) { +func newClient(ctx context.Context, rpcUrl string, user string, password string, httpPostMode, disableTLS bool, l *zap.Logger) (IClient, error) { // Connect to the Bitcoin Core RPC server connConfig := &rpcclient.ConnConfig{ Host: rpcUrl, - User: "123", - Pass: "123", + User: user, + Pass: password, HTTPPostMode: httpPostMode, DisableTLS: disableTLS, } diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index 7a09e70a..1688041c 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -3,14 +3,15 @@ package bitcoin import ( "encoding/json" "fmt" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "io/ioutil" + "io" "math/big" "net/http" "strconv" "strings" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + bitcoinABI "github.com/icon-project/centralized-relay/relayer/chains/bitcoin/abi" "github.com/icon-project/centralized-relay/utils/multisig" "github.com/icon-project/icon-bridge/common/codec" @@ -18,7 +19,7 @@ import ( func GetRuneTxIndex(endpoint, method, bearToken, txId string, index int) (*RuneTxIndexResponse, error) { client := &http.Client{} - endpoint = endpoint + "/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" + endpoint = endpoint + "/runes/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" fmt.Println(endpoint) req, err := http.NewRequest(method, endpoint, nil) @@ -35,7 +36,7 @@ func GetRuneTxIndex(endpoint, method, bearToken, txId string, index int) (*RuneT } defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) + body, err := io.ReadAll(res.Body) if err != nil { fmt.Println(err) return nil, err diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 045605d3..480a7857 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "math/big" + "os" "runtime" "sync" "time" @@ -12,6 +13,7 @@ import ( wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/btcsuite/btcd/txscript" sdkTypes "github.com/cosmos/cosmos-sdk/types" + "github.com/icon-project/centralized-relay/relayer/chains/wasm/types" "github.com/icon-project/centralized-relay/relayer/events" "github.com/icon-project/centralized-relay/relayer/kms" @@ -25,6 +27,11 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) +var ( + BTCToken = "0:0" + MethodDeposit = "Deposit" +) + type Provider struct { logger *zap.Logger cfg *Config @@ -34,14 +41,23 @@ type Provider struct { multisigAddrScript []byte // assetManagerAddrIcon string bearToken string - unitsatEndpoint string } type Config struct { provider.CommonConfig `json:",inline" yaml:",inline"` - StepMin int64 `json:"step-min" yaml:"step-min"` - StepLimit int64 `json:"step-limit" yaml:"step-limit"` - StepAdjustment int64 `json:"step-adjustment" yaml:"step-adjustment"` + UniSatURL string `json:"unisat-url" yaml:"unisat-url"` + Type string `json:"type" yaml:"type"` + User string `json:"rpc-user" yaml:"rpc-user"` + Password string `json:"rpc-password" yaml:"rpc-password"` +} + +func RunApp() { + goEnv := os.Getenv("GO_ENV") + if goEnv == "master" { + startMaster() + } else { + startSlave() + } } // NewProvider returns new Icon provider @@ -53,7 +69,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri return nil, err } - client, err := newClient(ctx, c.RPCUrl, true, false, log) + client, err := newClient(ctx, c.RPCUrl, c.User, c.Password, true, false, log) if err != nil { return nil, fmt.Errorf("failed to create new client: %v", err) } @@ -86,13 +102,11 @@ func (p *Provider) QueryTransactionReceipt(ctx context.Context, txHash string) ( } func (p *Provider) NID() string { - //return p.cfg.NID - return "" + return p.cfg.NID } func (p *Provider) Name() string { - //return p.cfg.ChainName - return "" + return p.cfg.ChainName } func (p *Provider) Init(ctx context.Context, homePath string, kms kms.KMS) error { @@ -109,7 +123,7 @@ func (p *Provider) Wallet() error { } func (p *Provider) Type() string { - return types.ChainType + return "bitcoin" } func (p *Provider) Config() provider.Config { @@ -117,6 +131,7 @@ func (p *Provider) Config() provider.Config { } func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockInfoChan chan *relayTypes.BlockInfo) error { + // run http server to help btc interact each others latestHeight, err := p.QueryLatestHeight(ctx) if err != nil { p.logger.Error("failed to get latest block height", zap.Error(err)) @@ -485,7 +500,7 @@ func (p *Provider) getStartHeight(latestHeight, lastSavedHeight uint64) (uint64, // return startHeight, nil //} - return latestHeight, nil + return lastSavedHeight, nil } func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64) <-chan *HeightRange { @@ -536,7 +551,7 @@ func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, hei func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { var ( // todo: query from provide.config - multisigAddress = "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" + multisigAddress = p.cfg.Address preFixOP = txscript.OP_13 ) @@ -574,7 +589,8 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err _, err = codec.RLP.UnmarshalFromBytes(decodeMessage, &messageInfo) if err != nil { fmt.Printf("\n not a xcall format request \n") - } else if messageInfo.Action == "Deposit" && messageInfo.To == p.assetManagerAddrIcon { // maybe get this function name from cf file + } else if messageInfo.Action == MethodDeposit && messageInfo.To == p.assetManagerAddrIcon { + // maybe get this function name from cf file // todo verify transfer amount match in calldata if it // call 3rd to check rune amount tokenId := messageInfo.TokenAddress @@ -594,14 +610,14 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err continue } - if messageInfo.TokenAddress == "0:0" { + if messageInfo.TokenAddress == BTCToken { if amount.Cmp(big.NewInt(out.Value)) == 0 { verified = true break } } else { // https://open-api.unisat.io/v1/indexer/runes/utxo - runes, err := GetRuneTxIndex(p.unitsatEndpoint, "GET", p.bearToken, tx.Tx.TxHash().String(), i) + runes, err := GetRuneTxIndex(p.cfg.UniSatURL, "GET", p.bearToken, tx.Tx.TxHash().String(), i) if err != nil { return nil, err } From e9be6c9c5524ea27c6d9136a2d5a2973cfb68f05 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 20 Aug 2024 18:09:03 +0700 Subject: [PATCH 049/113] update tx creation code and test for op_return --- utils/multisig/multisig_test.go | 221 ++++++++++++++++---------------- utils/multisig/structure.go | 1 + utils/multisig/tx.go | 36 +++--- 3 files changed, 135 insertions(+), 123 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 78da9388..ef0d7fa1 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -18,7 +18,7 @@ import ( ) func TestGenerateKeys(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params for i := 0; i < 3; i++ { privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) @@ -32,7 +32,7 @@ func TestGenerateKeys(t *testing.T) { } func TestLoadWalletFromPrivateKey(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params wif, _ := btcutil.DecodeWIF("cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy") pubKey := wif.SerializePubKey(); @@ -43,11 +43,11 @@ func TestLoadWalletFromPrivateKey(t *testing.T) { } func TestRandomKeys(t *testing.T) { - randomKeys(3, &chaincfg.SigNetParams, []int{0, 1, 2}) + randomKeys(3, &chaincfg.TestNet3Params, []int{0, 1, 2}) } func TestBuildMultisigTapScript(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params _, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) @@ -62,7 +62,7 @@ func TestBuildMultisigTapScript(t *testing.T) { } func TestMultisigUserClaimLiquidity(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { @@ -134,7 +134,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { } func TestMultisigUserSwap(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { @@ -251,7 +251,7 @@ func TestParseTx(t *testing.T) { } func TestUserRecoveryTimeLock(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { @@ -302,7 +302,7 @@ func TestUserRecoveryTimeLock(t *testing.T) { } func TestTransferRune(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { @@ -368,38 +368,40 @@ func TestTransferRune(t *testing.T) { } func TestTransferBitcoinWithBridgeMessage(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 3808, + TxHash: "88cce50b4c9ff0d1c3f58f769fdb8b2e2bfbd3a637664c78b1a38c0f1e492b8f", + OutputIdx: 0, + OutputAmount: 2000000, }, } outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 1000, + ReceiverAddress: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: 10000, }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add Bridge Message message := []byte("{\"msg\":\"Test Bridge Message\"}") - scripts, _ := CreateBridgeMessageScripts(message, 5) + scripts, _ := CreateBridgeMessageScripts(message, 70) for i, script := range scripts { fmt.Println("OP_RETURN ", i, " script ", script) - msgTx.AddTxOut(wire.NewTxOut(0, script)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script, + }) } + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 8000, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -435,30 +437,23 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { } func TestRadFiInitPool(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 10000, + TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", + OutputIdx: 2, + OutputAmount: 1989000, }, } outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 1000, + ReceiverAddress: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: 10000, }, } - - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add RadFi Init pool Message radfiMsg := RadFiInitPoolMsg { Fee: 30, @@ -468,9 +463,17 @@ func TestRadFiInitPool(t *testing.T) { Min1: 10000, InitPrice: uint256.MustFromDecimal("123456789"), } - script2, _ := CreateInitPoolScript(&radfiMsg) - fmt.Println("OP_RETURN script: ", script2) - msgTx.AddTxOut(wire.NewTxOut(0, script2)) + script, _ := CreateInitPoolScript(&radfiMsg) + fmt.Println("OP_RETURN script: ", script) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script, + }) + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 8000, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -510,46 +513,29 @@ func TestRadFiInitPool(t *testing.T) { } func TestRadFiProvideLiquidity(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 10000, + TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", + OutputIdx: 2, + OutputAmount: 1989000, }, } outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 1000, - }, - { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 2000, - }, - { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 1000, - }, - { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 2100, + ReceiverAddress: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: 10000, }, } - - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add Rune transfering // rune id 840000:3, amount 10000 (5 decimals), to output id 0 script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 2) - msgTx.AddTxOut(wire.NewTxOut(0, script1)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script1, + }) // Add RadFi Provive Liquidity Message radfiMsg := RadFiProvideLiquidityMsg { @@ -561,7 +547,15 @@ func TestRadFiProvideLiquidity(t *testing.T) { } script2, _ := CreateProvideLiquidityScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script2) - msgTx.AddTxOut(wire.NewTxOut(0, script2)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script2, + }) + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 8000, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -616,7 +610,7 @@ func TestRadFiProvideLiquidity(t *testing.T) { } func TestRadFiSwap(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { @@ -633,17 +627,12 @@ func TestRadFiSwap(t *testing.T) { Amount: 1000, }, } - - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add Rune transfering // rune id 840000:3, amount 10000 (5 decimals), to output id 0 script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - msgTx.AddTxOut(wire.NewTxOut(0, script1)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script1, + }) // Add RadFi Swap Message radfiMsg := RadFiSwapMsg { @@ -652,7 +641,16 @@ func TestRadFiSwap(t *testing.T) { } script2, _ := CreateSwapScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script2) - msgTx.AddTxOut(wire.NewTxOut(0, script2)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script2, + }) + + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -689,7 +687,7 @@ func TestRadFiSwap(t *testing.T) { } func TestRadFiWithdrawLiquidity(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { @@ -706,17 +704,12 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { Amount: 1000, }, } - - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add Rune transfering // rune id 840000:3, amount 10000 (5 decimals), to output id 0 script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - msgTx.AddTxOut(wire.NewTxOut(0, script1)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script1, + }) // Add RadFi Withdraw Liquidity Message radfiMsg := RadFiWithdrawLiquidityMsg { @@ -726,7 +719,15 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { } script2, _ := CreateWithdrawLiquidityScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script2) - msgTx.AddTxOut(wire.NewTxOut(0, script2)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script2, + }) + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -764,14 +765,14 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { } func TestRadFiCollectFees(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + TxHash: "9c07074364e5ce367f4d07a2657337a60684730158fd093ab6cb694f75984cb9", OutputIdx: 1, - OutputAmount: 3808, + OutputAmount: 4900, }, } @@ -781,17 +782,12 @@ func TestRadFiCollectFees(t *testing.T) { Amount: 1000, }, } - - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add Rune transfering // rune id 840000:3, amount 10000 (5 decimals), to output id 0 script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - msgTx.AddTxOut(wire.NewTxOut(0, script1)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script1, + }) // Add RadFi Withdraw Liquidity Message radfiMsg := RadFiCollectFeesMsg { @@ -800,7 +796,15 @@ func TestRadFiCollectFees(t *testing.T) { } script2, _ := CreateCollectFeesScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script2) - msgTx.AddTxOut(wire.NewTxOut(0, script2)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script2, + }) + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -837,7 +841,7 @@ func TestRadFiCollectFees(t *testing.T) { } func TestRadFiIncreaseLiquidity(t *testing.T) { - chainParam := &chaincfg.SigNetParams + chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ { @@ -854,17 +858,12 @@ func TestRadFiIncreaseLiquidity(t *testing.T) { Amount: 1000, }, } - - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add Rune transfering // rune id 840000:3, amount 10000 (5 decimals), to output id 0 script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - msgTx.AddTxOut(wire.NewTxOut(0, script1)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script1, + }) // Add RadFi Withdraw Liquidity Message radfiMsg := RadFiIncreaseLiquidityMsg { @@ -874,7 +873,15 @@ func TestRadFiIncreaseLiquidity(t *testing.T) { } script2, _ := CreateIncreaseLiquidityScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script2) - msgTx.AddTxOut(wire.NewTxOut(0, script2)) + outputs = append(outputs, &OutputTx{ + OpReturnScript: script2, + }) + + userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 80a5130a..656994a7 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -23,6 +23,7 @@ type MultisigWallet struct { } type OutputTx struct { + OpReturnScript []byte ReceiverAddress string Amount uint64 } diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 8b618a93..73c84149 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -64,24 +64,28 @@ func CreateMultisigTx( // totalOutputAmount in external unit totalOutputAmount := uint64(0) for _, out := range outputs { - // adding the output to tx - decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) - if err != nil { - return nil, "", nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) - } - destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) - if err != nil { - return nil, "", nil, err - } + if len(out.OpReturnScript) > 0 { + msgTx.AddTxOut(wire.NewTxOut(0, out.OpReturnScript)) + } else { + // adding the output to tx + decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) + if err != nil { + return nil, "", nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + } + destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) + if err != nil { + return nil, "", nil, err + } - // adding the destination address and the amount to the transaction - if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { - return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) - } - redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) + // adding the destination address and the amount to the transaction + if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { + return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + } + redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) - msgTx.AddTxOut(redeemTxOut) - totalOutputAmount += out.Amount + msgTx.AddTxOut(redeemTxOut) + totalOutputAmount += out.Amount + } } // check amount of input coins and output coins From a5b01dc96557f6d27a783101af86e03522c482dd Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 20 Aug 2024 20:32:27 +0700 Subject: [PATCH 050/113] update to combine radfi init pool to provide liquidity op_return --- utils/multisig/multisig_test.go | 51 ++++++++++++---------- utils/multisig/op_message.go | 75 ++++++++++----------------------- 2 files changed, 51 insertions(+), 75 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index ef0d7fa1..b596fc64 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -455,15 +455,17 @@ func TestRadFiInitPool(t *testing.T) { }, } // Add RadFi Init pool Message - radfiMsg := RadFiInitPoolMsg { - Fee: 30, - UpperTick: 12345, - LowerTick: -12345, - Min0: 0, - Min1: 10000, + radfiMsg := RadFiProvideLiquidityMsg { + Detail: &RadFiProvideLiquidityDetail{ + Fee: 30, + UpperTick: 12345, + LowerTick: -12345, + Min0: 0, + Min1: 10000, + }, InitPrice: uint256.MustFromDecimal("123456789"), } - script, _ := CreateInitPoolScript(&radfiMsg) + script, _ := CreateProvideLiquidityScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script) outputs = append(outputs, &OutputTx{ OpReturnScript: script, @@ -504,12 +506,12 @@ func TestRadFiInitPool(t *testing.T) { decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) fmt.Println("err decode: ", err) fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - Fee : ", decodedRadFiMessage.InitPoolMsg.Fee) - fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.InitPoolMsg.UpperTick) - fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.InitPoolMsg.LowerTick) - fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.InitPoolMsg.Min0) - fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.InitPoolMsg.Min1) - fmt.Println("decoded message - InitPrice: ", decodedRadFiMessage.InitPoolMsg.InitPrice) + fmt.Println("decoded message - Fee : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Fee) + fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.UpperTick) + fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.LowerTick) + fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min0) + fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min1) + fmt.Println("decoded message - InitPrice: ", decodedRadFiMessage.ProvideLiquidityMsg.InitPrice) } func TestRadFiProvideLiquidity(t *testing.T) { @@ -539,11 +541,13 @@ func TestRadFiProvideLiquidity(t *testing.T) { // Add RadFi Provive Liquidity Message radfiMsg := RadFiProvideLiquidityMsg { - Fee: 30, - UpperTick: 12345, - LowerTick: -12345, - Min0: 0, - Min1: 10000, + Detail: &RadFiProvideLiquidityDetail{ + Fee: 30, + UpperTick: 12345, + LowerTick: -12345, + Min0: 0, + Min1: 10000, + }, } script2, _ := CreateProvideLiquidityScript(&radfiMsg) fmt.Println("OP_RETURN script: ", script2) @@ -586,11 +590,12 @@ func TestRadFiProvideLiquidity(t *testing.T) { decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) fmt.Println("err decode: ", err) fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - Fee : ", decodedRadFiMessage.ProvideLiquidityMsg.Fee) - fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.ProvideLiquidityMsg.UpperTick) - fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.LowerTick) - fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.ProvideLiquidityMsg.Min0) - fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Min1) + fmt.Println("decoded message - Fee : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Fee) + fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.UpperTick) + fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.LowerTick) + fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min0) + fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min1) + fmt.Println("decoded message - InitPrice: ", decodedRadFiMessage.ProvideLiquidityMsg.InitPrice) // get list of Relayer bitcoin an rune UTXOs relayerScriptAddress := signedMsgTx.TxOut[0].PkScript diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index e3275dc8..20c49bc2 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -15,7 +15,6 @@ const ( OP_RUNE_IDENT = txscript.OP_13 OP_BRIDGE_IDENT = txscript.OP_14 - OP_RADFI_INIT_POOL = txscript.OP_11 OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 OP_RADFI_SWAP = txscript.OP_2 OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 @@ -23,21 +22,17 @@ const ( OP_RADFI_INCREASE_LIQUIDITY = txscript.OP_5 ) -type RadFiInitPoolMsg struct { +type RadFiProvideLiquidityDetail struct { Fee uint8 UpperTick int32 LowerTick int32 Min0 uint16 Min1 uint16 - InitPrice *uint256.Int } type RadFiProvideLiquidityMsg struct { - Fee uint8 - UpperTick int32 - LowerTick int32 - Min0 uint16 - Min1 uint16 + Detail *RadFiProvideLiquidityDetail + InitPrice *uint256.Int } type RadFiSwapMsg struct { @@ -66,7 +61,6 @@ type RadFiIncreaseLiquidityMsg struct { type RadFiDecodedMsg struct { Flag byte - InitPoolMsg *RadFiInitPoolMsg ProvideLiquidityMsg *RadFiProvideLiquidityMsg SwapMsg *RadFiSwapMsg WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg @@ -103,25 +97,6 @@ func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) return scripts, nil } -func CreateInitPoolScript(msg *RadFiInitPoolMsg) ([]byte, error) { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(OP_RADFI_IDENT) - builder.AddOp(OP_RADFI_INIT_POOL) - // encode message content - buf := new(bytes.Buffer) - var data = []any{ msg.Fee, msg.UpperTick, msg.LowerTick, msg.Min0, msg.Min1 } - for _, v := range data { - err := binary.Write(buf, binary.BigEndian, v) - if err != nil { - fmt.Println("CreateProvideLiquidityScript encode data failed:", err) - } - } - - return builder.AddData(append(buf.Bytes(), msg.InitPrice.Bytes()...)).Script() -} - func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) { builder := txscript.NewScriptBuilder() @@ -130,7 +105,7 @@ func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) builder.AddOp(OP_RADFI_PROVIDE_LIQUIDITY) // encode message content buf := new(bytes.Buffer) - var data = []any{ msg.Fee, msg.UpperTick, msg.LowerTick, msg.Min0, msg.Min1 } + var data = []any{ msg.Detail.Fee, msg.Detail.UpperTick, msg.Detail.LowerTick, msg.Detail.Min0, msg.Detail.Min1 } for _, v := range data { err := binary.Write(buf, binary.BigEndian, v) if err != nil { @@ -138,6 +113,10 @@ func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) } } + if msg.InitPrice != nil { + return builder.AddData(append(buf.Bytes(), msg.InitPrice.Bytes()...)).Script() + } + return builder.AddData(buf.Bytes()).Script() } @@ -294,36 +273,28 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { // Decode RadFi message switch flag { - case OP_RADFI_INIT_POOL: + case OP_RADFI_PROVIDE_LIQUIDITY: r := bytes.NewReader(payload[:13]) - var provideLiquidityMsg RadFiProvideLiquidityMsg - if err := binary.Read(r, binary.BigEndian, &provideLiquidityMsg); err != nil { - return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_INIT_POOL Read failed") + var provideLiquidityDetail RadFiProvideLiquidityDetail + if err := binary.Read(r, binary.BigEndian, &provideLiquidityDetail); err != nil { + return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_PROVIDE_LIQUIDITY Read failed") } - initPrice := new(uint256.Int).SetBytes(payload[13:]) - return &RadFiDecodedMsg { - Flag : flag, - InitPoolMsg : &RadFiInitPoolMsg{ - Fee : provideLiquidityMsg.Fee, - UpperTick : provideLiquidityMsg.UpperTick, - LowerTick : provideLiquidityMsg.LowerTick, - Min0 : provideLiquidityMsg.Min0, - Min1 : provideLiquidityMsg.Min1, - InitPrice : initPrice, - }, - }, nil - - case OP_RADFI_PROVIDE_LIQUIDITY: - r := bytes.NewReader(payload) - var provideLiquidityMsg RadFiProvideLiquidityMsg - if err := binary.Read(r, binary.BigEndian, &provideLiquidityMsg); err != nil { - return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_PROVIDE_LIQUIDITY Read failed") + if len(payload) > 13 { + return &RadFiDecodedMsg { + Flag : flag, + ProvideLiquidityMsg : &RadFiProvideLiquidityMsg{ + Detail : &provideLiquidityDetail, + InitPrice : new(uint256.Int).SetBytes(payload[13:]), + }, + }, nil } return &RadFiDecodedMsg { Flag : flag, - ProvideLiquidityMsg : &provideLiquidityMsg, + ProvideLiquidityMsg : &RadFiProvideLiquidityMsg{ + Detail : &provideLiquidityDetail, + }, }, nil case OP_RADFI_SWAP: From 9c90b8a56ec0f5c92af6b465eb4a70030aae95d6 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 23 Aug 2024 20:26:08 +0700 Subject: [PATCH 051/113] update encoder decoder for bitcoin bridge xcall message OP_RETURN --- utils/multisig/multisig_test.go | 25 +++++++++++++--- utils/multisig/op_message.go | 51 +++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index e8623105..72609563 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -387,8 +387,18 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { } // Add Bridge Message - message := []byte("{\"msg\":\"Test Bridge Message\"}") - scripts, _ := CreateBridgeMessageScripts(message, 70) + payload, _ := CreateBridgePayload( + 1, + "18403e24f5f5f7cf7a7bae8885d3e1d27ce5fd10", + &XCallMessage{ + Action: "Deposit", + TokenAddress: "0:0", // bitcoin address + To: "0x2.icon/hx39eddef484f6bb08072c59cc0a206e6713fc6d7d", //(receiver) + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", //user + Amount: new(big.Int).SetUint64(1000).Bytes(), + Data: []byte(""), + }) + scripts, _ := CreateBridgeMessageScripts(payload, 76) for i, script := range scripts { fmt.Println("OP_RETURN ", i, " script ", script) outputs = append(outputs, &OutputTx{ @@ -432,8 +442,15 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { // Decode bridge message decodedMessage, err := ReadBridgeMessage(signedMsgTx) fmt.Println("err decode: ", err) - fmt.Println("original message: ", string(message)) - fmt.Println("decoded message : ", string(decodedMessage)) + fmt.Println("-----------decodedMessage---------- ") + fmt.Println("ChainId: ", decodedMessage.ChainId) + fmt.Println("Address: ", decodedMessage.Address) + fmt.Println("Message.Action: ", decodedMessage.Message.Action) + fmt.Println("Message.TokenAddress: ", decodedMessage.Message.TokenAddress) + fmt.Println("Message.From: ", decodedMessage.Message.From) + fmt.Println("Message.To: ", decodedMessage.Message.To) + fmt.Println("Message.Amount: ", decodedMessage.Message.Amount) + fmt.Println("Message.Data: ", decodedMessage.Message.Data) } func TestRadFiInitPool(t *testing.T) { diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index 20c49bc2..fa4b4ace 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -3,11 +3,13 @@ package multisig import ( "bytes" "encoding/binary" + "encoding/hex" "fmt" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/holiman/uint256" + "github.com/icon-project/goloop/common/codec" ) const ( @@ -22,6 +24,15 @@ const ( OP_RADFI_INCREASE_LIQUIDITY = txscript.OP_5 ) +type XCallMessage struct { + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte +} + type RadFiProvideLiquidityDetail struct { Fee uint8 UpperTick int32 @@ -59,6 +70,12 @@ type RadFiIncreaseLiquidityMsg struct { NftId *uint256.Int } +type BridgeDecodedMsg struct { + ChainId uint8 + Address string + Message *XCallMessage +} + type RadFiDecodedMsg struct { Flag byte ProvideLiquidityMsg *RadFiProvideLiquidityMsg @@ -68,6 +85,20 @@ type RadFiDecodedMsg struct { IncreaseLiquidityMsg *RadFiIncreaseLiquidityMsg } +func CreateBridgePayload(chainId uint8, address string, message *XCallMessage) ([]byte, error) { + payload, err := codec.RLP.MarshalToBytes(message) + if err != nil { + return nil, fmt.Errorf("could not marshal message - Error %v", err) + } + + bytesAddress, err := hex.DecodeString(address) + if err != nil { + return nil, fmt.Errorf("could decode string address - Error %v", err) + } + + return append(append(payload, chainId), bytesAddress...), nil +} + func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { var chunk []byte chunks := make([][]byte, 0, len(payload)/partLimit+1) @@ -109,7 +140,7 @@ func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) for _, v := range data { err := binary.Write(buf, binary.BigEndian, v) if err != nil { - fmt.Println("CreateProvideLiquidityScript encode data failed:", err) + return nil, fmt.Errorf("could encode data - Error %v", err) } } @@ -205,14 +236,14 @@ func CreateIncreaseLiquidityScript(msg *RadFiIncreaseLiquidityMsg) ([]byte, erro for _, v := range data { err := binary.Write(buf, binary.BigEndian, v) if err != nil { - fmt.Println("CreateIncreaseLiquidityScript encode data failed:", err) + return nil, fmt.Errorf("could encode data - Error %v", err) } } return builder.AddData(append(buf.Bytes(), msg.NftId.Bytes()...)).Script() } -func ReadBridgeMessage(transaction *wire.MsgTx) ([]byte, error) { +func ReadBridgeMessage(transaction *wire.MsgTx) (*BridgeDecodedMsg, error) { payload := []byte{} for _, output := range transaction.TxOut { tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) @@ -235,10 +266,20 @@ func ReadBridgeMessage(transaction *wire.MsgTx) ([]byte, error) { } if len(payload) == 0 { - return nil, fmt.Errorf("ReadBridgeMessage - no Bridge message found") + return nil, fmt.Errorf("no Bridge message found") + } + + var message XCallMessage + remainData, err := codec.RLP.UnmarshalFromBytes(payload, &message) + if err != nil { + return nil, fmt.Errorf("could not unmarshal message - Error %v", err) } - return payload, nil + return &BridgeDecodedMsg { + ChainId: uint8(remainData[0]), + Address: hex.EncodeToString(remainData[1:]), + Message: &message, + }, nil } func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { From d2da4adc7854bd430ec9a0ed241359d89b1f1249 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 23 Aug 2024 20:30:28 +0700 Subject: [PATCH 052/113] fix x call message encoding for radfi LP after merging code --- relayer/chains/bitcoin/decode_test.go | 12 +++++++----- relayer/chains/bitcoin/helper.go | 10 +++++----- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index b26b34f3..d90473ca 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -37,11 +37,13 @@ func TestGetRuneBalanceAtIndex(t *testing.T) { func TestEncodeToXcallMessage(t *testing.T) { // test1 := multisig.RadFiProvideLiquidityMsg{ - Fee: 30, - UpperTick: -173940, - LowerTick: -178320, - Min0: 0, - Min1: 0, + Detail: &multisig.RadFiProvideLiquidityDetail{ + Fee: 30, + UpperTick: -173940, + LowerTick: -178320, + Min0: 0, + Min1: 0, + }, } protocols := []string{ diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index 1688041c..25289cbb 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -77,17 +77,17 @@ func ToXCallMessage(data interface{}, from, to string, sn uint, protocols []stri mintParams := bitcoinABI.INonfungiblePositionManagerMintParams{ Token0: token0, Token1: token1, - Fee: big.NewInt(int64(dataMint.Fee) * 100), - TickLower: big.NewInt(int64(dataMint.LowerTick)), - TickUpper: big.NewInt(int64(dataMint.UpperTick)), + Fee: big.NewInt(int64(dataMint.Detail.Fee) * 100), + TickLower: big.NewInt(int64(dataMint.Detail.LowerTick)), + TickUpper: big.NewInt(int64(dataMint.Detail.UpperTick)), Amount0Desired: amount0, Amount1Desired: big.NewInt(539580403982610478), Recipient: common.HexToAddress(to), Deadline: big.NewInt(1000000000), } - mintParams.Amount0Min = mulDiv(mintParams.Amount0Desired, big.NewInt(int64(dataMint.Min0)), big.NewInt(1e4)) - mintParams.Amount1Min = mulDiv(mintParams.Amount1Desired, big.NewInt(int64(dataMint.Min1)), big.NewInt(1e4)) + mintParams.Amount0Min = mulDiv(mintParams.Amount0Desired, big.NewInt(int64(dataMint.Detail.Min0)), big.NewInt(1e4)) + mintParams.Amount1Min = mulDiv(mintParams.Amount1Desired, big.NewInt(int64(dataMint.Detail.Min1)), big.NewInt(1e4)) // encode // todo: for init pool From 07ee2ffc1ee46d8b4d3f69ce9fb585a498fb1c89 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 26 Aug 2024 23:10:42 +0700 Subject: [PATCH 053/113] update relayer multisig code and unit test --- utils/multisig/multisig_test.go | 430 +++++++++++++++++++++----------- utils/multisig/tx.go | 42 ++-- 2 files changed, 307 insertions(+), 165 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 72609563..498028a7 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -17,6 +17,12 @@ import ( "github.com/holiman/uint256" ) +const( + TX_FEE = 10000 + RELAYER_MULTISIG_ADDRESS = "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u" + USER_MULTISIG_ADDRESS = "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" +) + func TestGenerateKeys(t *testing.T) { chainParam := &chaincfg.TestNet3Params @@ -84,7 +90,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) + msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, RelayersPKScript: relayersMultisigWallet.PKScript, @@ -164,7 +170,7 @@ func TestMultisigUserSwap(t *testing.T) { userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 333, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) + msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, RelayersPKScript: relayersMultisigWallet.PKScript, @@ -264,7 +270,7 @@ func TestUserRecoveryTimeLock(t *testing.T) { outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, Amount: 1000, }, } @@ -272,8 +278,8 @@ func TestUserRecoveryTimeLock(t *testing.T) { userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, @@ -315,7 +321,7 @@ func TestTransferRune(t *testing.T) { outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, Amount: 1000, }, } @@ -323,8 +329,8 @@ func TestTransferRune(t *testing.T) { userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) // Add Rune transfering // rune id 840000:3, amount 10000 (5 decimals), to output id 0 script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) @@ -381,7 +387,7 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { outputs := []*OutputTx{ { - ReceiverAddress: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + ReceiverAddress: USER_MULTISIG_ADDRESS, Amount: 10000, }, } @@ -394,7 +400,7 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { Action: "Deposit", TokenAddress: "0:0", // bitcoin address To: "0x2.icon/hx39eddef484f6bb08072c59cc0a206e6713fc6d7d", //(receiver) - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", //user + From: USER_MULTISIG_ADDRESS, //user Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), }) @@ -409,8 +415,8 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 8000, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { @@ -459,19 +465,13 @@ func TestRadFiInitPool(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", - OutputIdx: 2, - OutputAmount: 1989000, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, }, } - outputs := []*OutputTx{ - { - ReceiverAddress: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: 10000, - }, - } - // Add RadFi Init pool Message + // OP_RETURN RadFi Init pool Message radfiMsg := RadFiProvideLiquidityMsg { Detail: &RadFiProvideLiquidityDetail{ Fee: 30, @@ -483,16 +483,22 @@ func TestRadFiInitPool(t *testing.T) { InitPrice: uint256.MustFromDecimal("123456789"), } script, _ := CreateProvideLiquidityScript(&radfiMsg) - fmt.Println("OP_RETURN script: ", script) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script, - }) + + outputs := []*OutputTx{ + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + OpReturnScript: script, + }, + } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 8000, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -507,7 +513,7 @@ func TestRadFiInitPool(t *testing.T) { userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS + // COMBINE SIGN signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) var signedTx bytes.Buffer @@ -535,28 +541,27 @@ func TestRadFiProvideLiquidity(t *testing.T) { chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ + { + IsRelayersMultisig: true, + TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", + OutputIdx: 0, + OutputAmount: 1000, + }, { IsRelayersMultisig: false, - TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", + TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", OutputIdx: 2, - OutputAmount: 1989000, + OutputAmount: 1918000, }, - } - - outputs := []*OutputTx{ { - ReceiverAddress: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: 10000, + IsRelayersMultisig: false, + TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", + OutputIdx: 0, + OutputAmount: 1000, }, } - // Add Rune transfering - // rune id 840000:3, amount 10000 (5 decimals), to output id 0 - script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 2) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script1, - }) - // Add RadFi Provive Liquidity Message + // OP_RETURN RadFi Provive Liquidity Message radfiMsg := RadFiProvideLiquidityMsg { Detail: &RadFiProvideLiquidityDetail{ Fee: 30, @@ -566,17 +571,37 @@ func TestRadFiProvideLiquidity(t *testing.T) { Min1: 10000, }, } - script2, _ := CreateProvideLiquidityScript(&radfiMsg) - fmt.Println("OP_RETURN script: ", script2) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script2, - }) + script1, _ := CreateProvideLiquidityScript(&radfiMsg) + // OP_RETURN Rune transfering + // rune id 840000:3, amount 10000 (5 decimals), to output id 4 + script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 4) + + outputs := []*OutputTx{ + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + OpReturnScript: script1, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 20000, + }, + { + OpReturnScript: script2, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 8000, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -635,44 +660,71 @@ func TestRadFiSwap(t *testing.T) { chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ + { + IsRelayersMultisig: true, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 0, + OutputAmount: 1000, + }, { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 3808, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 5, + OutputAmount: 1888000, }, - } - - outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 1000, + IsRelayersMultisig: false, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 4, + OutputAmount: 1000, }, } - // Add Rune transfering - // rune id 840000:3, amount 10000 (5 decimals), to output id 0 - script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script1, - }) - // Add RadFi Swap Message + // OP_RETURN RadFi Swap Message radfiMsg := RadFiSwapMsg { IsExactInOut: true, - TokenOutIndex: 123, + TokenOutIndex: 2, } - script2, _ := CreateSwapScript(&radfiMsg) - fmt.Println("OP_RETURN script: ", script2) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script2, - }) + script1, _ := CreateSwapScript(&radfiMsg) + // OP_RETURN Rune transfering + // rune id 840000:3, amount 4000 (5 decimals), to output id 3 + script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(400000000), 3) + // rune id 840000:3, amount 6000 (5 decimals), to output id 6 + script3, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(600000000), 6) + outputs := []*OutputTx{ + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + OpReturnScript: script1, + }, + { + OpReturnScript: script2, + }, + { + ReceiverAddress: USER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 10000, + }, + { + OpReturnScript: script3, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -713,43 +765,80 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { inputs := []*UTXO{ { - IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 3808, + IsRelayersMultisig: true, + TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", + OutputIdx: 0, + OutputAmount: 1000, }, - } - - outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 1000, + IsRelayersMultisig: true, + TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", + OutputIdx: 4, + OutputAmount: 10000, + }, + { + IsRelayersMultisig: true, + TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", + OutputIdx: 6, + OutputAmount: 1000, + }, + { + IsRelayersMultisig: false, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 5, + OutputAmount: 1867000, }, } - // Add Rune transfering - // rune id 840000:3, amount 10000 (5 decimals), to output id 0 - script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script1, - }) - // Add RadFi Withdraw Liquidity Message + // OP_RETURN RadFi Withdraw Liquidity Message radfiMsg := RadFiWithdrawLiquidityMsg { - RecipientIndex: 123, + RecipientIndex: 2, LiquidityValue: uint256.MustFromDecimal("123456"), NftId: uint256.MustFromDecimal("123456789"), } - script2, _ := CreateWithdrawLiquidityScript(&radfiMsg) - fmt.Println("OP_RETURN script: ", script2) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script2, - }) + script1, _ := CreateWithdrawLiquidityScript(&radfiMsg) + // OP_RETURN Rune transfering + // rune id 840000:3, amount 2500 (5 decimals), to output id 3 + script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(250000000), 4) + // rune id 840000:3, amount 3500 (5 decimals), to output id 7 + script3, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(350000000), 7) + outputs := []*OutputTx{ + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + OpReturnScript: script1, + }, + { + ReceiverAddress: USER_MULTISIG_ADDRESS, + Amount: 5000, + }, + { + OpReturnScript: script2, + }, + { + ReceiverAddress: USER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 5000, + }, + { + OpReturnScript: script3, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -790,43 +879,81 @@ func TestRadFiCollectFees(t *testing.T) { chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ + { + IsRelayersMultisig: true, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 0, + OutputAmount: 1000, + }, + { + IsRelayersMultisig: true, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 5, + OutputAmount: 5000, + }, + { + IsRelayersMultisig: true, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 7, + OutputAmount: 1000, + }, { IsRelayersMultisig: false, - TxHash: "9c07074364e5ce367f4d07a2657337a60684730158fd093ab6cb694f75984cb9", - OutputIdx: 1, - OutputAmount: 4900, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 8, + OutputAmount: 1856000, }, } + // OP_RETURN RadFi Collect Fees + radfiMsg := RadFiCollectFeesMsg { + RecipientIndex: 2, + NftId: uint256.MustFromDecimal("123456789"), + } + script1, _ := CreateCollectFeesScript(&radfiMsg) + // OP_RETURN Rune transfering + // rune id 840000:3, amount 500 (5 decimals), to output id 4 + script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(50000000), 4) + // rune id 840000:3, amount 3000 (5 decimals), to output id 7 + script3, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(300000000), 7) + outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + OpReturnScript: script1, + }, + { + ReceiverAddress: USER_MULTISIG_ADDRESS, + Amount: 2000, + }, + { + OpReturnScript: script2, + }, + { + ReceiverAddress: USER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 3000, + }, + { + OpReturnScript: script3, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, Amount: 1000, }, } - // Add Rune transfering - // rune id 840000:3, amount 10000 (5 decimals), to output id 0 - script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script1, - }) - - // Add RadFi Withdraw Liquidity Message - radfiMsg := RadFiCollectFeesMsg { - RecipientIndex: 123, - NftId: uint256.MustFromDecimal("123456789"), - } - script2, _ := CreateCollectFeesScript(&radfiMsg) - fmt.Println("OP_RETURN script: ", script2) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script2, - }) userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, @@ -866,44 +993,63 @@ func TestRadFiIncreaseLiquidity(t *testing.T) { chainParam := &chaincfg.TestNet3Params inputs := []*UTXO{ + { + IsRelayersMultisig: true, + TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", + OutputIdx: 0, + OutputAmount: 1000, + }, { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 3808, + TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", + OutputIdx: 8, + OutputAmount: 1845000, }, - } - - outputs := []*OutputTx{ { - ReceiverAddress: "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u", - Amount: 1000, + IsRelayersMultisig: false, + TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", + OutputIdx: 0, + OutputAmount: 1000, }, } - // Add Rune transfering - // rune id 840000:3, amount 10000 (5 decimals), to output id 0 - script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script1, - }) - // Add RadFi Withdraw Liquidity Message + // OP_RETURN RadFi Increase Liquidity Message radfiMsg := RadFiIncreaseLiquidityMsg { Min0: 0, Min1: 10000, NftId: uint256.MustFromDecimal("123456789"), } - script2, _ := CreateIncreaseLiquidityScript(&radfiMsg) - fmt.Println("OP_RETURN script: ", script2) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script2, - }) + script1, _ := CreateIncreaseLiquidityScript(&radfiMsg) + // OP_RETURN Rune transfering + // rune id 840000:3, amount 500 (5 decimals), to output id 4 + script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(50000000), 4) + + outputs := []*OutputTx{ + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + { + OpReturnScript: script1, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 20000, + }, + { + OpReturnScript: script2, + }, + { + ReceiverAddress: RELAYER_MULTISIG_ADDRESS, + Amount: 1000, + }, + } userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, 200, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + changeReceiverAddress := USER_MULTISIG_ADDRESS + msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := TapSigParams { TxSigHashes: txSigHashes, diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 73c84149..e61bb2cd 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -20,7 +20,7 @@ import ( func CreateMultisigTx( inputs []*UTXO, outputs []*OutputTx, - feePerOutput uint64, + txFee uint64, relayersMultisigWallet *MultisigWallet, userMultisigWallet *MultisigWallet, chainParam *chaincfg.Params, @@ -62,7 +62,7 @@ func CreateMultisigTx( // add TxOuts into raw tx // totalOutputAmount in external unit - totalOutputAmount := uint64(0) + totalOutputAmount := txFee for _, out := range outputs { if len(out.OpReturnScript) > 0 { msgTx.AddTxOut(wire.NewTxOut(0, out.OpReturnScript)) @@ -70,7 +70,7 @@ func CreateMultisigTx( // adding the output to tx decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) if err != nil { - return nil, "", nil, fmt.Errorf("CreateRawExternalTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) + return nil, "", nil, fmt.Errorf("CreateMultisigTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) } destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) if err != nil { @@ -78,10 +78,10 @@ func CreateMultisigTx( } // adding the destination address and the amount to the transaction - if out.Amount <= feePerOutput || out.Amount-feePerOutput < MIN_SAT { - return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Output amount %v must greater than fee %v", out.Amount, feePerOutput) + if out.Amount < MIN_SAT { + return nil, "", nil, fmt.Errorf("CreateMultisigTx - Output amount %v must greater than minimum UTXO value %v", out.Amount, MIN_SAT) } - redeemTxOut := wire.NewTxOut(int64(out.Amount-feePerOutput), destinationAddrByte) + redeemTxOut := wire.NewTxOut(int64(out.Amount), destinationAddrByte) msgTx.AddTxOut(redeemTxOut) totalOutputAmount += out.Amount @@ -90,29 +90,26 @@ func CreateMultisigTx( // check amount of input coins and output coins if totalInputAmount < totalOutputAmount { - return nil, "", nil, fmt.Errorf("[CreateRawExternalTx-BTC] Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + return nil, "", nil, fmt.Errorf("CreateMultisigTx - Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) } // calculate the change output - changeAmt := uint64(0) if totalInputAmount > totalOutputAmount { - // adding the output to tx - decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) - if err != nil { - return nil, "", nil, err - } - destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) - if err != nil { - return nil, "", nil, err - } - - // adding the destination address and the amount to the transaction - changeAmt = totalInputAmount - totalOutputAmount + changeAmt := totalInputAmount - totalOutputAmount if changeAmt >= MIN_SAT { + // adding the output to tx + decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) + if err != nil { + return nil, "", nil, err + } + destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) + if err != nil { + return nil, "", nil, err + } + + // adding the destination address and the amount to the transaction redeemTxOut := wire.NewTxOut(int64(changeAmt), destinationAddrByte) msgTx.AddTxOut(redeemTxOut) - } else { - changeAmt = 0 } } @@ -122,7 +119,6 @@ func CreateMultisigTx( return nil, "", nil, err } hexRawTx := hex.EncodeToString(rawTxBytes.Bytes()) - txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) return msgTx, hexRawTx, txSigHashes, nil From d6655922f3917e2199c30c21025953cbab7761e7 Mon Sep 17 00:00:00 2001 From: Shall Date: Tue, 27 Aug 2024 16:09:18 +0700 Subject: [PATCH 054/113] feat: move hardcode constant to config file --- cmd/bitcoin.go | 18 -- cmd/root.go | 1 - config.yaml | 47 +++-- ...hx9a530643c071f15e8411eadd9f0b2ee5a871d37f | 22 +++ ...30643c071f15e8411eadd9f0b2ee5a871d37f.pass | 1 + relayer/chains/bitcoin/client.go | 29 ++- relayer/chains/bitcoin/master.go | 6 +- relayer/chains/bitcoin/provider.go | 175 ++++++++++++------ relayer/chains/bitcoin/slave.go | 4 +- relayer/chains/icon/keys.go | 21 ++- 10 files changed, 208 insertions(+), 116 deletions(-) delete mode 100644 cmd/bitcoin.go create mode 100644 keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f create mode 100644 keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass diff --git a/cmd/bitcoin.go b/cmd/bitcoin.go deleted file mode 100644 index c9d56a88..00000000 --- a/cmd/bitcoin.go +++ /dev/null @@ -1,18 +0,0 @@ -package cmd - -import ( - "github.com/icon-project/centralized-relay/relayer/chains/bitcoin" - "github.com/spf13/cobra" -) - -func bitcoinCmd(a *appState) *cobra.Command { - bitcoinCmd := &cobra.Command{ - Use: "bitcoin", - Short: "Run Bitcoin Relayer", - Run: func(cmd *cobra.Command, args []string) { - bitcoin.RunApp() - }, - } - - return bitcoinCmd -} diff --git a/cmd/root.go b/cmd/root.go index 1c9dbdd9..6c59a737 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -159,7 +159,6 @@ func NewRootCmd(log *zap.Logger) *cobra.Command { dbCmd(a), keystoreCmd(a), contractCMD(a), - bitcoinCmd(a), ) return rootCmd } diff --git a/config.yaml b/config.yaml index e1118940..b865069c 100644 --- a/config.yaml +++ b/config.yaml @@ -2,34 +2,41 @@ global: timeout: 10s kms-key-id: f5c550ca-a6f2-4597-895c-4846ab8e4ad2 chains: - # icon: - # type: icon - # value: - # rpc-url: https://lisbon.net.solidwallet.io/api/v3/ - # address: hxb6b5791be0b5ef67063b3c10b840fb81514db2fd - # start-height: 42066559 - # step-min: 1 - # step-limit: 2000000000000000000 - # contracts: - # xcall: cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 - # connection: cx8d02efb10359105f7e033149556eaea531a3740e - # network-id: 2 - # finality-block: 10 - # nid: 0x2.icon + icon: + type: icon + value: + rpc-url: https://lisbon.net.solidwallet.io/api/v3/ + address: hx9a530643c071f15e8411eadd9f0b2ee5a871d37f + start-height: 42842964 + step-min: 1 + step-limit: 2000000000000000000 + contracts: + xcall: cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 + connection: cx577f5e756abd89cbcba38a58508b60a12754d2f5 + network-id: 2 + finality-block: 10 + nid: 0x2.icon bitcoin: type: bitcoin value: - rpc-url: thrumming-light-mountain.btc.quiknode.pro:443/9010506d85a546fd92e68fff9b9af3478f0708a6/ + rpc-url: stylish-white-paper.btc-testnet.quiknode.pro/f87ecf84754d9daf8cf45b0334ba3fee9b356db6/ rpc-user: 123 rpc-password: 123 - address: tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd + address: tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su + protocals: + - cx577f5e756abd89cbcba38a58508b60a12754d2f5 + # - cxf5a0b146af1572e44775a40ef06c5a39b143ed1e unisat-url: https://open-api.unisat.io/v1/indexer - start-height: 847735 - network-id: 1 + # start-height: 2874137 + start-height: 2874459 + network-id: 2 + op-code: 0x5e finality-block: 10 - nid: 0x1.btc + nid: 0x2.btc chain-name: bitcoin - mode: slave + mode: master + slave-server-1: http://localhost:8081 + slave-server-2: http://localhost:8082 port: 8082 api-key: key diff --git a/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f b/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f new file mode 100644 index 00000000..c9fd2507 --- /dev/null +++ b/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f @@ -0,0 +1,22 @@ +{ + "version": 3, + "id": "c324d6d7-b1ed-41dd-bb7c-0a014628f121", + "address": "hx9a530643c071f15e8411eadd9f0b2ee5a871d37f", + "crypto": { + "ciphertext": "7353d2c1332d96511fb6ad5c74f710a6c30135431a04128fde1ed36dd5e7414c", + "cipherparams": { + "iv": "b5aa163de4de082065169a5acf5eb676" + }, + "cipher": "aes-128-ctr", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "salt": "7240a6dbcff5290551ca7a760f3c69fc6489b47fdc500fa803cc6e626865e253", + "n": 16384, + "r": 8, + "p": 1 + }, + "mac": "d6dc6d8f4cb4d6f703976eb79c92029b856230f0bb8ee142ac7af368ca324345" + }, + "coinType": "icx" +} \ No newline at end of file diff --git a/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass b/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass new file mode 100644 index 00000000..87b7e2fc --- /dev/null +++ b/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass @@ -0,0 +1 @@ +S@ng123!@# \ No newline at end of file diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 6d087aff..0abd0652 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -3,6 +3,7 @@ package bitcoin import ( "bytes" "context" + "fmt" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/btcutil" @@ -63,12 +64,13 @@ func newClient(ctx context.Context, rpcUrl string, user string, password string, // query block height func (c *Client) GetLatestBlockHeight(ctx context.Context) (uint64, error) { // Get the current block height - blockCount, err := c.client.GetBlockCount() - if err != nil { - return 0, err - } + // blockCount, err := c.client.GetBlockCount() + // if err != nil { + // return 0, err + // } - return uint64(blockCount), nil + // return uint64(blockCount), nil + return 2874461, nil } // get transaction reciept @@ -112,19 +114,31 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch meetRequirement2 := 0 for i := param.StartHeight; i <= param.EndHeight; i++ { + blockHash, err := c.client.GetBlockHash(int64(i)) if err != nil { return nil, err } + // Print the block hash to a string + blockHashStr := fmt.Sprintf("%v", blockHash) + c.log.Info("Block Hash", zap.String("blockHash", blockHashStr)) + block, err := c.client.GetBlock(blockHash) + if err != nil { + return nil, err + } // loop thru transactions for _, tx := range block.Transactions { // loop thru tx output for _, txOutput := range tx.TxOut { if len(txOutput.PkScript) > 2 { + // check OP_RETURN - if txOutput.PkScript[0] == txscript.OP_RETURN && txOutput.PkScript[1] == byte(param.OPReturnPrefix) { + if txOutput.PkScript[0] == txscript.OP_RETURN && (txOutput.PkScript[1] == byte(param.OPReturnPrefix) || txOutput.PkScript[1] == byte(param.OPReturnPrefix)) { + c.log.Info("TxSearch txhash", + zap.String("txhash", tx.TxHash().String()), + ) meetRequirement1++ } @@ -134,6 +148,9 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch } if meetRequirement2*meetRequirement1 != 0 { + c.log.Info("TxSearch found op_return", + zap.Uint64("height", i), + ) res = append(res, &TxSearchRes{Height: i, Tx: tx}) break } diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index ef3fe8a9..c31d9ce5 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -11,9 +11,9 @@ import ( "sync" ) -func startMaster() { +func startMaster(c *Config) { http.HandleFunc("/execute", handleExecute) - port := os.Getenv("PORT") + port := c.Port server := &http.Server{ Addr: ":" + port, Handler: nil, @@ -29,7 +29,7 @@ func startMaster() { } func handleExecute(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { + if r.Method != http.MethodGet { http.Error(w, "Invalid request method", http.StatusMethodNotAllowed) return } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 480a7857..51ef4cc4 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -5,13 +5,11 @@ import ( "context" "fmt" "math/big" - "os" "runtime" "sync" "time" wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" - "github.com/btcsuite/btcd/txscript" sdkTypes "github.com/cosmos/cosmos-sdk/types" "github.com/icon-project/centralized-relay/relayer/chains/wasm/types" @@ -20,7 +18,7 @@ import ( "github.com/icon-project/centralized-relay/relayer/provider" relayTypes "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" - "github.com/icon-project/icon-bridge/common/codec" + "github.com/icon-project/goloop/common/codec" jsoniter "github.com/json-iterator/go" "go.uber.org/zap" ) @@ -30,34 +28,43 @@ import ( var ( BTCToken = "0:0" MethodDeposit = "Deposit" + MasterMode = "master" + SlaveMode = "slave" ) +var chainIdToName = map[uint8]string{ + 1: "0x1.icon", + 2: "0x1.btc", + 3: "0x2.icon", + 4: "0x2.btc", + // Add more mappings as needed +} + type Provider struct { logger *zap.Logger cfg *Config client IClient LastSavedHeightFunc func() uint64 LastSerialNumFunc func() *big.Int - multisigAddrScript []byte // + multisigAddrScript []byte assetManagerAddrIcon string bearToken string + httpServer chan struct{} } type Config struct { provider.CommonConfig `json:",inline" yaml:",inline"` - UniSatURL string `json:"unisat-url" yaml:"unisat-url"` - Type string `json:"type" yaml:"type"` - User string `json:"rpc-user" yaml:"rpc-user"` - Password string `json:"rpc-password" yaml:"rpc-password"` -} - -func RunApp() { - goEnv := os.Getenv("GO_ENV") - if goEnv == "master" { - startMaster() - } else { - startSlave() - } + OpCode int `json:"op-code" yaml:"op-code"` + UniSatURL string `json:"unisat-url" yaml:"unisat-url"` + Type string `json:"type" yaml:"type"` + User string `json:"rpc-user" yaml:"rpc-user"` + Password string `json:"rpc-password" yaml:"rpc-password"` + Protocals []string `yaml:"protocals"` + Mode string `json:"mode" yaml:"mode"` + SlaveServer1 string `json:"slave-server-1" yaml:"slave-server-1"` + SlaveServer2 string `json:"slave-server-2" yaml:"slave-server-2"` + Port string `json:"port" yaml:"port"` + ApiKey string `json:"api-key" yaml:"api-key"` } // NewProvider returns new Icon provider @@ -77,11 +84,49 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri c.ChainName = chainName c.HomeDir = homepath - return &Provider{ - logger: log.With(zap.Stringp("nid", &c.NID), zap.Stringp("name", &c.ChainName)), - cfg: c, - client: client, - }, nil + p := &Provider{ + logger: log.With(zap.Stringp("nid", &c.NID), zap.Stringp("name", &c.ChainName)), + cfg: c, + client: client, + LastSerialNumFunc: func() *big.Int { return big.NewInt(0) }, + httpServer: make(chan struct{}), + } + // Run an http server to help btc interact each others + go func() { + if c.Mode == MasterMode { + startMaster(c) + } else { + startSlave(c) + } + close(p.httpServer) + }() + + return p, nil +} + +func (p *Provider) CallSlaves(txId string) []string { + resultChan := make(chan []string) + go func() { + responses := make(chan string, 2) + var wg sync.WaitGroup + wg.Add(2) + + go requestPartialSign(p.cfg.SlaveServer1, txId, responses, &wg) + go requestPartialSign(p.cfg.SlaveServer2, txId, responses, &wg) + + go func() { + wg.Wait() + close(responses) + }() + + var results []string + for res := range responses { + results = append(results, res) + } + resultChan <- results + }() + + return <-resultChan } func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { @@ -123,7 +168,7 @@ func (p *Provider) Wallet() error { } func (p *Provider) Type() string { - return "bitcoin" + return p.cfg.ChainName } func (p *Provider) Config() provider.Config { @@ -170,15 +215,21 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { p.logger.Info("starting to route message", zap.Any("message", message)) - res, err := p.call(ctx, message) - if err != nil { - return err - } + + // TODO: Implement logic to route message to bitcoin network + + // p.cfg.Mode == MasterMode + // p.CallSlaves(txid) + // build bitcoin transaction + // send icon tx id to slaves get the multisig signature + // collect signature + // trigger call funtion to broadcast transaction to bitcoin network + // seq := p.wallet.GetSequence() + 1 // if err := p.wallet.SetSequence(seq); err != nil { // p.logger.Error("failed to set sequence", zap.Error(err)) // } - p.waitForTxResult(ctx, message.MessageKey(), res, callback) + // p.waitForTxResult(ctx, message.MessageKey(), res, callback) return nil } @@ -221,6 +272,7 @@ func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (strin } func (p *Provider) sendMessage(ctx context.Context, msgs ...sdkTypes.Msg) (string, error) { + // return p.prepareAndPushTxToMemPool(ctx, p.wallet.GetAccountNumber(), p.wallet.GetSequence(), msgs...) return "", nil } @@ -487,20 +539,20 @@ func (p *Provider) ExecuteRollback(ctx context.Context, sn *big.Int) error { // todo: func (p *Provider) getStartHeight(latestHeight, lastSavedHeight uint64) (uint64, error) { - //startHeight := lastSavedHeight - //if p.cfg.StartHeight > 0 && p.cfg.StartHeight < latestHeight { - // return p.cfg.StartHeight, nil - //} - // - //if startHeight > latestHeight { - // return 0, fmt.Errorf("last saved height cannot be greater than latest height") - //} - // - //if startHeight != 0 && startHeight < latestHeight { - // return startHeight, nil - //} + startHeight := lastSavedHeight + if p.cfg.StartHeight > 0 && p.cfg.StartHeight < latestHeight { + return p.cfg.StartHeight, nil + } + + if startHeight > latestHeight { + return 0, fmt.Errorf("last saved height cannot be greater than latest height") + } - return lastSavedHeight, nil + if startHeight != 0 && startHeight < latestHeight { + return startHeight, nil + } + + return latestHeight, nil } func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64) <-chan *HeightRange { @@ -549,10 +601,11 @@ func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, hei } func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { + var ( // todo: query from provide.config multisigAddress = p.cfg.Address - preFixOP = txscript.OP_13 + preFixOP = p.cfg.OpCode ) multiSigScript, err := p.client.DecodeAddress(multisigAddress) @@ -579,17 +632,16 @@ func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRan func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, error) { // handle for bitcoin bridge // decode message from OP_RETURN - decodeMessage, err := multisig.ReadBridgeMessage(tx.Tx) + p.logger.Info("parseMessageFromTx", + zap.Uint64("height", tx.Height)) + + bridgeMessage, err := multisig.ReadBridgeMessage(tx.Tx) if err != nil { return nil, err } + messageInfo := bridgeMessage.Message - // check if it is Deposit request - messageInfo := XCallMessage{} - _, err = codec.RLP.UnmarshalFromBytes(decodeMessage, &messageInfo) - if err != nil { - fmt.Printf("\n not a xcall format request \n") - } else if messageInfo.Action == MethodDeposit && messageInfo.To == p.assetManagerAddrIcon { + if messageInfo.Action == MethodDeposit && messageInfo.To == p.assetManagerAddrIcon { // maybe get this function name from cf file // todo verify transfer amount match in calldata if it // call 3rd to check rune amount @@ -651,14 +703,23 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err // todo: handle for rad fi + // TODO: call xcallformat and then replace to data + + from := p.cfg.NID + "/" + p.cfg.Address + decodeMessage, _ := codec.RLP.MarshalToBytes(messageInfo) + data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Address, uint(tx.Height), p.cfg.Protocals) + return &relayTypes.Message{ // todo: - Dst: "icon", - Src: messageInfo.From, - Sn: p.LastSerialNumFunc(), - Data: decodeMessage, + Dst: "0x2.icon", + // Dst: chainIdToName[bridgeMessage.ChainId], + Src: p.NID(), + // Sn: p.LastSerialNumFunc(), + Sn: new(big.Int).SetUint64(tx.Height<<32 + 4), // TODO should implement it + Data: data, MessageHeight: tx.Height, - EventType: events.CallMessage, + EventType: events.EmitMessage, + // ReqID: new(big.Int).SetUint64(tx.Height<<32 + 1), // TODO: should implement it }, nil } @@ -678,11 +739,11 @@ func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayT zap.String("event_type", msg.EventType), ) messages = append(messages, &relayTypes.BlockInfo{ - Height: resultTx.Height, - //Messages: msgs, + Height: resultTx.Height, + Messages: []*relayTypes.Message{msg}, }) } - return nil, nil + return messages, nil } func (p *Provider) getRawContractMessage(message *relayTypes.Message) (wasmTypes.RawContractMessage, error) { diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index 02b3bf08..80cc4d93 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -7,9 +7,9 @@ import ( "os" ) -func startSlave() { +func startSlave(c *Config) { http.HandleFunc("/", handleRoot) - port := os.Getenv("PORT") + port := c.Port server := &http.Server{ Addr: ":" + port, Handler: nil, diff --git a/relayer/chains/icon/keys.go b/relayer/chains/icon/keys.go index 4dcc10ca..e6e92f0f 100644 --- a/relayer/chains/icon/keys.go +++ b/relayer/chains/icon/keys.go @@ -15,19 +15,22 @@ func (p *Provider) RestoreKeystore(ctx context.Context) error { if err != nil { return err } - keystoreJson, err := p.kms.Decrypt(ctx, keystoreCipher) - if err != nil { - return err - } + + // TODO: Should remove comment this + // keystoreJson, err := p.kms.Decrypt(ctx, keystoreCipher) + // if err != nil { + // return err + // } authCipher, err := os.ReadFile(path + ".pass") if err != nil { return err } - secret, err := p.kms.Decrypt(ctx, authCipher) - if err != nil { - return err - } - wallet, err := wallet.NewFromKeyStore(keystoreJson, secret) + // TODO: Should remove comment this + // secret, err := p.kms.Decrypt(ctx, authCipher) + // if err != nil { + // return err + // } + wallet, err := wallet.NewFromKeyStore(keystoreCipher, authCipher) if err != nil { return err } From 154d4257f7259273a6a613dd47156aa19d109a4e Mon Sep 17 00:00:00 2001 From: homelander Date: Wed, 28 Aug 2024 11:38:20 +0700 Subject: [PATCH 055/113] added tx index --- relayer/chains/bitcoin/client.go | 6 +++--- relayer/chains/bitcoin/provider.go | 2 +- relayer/chains/bitcoin/types.go | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 0abd0652..76599fed 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -129,13 +129,13 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch return nil, err } // loop thru transactions - for _, tx := range block.Transactions { + for j, tx := range block.Transactions { // loop thru tx output for _, txOutput := range tx.TxOut { if len(txOutput.PkScript) > 2 { // check OP_RETURN - if txOutput.PkScript[0] == txscript.OP_RETURN && (txOutput.PkScript[1] == byte(param.OPReturnPrefix) || txOutput.PkScript[1] == byte(param.OPReturnPrefix)) { + if txOutput.PkScript[0] == txscript.OP_RETURN && txOutput.PkScript[1] == byte(param.OPReturnPrefix) { c.log.Info("TxSearch txhash", zap.String("txhash", tx.TxHash().String()), ) @@ -151,7 +151,7 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch c.log.Info("TxSearch found op_return", zap.Uint64("height", i), ) - res = append(res, &TxSearchRes{Height: i, Tx: tx}) + res = append(res, &TxSearchRes{Height: i, Tx: tx, TxIndex: uint64(j)}) break } } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 51ef4cc4..985553b1 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -715,7 +715,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err // Dst: chainIdToName[bridgeMessage.ChainId], Src: p.NID(), // Sn: p.LastSerialNumFunc(), - Sn: new(big.Int).SetUint64(tx.Height<<32 + 4), // TODO should implement it + Sn: new(big.Int).SetUint64(tx.Height<<32 + tx.TxIndex), Data: data, MessageHeight: tx.Height, EventType: events.EmitMessage, diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index e6df91a1..6a8a93e3 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -29,6 +29,7 @@ type TxSearchParam struct { type TxSearchRes struct { Tx *wire.MsgTx Height uint64 + TxIndex uint64 } // HightRange is a struct to represent a range of heights From 48476648bb17b626139c271982ee81d89bcfb380 Mon Sep 17 00:00:00 2001 From: Shall Date: Fri, 30 Aug 2024 11:32:31 +0700 Subject: [PATCH 056/113] feat: add lvdb for provider and test for provider route --- relayer/chains/bitcoin/provider.go | 62 ++++++++++++---- relayer/chains/bitcoin/provider_route_test.go | 73 +++++++++++++++++++ 2 files changed, 121 insertions(+), 14 deletions(-) create mode 100644 relayer/chains/bitcoin/provider_route_test.go diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 985553b1..507b7156 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -3,6 +3,7 @@ package bitcoin import ( "bytes" "context" + "encoding/json" "fmt" "math/big" "runtime" @@ -12,6 +13,8 @@ import ( wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" sdkTypes "github.com/cosmos/cosmos-sdk/types" + "path/filepath" + "github.com/icon-project/centralized-relay/relayer/chains/wasm/types" "github.com/icon-project/centralized-relay/relayer/events" "github.com/icon-project/centralized-relay/relayer/kms" @@ -20,6 +23,7 @@ import ( "github.com/icon-project/centralized-relay/utils/multisig" "github.com/icon-project/goloop/common/codec" jsoniter "github.com/json-iterator/go" + "github.com/syndtr/goleveldb/leveldb" "go.uber.org/zap" ) @@ -30,6 +34,7 @@ var ( MethodDeposit = "Deposit" MasterMode = "master" SlaveMode = "slave" + BtcSlaveDB = "btc_slave.db" ) var chainIdToName = map[uint8]string{ @@ -50,6 +55,7 @@ type Provider struct { assetManagerAddrIcon string bearToken string httpServer chan struct{} + db *leveldb.DB } type Config struct { @@ -76,8 +82,18 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri return nil, err } + // Create the database file path + dbPath := filepath.Join(homepath+"/data", BtcSlaveDB) + + // Open the database, creating it if it doesn't exist + db, err := leveldb.OpenFile(dbPath, nil) + if err != nil { + return nil, fmt.Errorf("failed to open or create database: %v", err) + } + client, err := newClient(ctx, c.RPCUrl, c.User, c.Password, true, false, log) if err != nil { + db.Close() // Close the database if client creation fails return nil, fmt.Errorf("failed to create new client: %v", err) } @@ -90,6 +106,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri client: client, LastSerialNumFunc: func() *big.Int { return big.NewInt(0) }, httpServer: make(chan struct{}), + db: db, // Add the database to the Provider } // Run an http server to help btc interact each others go func() { @@ -216,20 +233,38 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { p.logger.Info("starting to route message", zap.Any("message", message)) - // TODO: Implement logic to route message to bitcoin network + if p.cfg.Mode == SlaveMode { + // Store the message in LevelDB + messageJSON, err := json.Marshal(message) + if err != nil { + return fmt.Errorf("failed to marshal message: %v", err) + } + // TODO: replace key with txid + key := []byte(fmt.Sprintf("bitcoin_message_%s", message.Sn.String())) + err = p.db.Put(key, messageJSON, nil) + if err != nil { + return fmt.Errorf("failed to store message in LevelDB: %v", err) + } + + p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) + return nil + } else if p.cfg.Mode == MasterMode { + // TODO: Implement logic to build bitcoin transaction using signatures + } - // p.cfg.Mode == MasterMode - // p.CallSlaves(txid) - // build bitcoin transaction - // send icon tx id to slaves get the multisig signature - // collect signature - // trigger call funtion to broadcast transaction to bitcoin network + // MasterMode logic + // txid := "example_txid" // Replace with actual txid generation logic + // signatures := p.CallSlaves(txid) + + // TODO: Implement logic to build bitcoin transaction using signatures + + // TODO: Broadcast transaction to bitcoin network + + // After successful broadcast, remove the message from LevelDB if it exists + + // TODO: Implement proper callback handling + // callback(message.MessageKey(), txResponse, nil) - // seq := p.wallet.GetSequence() + 1 - // if err := p.wallet.SetSequence(seq); err != nil { - // p.logger.Error("failed to set sequence", zap.Error(err)) - // } - // p.waitForTxResult(ctx, message.MessageKey(), res, callback) return nil } @@ -710,7 +745,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Address, uint(tx.Height), p.cfg.Protocals) return &relayTypes.Message{ - // todo: + // TODO: Dst: "0x2.icon", // Dst: chainIdToName[bridgeMessage.ChainId], Src: p.NID(), @@ -719,7 +754,6 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err Data: data, MessageHeight: tx.Height, EventType: events.EmitMessage, - // ReqID: new(big.Int).SetUint64(tx.Height<<32 + 1), // TODO: should implement it }, nil } diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go new file mode 100644 index 00000000..65909674 --- /dev/null +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -0,0 +1,73 @@ +package bitcoin + +import ( + "context" + "encoding/json" + "fmt" + "math/big" + "os" + "path/filepath" + "testing" + + "github.com/icon-project/centralized-relay/relayer/events" + "github.com/icon-project/centralized-relay/relayer/types" + "github.com/stretchr/testify/assert" + "github.com/syndtr/goleveldb/leveldb" + "go.uber.org/zap" +) + +func TestProvider_Route(t *testing.T) { + // Setup + tempDir, err := os.MkdirTemp("", "bitcoin_provider_test") + assert.NoError(t, err) + defer os.RemoveAll(tempDir) + + dbPath := filepath.Join(tempDir, "test.db") + db, err := leveldb.OpenFile(dbPath, nil) + assert.NoError(t, err) + defer db.Close() + + logger, _ := zap.NewDevelopment() + provider := &Provider{ + logger: logger, + cfg: &Config{Mode: SlaveMode}, + db: db, + } + + // Create a test message + testMessage := &types.Message{ + Dst: "destination", + Src: "source", + Sn: big.NewInt(123), + Data: []byte("test data"), + MessageHeight: 456, + EventType: events.EmitMessage, + } + + // Test storing the message + err = provider.Route(context.Background(), testMessage, nil) + assert.NoError(t, err) + + // Test retrieving the message + key := []byte(fmt.Sprintf("bitcoin_message_%s", testMessage.Sn.String())) + storedData, err := db.Get(key, nil) + assert.NoError(t, err) + + var retrievedMessage types.Message + err = json.Unmarshal(storedData, &retrievedMessage) + assert.NoError(t, err) + + assert.Equal(t, testMessage.Dst, retrievedMessage.Dst) + assert.Equal(t, testMessage.Src, retrievedMessage.Src) + assert.Equal(t, testMessage.Sn.String(), retrievedMessage.Sn.String()) + assert.Equal(t, testMessage.Data, retrievedMessage.Data) + assert.Equal(t, testMessage.MessageHeight, retrievedMessage.MessageHeight) + assert.Equal(t, testMessage.EventType, retrievedMessage.EventType) + + // Test deleting the message + err = db.Delete(key, nil) + assert.NoError(t, err) + + _, err = db.Get(key, nil) + assert.Error(t, err) // Should return an error as the key no longer exists +} From d60f7f8d69b94998a0e0521d9bab049789691fb7 Mon Sep 17 00:00:00 2001 From: homelander Date: Sat, 31 Aug 2024 20:53:33 +0700 Subject: [PATCH 057/113] added example --- relayer/chains/bitcoin/decode_test.go | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index d90473ca..602c4552 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -22,6 +22,37 @@ func TestDecode(t *testing.T) { } fmt.Println(depositInfo) + fmt.Println("\n =============") + + // test decode 2 + data, _ = hex.DecodeString("f9011d01b90119f90116b33078322e69636f6e2f637866633836656537363837653162663638316235353438623236363738343434383563306537313932b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375821e8501b852f8508a5769746864726177546f83303a30b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a78357368767637737564f848b8463078322e6274632f74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375") + withdrawInfoWrapper := CSMessage{} + _, err = codec.RLP.UnmarshalFromBytes(data, &withdrawInfoWrapper) + if err != nil { + log.Fatal(err.Error()) + } + + fmt.Println(withdrawInfoWrapper) + fmt.Println("\n =============") + + // withdraw info data + withdrawInfoWrapperV2 := CSMessageRequestV2{} + _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapper.Payload, &withdrawInfoWrapperV2) + if err != nil { + log.Fatal(err.Error()) + } + + fmt.Println(withdrawInfoWrapperV2) + fmt.Println("\n =============") + + // withdraw info + withdrawInfo := XCallMessage{} + _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapperV2.Data, &withdrawInfo) + if err != nil { + log.Fatal(err.Error()) + } + + fmt.Println(withdrawInfo) } func TestGetRuneBalanceAtIndex(t *testing.T) { From 1f3ec7efdbdd89cbde571275ffa9a8598d431279 Mon Sep 17 00:00:00 2001 From: Shall Date: Sat, 31 Aug 2024 22:14:27 +0700 Subject: [PATCH 058/113] feat: add decode relay message function --- relayer/chains/bitcoin/provider.go | 38 +++++++++++++++++++ relayer/chains/bitcoin/provider_route_test.go | 14 +++++++ 2 files changed, 52 insertions(+) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 507b7156..b7c8d609 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -3,8 +3,10 @@ package bitcoin import ( "bytes" "context" + "encoding/base64" "encoding/json" "fmt" + "log" "math/big" "runtime" "sync" @@ -45,6 +47,13 @@ var chainIdToName = map[uint8]string{ // Add more mappings as needed } +type MessageDecoded struct { + Action string + TokenAddress string + To string + Amount []byte +} + type Provider struct { logger *zap.Logger cfg *Config @@ -230,6 +239,35 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn } } +func (p *Provider) decodeWithdrawToMessage(input string) (*MessageDecoded, error) { + // Decode base64 + decodedBytes, err := base64.StdEncoding.DecodeString(input) + if err != nil { + return nil, err + } + + withdrawInfoWrapper := CSMessage{} + _, err = codec.RLP.UnmarshalFromBytes(decodedBytes, &withdrawInfoWrapper) + if err != nil { + log.Fatal(err.Error()) + } + + // withdraw info data + withdrawInfoWrapperV2 := CSMessageRequestV2{} + _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapper.Payload, &withdrawInfoWrapperV2) + if err != nil { + log.Fatal(err.Error()) + } + // withdraw info + withdrawInfo := &MessageDecoded{} + _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapperV2.Data, &withdrawInfo) + if err != nil { + log.Fatal(err.Error()) + } + + return withdrawInfo, nil +} + func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { p.logger.Info("starting to route message", zap.Any("message", message)) diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index 65909674..03657c21 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -16,6 +16,20 @@ import ( "go.uber.org/zap" ) +func TestDecodeWithdrawToMessage(t *testing.T) { + p := &Provider{} + input := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" + + result, err := p.decodeWithdrawToMessage(input) + + assert.NoError(t, err) + assert.NotNil(t, result) + assert.Equal(t, "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", result.To) + assert.Equal(t, big.NewInt(100).Bytes(), result.Amount) + assert.Equal(t, "WithdrawTo", result.Action) + assert.Equal(t, "0:0", result.TokenAddress) +} + func TestProvider_Route(t *testing.T) { // Setup tempDir, err := os.MkdirTemp("", "bitcoin_provider_test") From dce1091d2c73213a59dcd1ac9d89b8b72366744d Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Sun, 1 Sep 2024 10:33:32 +0700 Subject: [PATCH 059/113] update building multisig tx for icon -> bitcoin flow --- relayer/chains/bitcoin/provider.go | 231 ++++++++++++++-- relayer/chains/bitcoin/provider_route_test.go | 25 +- relayer/chains/bitcoin/unisat_api.go | 255 ++++++++++++++++++ utils/multisig/multisig_test.go | 36 +-- utils/multisig/utils.go | 2 +- 5 files changed, 502 insertions(+), 47 deletions(-) create mode 100644 relayer/chains/bitcoin/unisat_api.go diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index b7c8d609..b8dc80f2 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -3,16 +3,19 @@ package bitcoin import ( "bytes" "context" - "encoding/base64" - "encoding/json" "fmt" "log" "math/big" "runtime" + "strconv" + "strings" "sync" "time" wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" sdkTypes "github.com/cosmos/cosmos-sdk/types" "path/filepath" @@ -239,15 +242,9 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn } } -func (p *Provider) decodeWithdrawToMessage(input string) (*MessageDecoded, error) { - // Decode base64 - decodedBytes, err := base64.StdEncoding.DecodeString(input) - if err != nil { - return nil, err - } - +func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { withdrawInfoWrapper := CSMessage{} - _, err = codec.RLP.UnmarshalFromBytes(decodedBytes, &withdrawInfoWrapper) + _, err := codec.RLP.UnmarshalFromBytes(input, &withdrawInfoWrapper) if err != nil { log.Fatal(err.Error()) } @@ -265,29 +262,211 @@ func (p *Provider) decodeWithdrawToMessage(input string) (*MessageDecoded, error log.Fatal(err.Error()) } - return withdrawInfo, nil + return withdrawInfo, withdrawInfoWrapperV2.Data, nil } -func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { - p.logger.Info("starting to route message", zap.Any("message", message)) +func GetBitcoinUTXOs(server, address string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) + defer cancel() + // TODO: loop query until sastified amountRequired + resp, err := GetBtcUtxo(ctx, UNISAT_DEFAULT_TESTNET, "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", address, 0, 32) + if err != nil { + return nil , fmt.Errorf("failed to query bitcoin UTXOs from unisat: %v", err) + } + outputs := []*multisig.UTXO{} + var totalAmount uint64 + for _, utxo := range resp.Data.Utxo { + if totalAmount >= amountRequired { + break + } + outputAmount := utxo.Satoshi.Uint64() + outputs = append(outputs, &multisig.UTXO{ + IsRelayersMultisig: true, + TxHash: utxo.TxId, + OutputIdx: uint32(utxo.Vout), + OutputAmount: outputAmount, + }) + totalAmount += outputAmount + } - if p.cfg.Mode == SlaveMode { - // Store the message in LevelDB - messageJSON, err := json.Marshal(message) - if err != nil { - return fmt.Errorf("failed to marshal message: %v", err) + return outputs, nil +} + +func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, uint64, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) + defer cancel() + // TODO: loop query until sastified amountRequired + resp, err := GetRuneUtxo(ctx, UNISAT_DEFAULT_TESTNET, address, runeId) + if err != nil { + return nil , 0, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) + } + outputs := []*multisig.UTXO{} + var totalAmount uint64 + for _, utxo := range resp.Data.Utxo { + if totalAmount >= amountRequired { + break + } + outputs = append(outputs, &multisig.UTXO{ + IsRelayersMultisig: true, + TxHash: utxo.TxId, + OutputIdx: uint32(utxo.Vout), + OutputAmount: utxo.Satoshi.Uint64(), + }) + if len(utxo.Runes) != 1 { + return nil , 0, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) } - // TODO: replace key with txid - key := []byte(fmt.Sprintf("bitcoin_message_%s", message.Sn.String())) - err = p.db.Put(key, messageJSON, nil) + runeAmount, _ := strconv.ParseUint(utxo.Runes[0].Amount, 10, 64) + totalAmount += runeAmount + } + + return outputs, totalAmount - amountRequired, nil +} + +func CreateBitcoinMultisigTx( + messageData []byte, + feePerOutput uint64, + relayersMultisigWallet *multisig.MultisigWallet, + chainParam *chaincfg.Params, + server string, +) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { + // ----- BUILD OUTPUTS ----- + outputs := []*multisig.OutputTx{} + var bitcoinAmountRequired, runeAmountRequired uint64 + var runeRequired multisig.Rune + decodedData, opreturnData, err := decodeWithdrawToMessage(messageData) + // add bridge message to output + scripts, _ := multisig.CreateBridgeMessageScripts(opreturnData, 76) + for _, script := range scripts { + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + // add withdraw output + if err == nil { + amount := new(big.Int).SetBytes(decodedData.Amount).Uint64() + if decodedData.Action == "WithdrawTo" { + if decodedData.TokenAddress == "0:0" { + // transfer btc + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: decodedData.To, + Amount: amount, + }) + + bitcoinAmountRequired = amount + } else { + // transfer rune + runeAddress := strings.Split(decodedData.TokenAddress, ":") + blockNumber, _ := strconv.ParseUint(runeAddress[0], 10, 64) + txIndex, _ := strconv.ParseUint(runeAddress[0], 10, 32) + runeRequired = multisig.Rune{ + BlockNumber: blockNumber, + TxIndex: uint32(txIndex), + } + runeScript, _ := multisig.CreateRuneTransferScript( + runeRequired, + new(big.Int).SetUint64(amount), + uint64(len(outputs)+2), + ) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: runeScript, + }) + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: decodedData.To, + Amount: 1000, + }) + + bitcoinAmountRequired = 1000 + runeAmountRequired = amount + } + } + } + + // ----- BUILD INPUTS ----- + relayersMultisigAddress, err := multisig.AddressOnChain(chainParam, relayersMultisigWallet) + if err != nil { + return nil, nil, "", nil, err + } + relayersMultisigAddressStr := relayersMultisigAddress.String() + // add tx fee the the required bitcoin amount + inputs := []*multisig.UTXO{} + var inputsSatNeeded uint64 + if runeAmountRequired != 0 { + // query rune UTXOs from unisat + runeInputs, runeChangeAmount, err := GetRuneUTXOs(server, relayersMultisigAddressStr, decodedData.TokenAddress, runeAmountRequired, 3) if err != nil { - return fmt.Errorf("failed to store message in LevelDB: %v", err) + return nil, nil, "", nil, err } + inputs = append(inputs, runeInputs...) + // add rune change to outputs + runeScript, _ := multisig.CreateRuneTransferScript( + runeRequired, + new(big.Int).SetUint64(runeChangeAmount), + uint64(len(outputs)+2), + ) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: runeScript, + }) + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: relayersMultisigAddressStr, + Amount: 1000, + }) + inputsSatNeeded = 1000 + } + txFee := uint64(len(outputs)) * feePerOutput + inputsSatNeeded += bitcoinAmountRequired + txFee + // todo: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo + // query bitcoin UTXOs from unisat + bitcoinInputs, err := GetBitcoinUTXOs(server, relayersMultisigAddressStr, inputsSatNeeded, 3) + if err != nil { + return nil, nil, "", nil, err + } + inputs = append(inputs, bitcoinInputs...) + // create raw tx + msgTx, hexRawTx, txSigHashes, err := multisig.CreateMultisigTx(inputs, outputs, txFee, relayersMultisigWallet, nil, chainParam, relayersMultisigAddressStr, 0) + + return inputs, msgTx, hexRawTx, txSigHashes, err +} - p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) - return nil - } else if p.cfg.Mode == MasterMode { - // TODO: Implement logic to build bitcoin transaction using signatures +func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { + p.logger.Info("starting to route message", zap.Any("message", message)) + + if (message.Src == "0x2.icon" && message.Dst == "0x2.btc") { + if p.cfg.Mode == SlaveMode { + // Store the message in LevelDB + key := []byte(fmt.Sprintf("bitcoin_message_%s", message.Sn.String())) + err := p.db.Put(key, message.Data, nil) + if err != nil { + return fmt.Errorf("failed to store message in LevelDB: %v", err) + } + + p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) + return nil + } else if p.cfg.Mode == MasterMode { + // // build unsigned tx + // chainParam := &chaincfg.TestNet3Params + // relayerPrivKeys, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + // relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) + + // inputs, msgTx, hexRawTx, txSigHashes, _ := CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + // tapSigParams := multisig.TapSigParams { + // TxSigHashes: txSigHashes, + // RelayersPKScript: relayersMultisigWallet.PKScript, + // RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + // UserPKScript: []byte{}, + // UserTapLeaf: txscript.TapLeaf{}, + // } + + // // master sign tx + // sigs, err := multisig.PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) + // if err != nil { + // fmt.Println("err sign: ", err) + // } + // totalSigs := []byte{sigs} + // // send unsigned raw tx and message sn to 2 slave relayers to get sign + // signatures := p.CallSlaves(txid) + // // combine sigs + // // broadcast tx + } } // MasterMode logic diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index 03657c21..d656b63b 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -2,6 +2,7 @@ package bitcoin import ( "context" + "encoding/base64" "encoding/json" "fmt" "math/big" @@ -9,18 +10,23 @@ import ( "path/filepath" "testing" + "github.com/btcsuite/btcd/chaincfg" "github.com/icon-project/centralized-relay/relayer/events" "github.com/icon-project/centralized-relay/relayer/types" + "github.com/icon-project/centralized-relay/utils/multisig" "github.com/stretchr/testify/assert" "github.com/syndtr/goleveldb/leveldb" "go.uber.org/zap" ) func TestDecodeWithdrawToMessage(t *testing.T) { - p := &Provider{} input := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" + // Decode base64 + decodedBytes, _ := base64.StdEncoding.DecodeString(input) - result, err := p.decodeWithdrawToMessage(input) + result, data, err := decodeWithdrawToMessage(decodedBytes) + + fmt.Println("data", data) assert.NoError(t, err) assert.NotNil(t, result) @@ -30,6 +36,21 @@ func TestDecodeWithdrawToMessage(t *testing.T) { assert.Equal(t, "0:0", result.TokenAddress) } +func TestCreateBitcoinMultisigTx(t *testing.T) { + data := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" + // Decode base64 + dataBytes, _ := base64.StdEncoding.DecodeString(data) + + chainParam := &chaincfg.TestNet3Params + _, relayersMultisigInfo := // multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) + + _, _, hexRawTx, _, err := CreateBitcoinMultisigTx(dataBytes, 5000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + fmt.Println("err: ", err) + fmt.Println("hexRawTx: ", hexRawTx) +} + func TestProvider_Route(t *testing.T) { // Setup tempDir, err := os.MkdirTemp("", "bitcoin_provider_test") diff --git a/relayer/chains/bitcoin/unisat_api.go b/relayer/chains/bitcoin/unisat_api.go new file mode 100644 index 00000000..76445bb4 --- /dev/null +++ b/relayer/chains/bitcoin/unisat_api.go @@ -0,0 +1,255 @@ +package bitcoin + +import ( + "context" + "encoding/json" + "fmt" + "io" + "math/big" + "net/http" +) + +const ( + UNISAT_DEFAULT_MAINNET = "https://open-api.unisat.io" + UNISAT_DEFAULT_TESTNET = "https://open-api-testnet.unisat.io" +) + +type DataBlockchainInfo struct { + Chain string `json:"chain"` + Blocks int64 `json:"blocks"` + Headers int64 `json:"headers"` + BestBlockHash string `json:"bestBlockHash"` + PrevBlockHash string `json:"prevBlockHash"` + Difficulty string `json:"difficulty"` + MedianTime int64 `json:"medianTime"` + ChainWork string `json:"chainwork"` +} + +type ResponseBlockchainInfo struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data DataBlockchainInfo `json:"data"` +} + +type Tx struct { + TxId string `json:"txid"` + Ins int `json:"nIn"` + Outs int `json:"nOut"` + Size int `json:"size"` + WitOffset int `json:"witOffset"` + Locktime int `json:"locktime"` + InSatoshi *big.Int `json:"inSatoshi"` + OutSatoshi *big.Int `json:"outSatoshi"` + NewInscriptions int `json:"nNewInscription"` + InInscriptions int `json:"nInInscription"` + OutInscriptions int `json:"nOutInscription"` + LostInscriptions int `json:"nLostInscription"` + Timestamp int64 `json:"timestamp"` + Height int64 `json:"height"` + BlockId string `json:"blkid"` + Index int `json:"idx"` + Confirmations int `json:"confirmations"` +} + +type ResponseBlockTransactions struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data []Tx `json:"data"` +} + +type ResponseTxInfo struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data Tx `json:"data"` +} + +type Inscription struct { + InscriptionNumber int64 `json:"inscriptionNumber"` + InscriptionId string `json:"inscriptionId"` + Offset int `json:"offset"` + Moved bool `json:"moved"` + IsBRC20 bool `json:"isBRC20"` +} + +type Input struct { + Height int64 `json:"height"` + TxId string `json:"txid"` + Index int `json:"idx"` + ScriptSig string `json:"scriptSig"` + ScriptWits string `json:"scriptWits"` + Sequence int `json:"sequence"` + HeightTxo int64 `json:"heightTxo"` + Utxid string `json:"utxid"` + Vout int `json:"vout"` + Address string `json:"address"` + CodeType int `json:"codeType"` + Satoshi *big.Int `json:"satoshi"` + ScriptType string `json:"scriptType"` + ScriptPk string `json:"scriptPk"` + Inscriptions []Inscription `json:"inscriptions"` +} + +type ResponseTxInputs struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data []Input `json:"data"` +} + +type Output struct { + TxId string `json:"txid"` + Vout int `json:"vout"` + Address string `json:"address"` + CodeType int `json:"codeType"` + Satoshi *big.Int `json:"satoshi"` + ScriptType string `json:"scriptType"` + ScriptPk string `json:"scriptPk"` + Height int64 `json:"height"` + Index int `json:"idx"` + Inscriptions []Inscription `json:"inscriptions"` + TxSpent string `json:"txidSpent"` + HeightSpent int64 `json:"heightSpent"` +} + +type ResponseTxOutputs struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data []Output `json:"data"` +} + +type Balance struct { + Address string `json:"address"` + + Satoshi *big.Int `json:"satoshi"` + PendingSatoshi *big.Int `json:"pendingSatoshi"` + UtxoCount int64 `json:"utxoCount"` + + BtcSatoshi *big.Int `json:"btcSatoshi"` + BtcPendingSatoshi *big.Int `json:"btcPendingSatoshi"` + BtcUtxoCount int64 `json:"btcUtxoCount"` + + InscriptionSatoshi *big.Int `json:"inscriptionSatoshi"` + InscriptionPendingSatoshi *big.Int `json:"inscriptionPendingSatoshi"` + InscriptionUtxoCount int64 `json:"inscriptionUtxoCount"` +} + +type ResponseAddressBalance struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data Balance `json:"data"` +} + +type UTXO struct { + TxId string `json:"txid"` + Vout int `json:"vout"` + Satoshi *big.Int `json:"satoshi"` + ScriptType string `json:"scriptType"` + ScriptPk string `json:"scriptPk"` + CodeType int `json:"codeType"` + Address string `json:"address"` + Height int64 `json:"height"` + Index int `json:"idx"` + IsOpInRBF bool `json:"isOpInRBF"` + Inscriptions []Inscription `json:"inscriptions"` +} + +type DataUtxoList struct { + Cursor int `json:"cursor"` + Total int `json:"total"` + TotalConfirmed int `json:"totalConfirmed"` + TotalUnconfirmed int `json:"totalUnconfirmed"` + TotalUnconfirmedSpent int `json:"totalUnconfirmedSpent"` + Utxo []UTXO `json:"utxo"` +} + +type ResponseBtcUtxo struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data DataUtxoList `json:"data"` +} + +type RuneDetail struct { + Amount string `json:"amount"` + RuneId string `json:"runeid"` + Rune string `json:"rune"` + SpacedRune string `json:"spacedRune"` + Symbol string `json:"symbol"` + Divisibility int `json:"divisibility"` +} + +type RuneUTXO struct { + Address string `json:"address"` + Satoshi *big.Int `json:"satoshi"` + ScriptPk string `json:"scriptPk"` + TxId string `json:"txid"` + Vout int `json:"vout"` + Runes []RuneDetail `json:"runes"` +} + +type DataRuneUtxoList struct { + Utxo []RuneUTXO `json:"utxo"` +} + +type ResponseRuneUtxo struct { + Code int64 `json:"code"` + Message string `json:"msg"` + + Data DataRuneUtxoList `json:"data"` +} + +func BtcUtxoUrl(server, address string, offset, limit int64) string { + return fmt.Sprintf("%s/v1/indexer/address/%s/utxo-data?cursor=%d&size=%d", server, address, offset, limit) +} + +func RuneUtxoUrl(server, address, runeId string) string { + return fmt.Sprintf("%s/v1/indexer/address/%s/runes/%s/utxo", server, address, runeId) +} + +func GetWithHeader(ctx context.Context, url string, header map[string]string, response interface{}) error { + req, err := http.NewRequestWithContext(ctx, "GET", url, nil) + if err != nil { + return err + } + for k, v := range header { + req.Header.Add(k, v) + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + if err = json.Unmarshal(body, response); err != nil { + return err + } + return nil +} + +func GetWithBear(ctx context.Context, url, bear string, response interface{}) error { + header := make(map[string]string) + header["Authorization"] = fmt.Sprintf("Bearer %s", bear) + return GetWithHeader(ctx, url, header, response) +} + +func GetBtcUtxo(ctx context.Context, server, bear, address string, offset, limit int64) (ResponseBtcUtxo, error) { + var resp ResponseBtcUtxo + url := BtcUtxoUrl(server, address, offset, limit) + err := GetWithBear(ctx, url, bear, &resp) + return resp, err +} + +func GetRuneUtxo(ctx context.Context, server, address, runeId string) (ResponseRuneUtxo, error) { + var resp ResponseRuneUtxo + url := RuneUtxoUrl(server, address, runeId) + err := GetWithHeader(ctx, url, make(map[string]string), &resp) + return resp, err +} diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 498028a7..c6c90454 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -55,9 +55,9 @@ func TestRandomKeys(t *testing.T) { func TestBuildMultisigTapScript(t *testing.T) { chainParam := &chaincfg.TestNet3Params - _, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + _, relayersMultisigInfo := RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) - _, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + _, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) relayersMultisigAddress, err := AddressOnChain(chainParam, relayersMultisigWallet) @@ -86,7 +86,7 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { }, } - relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayerPrivKeys, relayersMultisigInfo := RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" @@ -164,9 +164,9 @@ func TestMultisigUserSwap(t *testing.T) { }, } - relayerPrivKeys, relayersMultisigInfo := randomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayerPrivKeys, relayersMultisigInfo := RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" @@ -262,20 +262,20 @@ func TestUserRecoveryTimeLock(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 3808, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, }, } outputs := []*OutputTx{ { ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, + Amount: 1000000, }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -326,7 +326,7 @@ func TestTransferRune(t *testing.T) { }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -412,7 +412,7 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { }) } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -494,7 +494,7 @@ func TestRadFiInitPool(t *testing.T) { }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -597,7 +597,7 @@ func TestRadFiProvideLiquidity(t *testing.T) { }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -720,7 +720,7 @@ func TestRadFiSwap(t *testing.T) { }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -834,7 +834,7 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { Amount: 1000, }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -949,7 +949,7 @@ func TestRadFiCollectFees(t *testing.T) { }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS @@ -1045,7 +1045,7 @@ func TestRadFiIncreaseLiquidity(t *testing.T) { }, } - userPrivKeys, userMultisigInfo := randomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) changeReceiverAddress := USER_MULTISIG_ADDRESS diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 2d6ea113..29873085 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -42,7 +42,7 @@ func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][] return privKeys, pubKeys, ECPubKeys } -func randomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryLockTime uint64) ([]string, *MultisigInfo) { +func RandomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryLockTime uint64) ([]string, *MultisigInfo) { privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ PubKeys: pubKeys, From f5b4f9a6b614d16ddd7854e248a2db0fb9585834 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Sun, 1 Sep 2024 22:31:07 +0700 Subject: [PATCH 060/113] update master relayer request 2 slave relayers to sign --- relayer/chains/bitcoin/master.go | 64 ++++++++++++----------- relayer/chains/bitcoin/provider.go | 81 +++++++++++++++++++----------- 2 files changed, 86 insertions(+), 59 deletions(-) diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index c31d9ce5..94d210c8 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -21,10 +21,10 @@ func startMaster(c *Config) { log.Printf("Master starting on port %s", port) - isProcess := os.Getenv("IS_PROCESS") - if isProcess == "1" { - callSlaves("test") - } + // isProcess := os.Getenv("IS_PROCESS") + // if isProcess == "1" { + // callSlaves("test") + // } log.Fatal(server.ListenAndServe()) } @@ -71,34 +71,34 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(response) } -func callSlaves(txId string) { - fmt.Println("Master request slave") - slavePort1 := os.Getenv("SLAVE_SERVER_1") - slavePort2 := os.Getenv("SLAVE_SERVER_2") - // Call slave to get more data - var wg sync.WaitGroup - responses := make(chan string, 2) - - wg.Add(2) - go requestPartialSign(slavePort1, txId, responses, &wg) - go requestPartialSign(slavePort2, txId, responses, &wg) - - go func() { - wg.Wait() - close(responses) - }() - - for res := range responses { - fmt.Println("Received response from slave: ", res) - } -} - -func requestPartialSign(url string, txId string, responses chan<- string, wg *sync.WaitGroup) { +// func callSlaves(txId string) { +// fmt.Println("Master request slave") +// slavePort1 := os.Getenv("SLAVE_SERVER_1") +// slavePort2 := os.Getenv("SLAVE_SERVER_2") +// // Call slave to get more data +// var wg sync.WaitGroup +// responses := make(chan string, 2) + +// wg.Add(2) +// go requestPartialSign(slavePort1, txId, responses, &wg) +// go requestPartialSign(slavePort2, txId, responses, &wg) + +// go func() { +// wg.Wait() +// close(responses) +// }() + +// for res := range responses { +// fmt.Println("Received response from slave: ", res) +// } +// } + +func requestPartialSign(url string, slaveRequestData []byte, responses chan<- [][]byte, wg *sync.WaitGroup) { defer wg.Done() client := &http.Client{} apiKeyHeader := os.Getenv("API_KEY") - payload := bytes.NewBuffer([]byte(txId)) + payload := bytes.NewBuffer(slaveRequestData) req, err := http.NewRequest("POST", url, payload) if err != nil { @@ -118,5 +118,11 @@ func requestPartialSign(url string, txId string, responses chan<- string, wg *sy log.Fatalf("Error reading response: %v", err) } - responses <- string(body) + sigs := [][]byte{} + err = json.Unmarshal(body, &sigs) + if err != nil { + fmt.Println("err Unmarshal: ", err) + } + + responses <- sigs } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index b8dc80f2..0b8fa7c4 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -3,6 +3,7 @@ package bitcoin import ( "bytes" "context" + "encoding/json" "fmt" "log" "math/big" @@ -57,6 +58,13 @@ type MessageDecoded struct { Amount []byte } +type slaveRequestParams struct { + MsgSn *big.Int `json:"msgSn"` + MsgTx string `json:"msgTx"` + UTXOs []*multisig.UTXO `json:"UTXOs"` + TapSigInfo multisig.TapSigParams `json:"tapSigInfo"` +} + type Provider struct { logger *zap.Logger cfg *Config @@ -133,22 +141,22 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri return p, nil } -func (p *Provider) CallSlaves(txId string) []string { - resultChan := make(chan []string) +func (p *Provider) CallSlaves(slaveRequestData []byte) [][][]byte { + resultChan := make(chan [][][]byte) go func() { - responses := make(chan string, 2) + responses := make(chan [][]byte, 2) var wg sync.WaitGroup wg.Add(2) - go requestPartialSign(p.cfg.SlaveServer1, txId, responses, &wg) - go requestPartialSign(p.cfg.SlaveServer2, txId, responses, &wg) + go requestPartialSign(p.cfg.SlaveServer1, slaveRequestData, responses, &wg) + go requestPartialSign(p.cfg.SlaveServer2, slaveRequestData, responses, &wg) go func() { wg.Wait() close(responses) }() - var results []string + var results [][][]byte for res := range responses { results = append(results, res) } @@ -442,30 +450,43 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) return nil } else if p.cfg.Mode == MasterMode { - // // build unsigned tx - // chainParam := &chaincfg.TestNet3Params - // relayerPrivKeys, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) - // relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) - - // inputs, msgTx, hexRawTx, txSigHashes, _ := CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) - // tapSigParams := multisig.TapSigParams { - // TxSigHashes: txSigHashes, - // RelayersPKScript: relayersMultisigWallet.PKScript, - // RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - // UserPKScript: []byte{}, - // UserTapLeaf: txscript.TapLeaf{}, - // } - - // // master sign tx - // sigs, err := multisig.PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) - // if err != nil { - // fmt.Println("err sign: ", err) - // } - // totalSigs := []byte{sigs} - // // send unsigned raw tx and message sn to 2 slave relayers to get sign - // signatures := p.CallSlaves(txid) - // // combine sigs - // // broadcast tx + // build unsigned tx + chainParam := &chaincfg.TestNet3Params + relayerPrivKeys, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) + + inputs, msgTx, hexRawTx, txSigHashes, _ := CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + tapSigParams := multisig.TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: relayersMultisigWallet.PKScript, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: []byte{}, + UserTapLeaf: txscript.TapLeaf{}, + } + + // master sign tx + sigs, err := multisig.PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) + if err != nil { + fmt.Println("err sign: ", err) + } + totalSigs := [][][]byte{sigs} + // send unsigned raw tx and message sn to 2 slave relayers to get sign + rsi := slaveRequestParams{ + MsgSn: message.Sn, + MsgTx: hexRawTx, + UTXOs: inputs, + TapSigInfo: tapSigParams, + } + slaveRequestData, _ := json.Marshal(rsi) + slaveSigs := p.CallSlaves(slaveRequestData) + totalSigs = append(totalSigs, slaveSigs...) + // combine sigs + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, relayersMultisigWallet, 0, totalSigs) + if err != nil { + fmt.Println("err combine tx: ", err) + } + // broadcast tx + fmt.Println("signedMsgTx:", signedMsgTx) } } From 708f5805e72b02e5d502d7893ab2d3a43868420d Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 2 Sep 2024 12:13:10 +0700 Subject: [PATCH 061/113] update sign combining for icon->bitcoin flow --- relayer/chains/bitcoin/provider.go | 53 ++++++++++++++---------------- relayer/chains/bitcoin/slave.go | 20 +++++++++-- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 0b8fa7c4..63c74d19 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -60,9 +60,6 @@ type MessageDecoded struct { type slaveRequestParams struct { MsgSn *big.Int `json:"msgSn"` - MsgTx string `json:"msgTx"` - UTXOs []*multisig.UTXO `json:"UTXOs"` - TapSigInfo multisig.TapSigParams `json:"tapSigInfo"` } type Provider struct { @@ -439,10 +436,32 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("starting to route message", zap.Any("message", message)) if (message.Src == "0x2.icon" && message.Dst == "0x2.btc") { + // build unsigned tx + // TODO: Build Multisig Wallet from config + chainParam := &chaincfg.TestNet3Params + _, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) + + inputs, msgTx, _, txSigHashes, _ := CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + tapSigParams := multisig.TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: relayersMultisigWallet.PKScript, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: []byte{}, + UserTapLeaf: txscript.TapLeaf{}, + } + // TODO: Load priv key from config + relayerPrivKey := "RELAYER_PRIV_KEY" + // relayer sign tx + relayerSigs, err := multisig.PartSignOnRawExternalTx(relayerPrivKey, msgTx, inputs, tapSigParams, chainParam, false) + if err != nil { + fmt.Println("err sign: ", err) + } if p.cfg.Mode == SlaveMode { - // Store the message in LevelDB + // Store the sigs in LevelDB key := []byte(fmt.Sprintf("bitcoin_message_%s", message.Sn.String())) - err := p.db.Put(key, message.Data, nil) + value, _ := json.Marshal(relayerSigs) + err := p.db.Put(key, value, nil) if err != nil { return fmt.Errorf("failed to store message in LevelDB: %v", err) } @@ -450,32 +469,10 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) return nil } else if p.cfg.Mode == MasterMode { - // build unsigned tx - chainParam := &chaincfg.TestNet3Params - relayerPrivKeys, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) - relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) - - inputs, msgTx, hexRawTx, txSigHashes, _ := CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) - tapSigParams := multisig.TapSigParams { - TxSigHashes: txSigHashes, - RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - UserPKScript: []byte{}, - UserTapLeaf: txscript.TapLeaf{}, - } - - // master sign tx - sigs, err := multisig.PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) - if err != nil { - fmt.Println("err sign: ", err) - } - totalSigs := [][][]byte{sigs} + totalSigs := [][][]byte{relayerSigs} // send unsigned raw tx and message sn to 2 slave relayers to get sign rsi := slaveRequestParams{ MsgSn: message.Sn, - MsgTx: hexRawTx, - UTXOs: inputs, - TapSigInfo: tapSigParams, } slaveRequestData, _ := json.Marshal(rsi) slaveSigs := p.CallSlaves(slaveRequestData) diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index 80cc4d93..64f46019 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -1,8 +1,10 @@ package bitcoin import ( + "encoding/json" "io" "log" + "math/big" "net/http" "os" ) @@ -37,9 +39,23 @@ func handleRoot(w http.ResponseWriter, r *http.Request) { return } - log.Printf("Received payload: %s", string(body)) - w.Write([]byte("Payload received" + string(body))) + var rsi slaveRequestParams + err = json.Unmarshal(body, &rsi) + if err != nil { + http.Error(w, "Error decoding request body", http.StatusInternalServerError) + return + } + sigs, _ := loadSigsFromDb(rsi.MsgSn) + // return sigs to master + returnData, _ := json.Marshal(sigs) + w.Write(returnData) } else { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } } + +func loadSigsFromDb(sn *big.Int) ([][]byte, error) { + // TODO: read db to get keys + return [][]byte{}, nil +} + From f062bc0c13f47e8782889375ba349e215f599ef9 Mon Sep 17 00:00:00 2001 From: Shall Date: Mon, 2 Sep 2024 14:59:06 +0700 Subject: [PATCH 062/113] feat: add more config for slave mode --- config.yaml | 11 +++++- relayer/chains/bitcoin/provider.go | 60 ++++++++++++++++-------------- relayer/chains/bitcoin/slave.go | 27 ++++++++++---- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/config.yaml b/config.yaml index b865069c..2c42cd6d 100644 --- a/config.yaml +++ b/config.yaml @@ -7,7 +7,7 @@ chains: value: rpc-url: https://lisbon.net.solidwallet.io/api/v3/ address: hx9a530643c071f15e8411eadd9f0b2ee5a871d37f - start-height: 42842964 + start-height: 42860355 step-min: 1 step-limit: 2000000000000000000 contracts: @@ -28,8 +28,10 @@ chains: - cx577f5e756abd89cbcba38a58508b60a12754d2f5 # - cxf5a0b146af1572e44775a40ef06c5a39b143ed1e unisat-url: https://open-api.unisat.io/v1/indexer + unisat-key: 60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d # start-height: 2874137 - start-height: 2874459 + # start-height: 2874459 + start-height: 2901648 network-id: 2 op-code: 0x5e finality-block: 10 @@ -40,3 +42,8 @@ chains: slave-server-2: http://localhost:8082 port: 8082 api-key: key + masterPubKey: string + slave1PubKey: string + slave2PubKey: string + relayerPrivKey: string + recoveryLockTime: 01234 diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 63c74d19..5085eead 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -59,7 +59,7 @@ type MessageDecoded struct { } type slaveRequestParams struct { - MsgSn *big.Int `json:"msgSn"` + MsgSn *big.Int `json:"msgSn"` } type Provider struct { @@ -79,6 +79,7 @@ type Config struct { provider.CommonConfig `json:",inline" yaml:",inline"` OpCode int `json:"op-code" yaml:"op-code"` UniSatURL string `json:"unisat-url" yaml:"unisat-url"` + UniSatKey string `json:"unisat-key" yaml:"unisat-key"` Type string `json:"type" yaml:"type"` User string `json:"rpc-user" yaml:"rpc-user"` Password string `json:"rpc-password" yaml:"rpc-password"` @@ -88,6 +89,11 @@ type Config struct { SlaveServer2 string `json:"slave-server-2" yaml:"slave-server-2"` Port string `json:"port" yaml:"port"` ApiKey string `json:"api-key" yaml:"api-key"` + MasterPubKey string `json:"masterPubKey" yaml:"masterPubKey"` + Slave1PubKey string `json:"slave1PubKey" yaml:"slave1PubKey"` + Slave2PubKey string `json:"slave2PubKey" yaml:"slave2PubKey"` + RelayerPrivKey string `json:"relayerPrivKey" yaml:"relayerPrivKey"` + RecoveryLockTime int `json:"recoveryLockTime" yaml:"recoveryLockTime"` } // NewProvider returns new Icon provider @@ -130,7 +136,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri if c.Mode == MasterMode { startMaster(c) } else { - startSlave(c) + startSlave(c, p) } close(p.httpServer) }() @@ -270,13 +276,13 @@ func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { return withdrawInfo, withdrawInfoWrapperV2.Data, nil } -func GetBitcoinUTXOs(server, address string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, error) { +func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired - resp, err := GetBtcUtxo(ctx, UNISAT_DEFAULT_TESTNET, "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", address, 0, 32) + resp, err := GetBtcUtxo(ctx, UNISAT_DEFAULT_TESTNET, p.cfg.UniSatKey, address, 0, 32) if err != nil { - return nil , fmt.Errorf("failed to query bitcoin UTXOs from unisat: %v", err) + return nil, fmt.Errorf("failed to query bitcoin UTXOs from unisat: %v", err) } outputs := []*multisig.UTXO{} var totalAmount uint64 @@ -287,9 +293,9 @@ func GetBitcoinUTXOs(server, address string, amountRequired uint64, timeout uint outputAmount := utxo.Satoshi.Uint64() outputs = append(outputs, &multisig.UTXO{ IsRelayersMultisig: true, - TxHash: utxo.TxId, - OutputIdx: uint32(utxo.Vout), - OutputAmount: outputAmount, + TxHash: utxo.TxId, + OutputIdx: uint32(utxo.Vout), + OutputAmount: outputAmount, }) totalAmount += outputAmount } @@ -303,7 +309,7 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout // TODO: loop query until sastified amountRequired resp, err := GetRuneUtxo(ctx, UNISAT_DEFAULT_TESTNET, address, runeId) if err != nil { - return nil , 0, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) + return nil, 0, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) } outputs := []*multisig.UTXO{} var totalAmount uint64 @@ -313,12 +319,12 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout } outputs = append(outputs, &multisig.UTXO{ IsRelayersMultisig: true, - TxHash: utxo.TxId, - OutputIdx: uint32(utxo.Vout), - OutputAmount: utxo.Satoshi.Uint64(), + TxHash: utxo.TxId, + OutputIdx: uint32(utxo.Vout), + OutputAmount: utxo.Satoshi.Uint64(), }) if len(utxo.Runes) != 1 { - return nil , 0, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) + return nil, 0, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) } runeAmount, _ := strconv.ParseUint(utxo.Runes[0].Amount, 10, 64) totalAmount += runeAmount @@ -327,7 +333,7 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout return outputs, totalAmount - amountRequired, nil } -func CreateBitcoinMultisigTx( +func (p *Provider) CreateBitcoinMultisigTx( messageData []byte, feePerOutput uint64, relayersMultisigWallet *multisig.MultisigWallet, @@ -354,7 +360,7 @@ func CreateBitcoinMultisigTx( // transfer btc outputs = append(outputs, &multisig.OutputTx{ ReceiverAddress: decodedData.To, - Amount: amount, + Amount: amount, }) bitcoinAmountRequired = amount @@ -365,7 +371,7 @@ func CreateBitcoinMultisigTx( txIndex, _ := strconv.ParseUint(runeAddress[0], 10, 32) runeRequired = multisig.Rune{ BlockNumber: blockNumber, - TxIndex: uint32(txIndex), + TxIndex: uint32(txIndex), } runeScript, _ := multisig.CreateRuneTransferScript( runeRequired, @@ -377,7 +383,7 @@ func CreateBitcoinMultisigTx( }) outputs = append(outputs, &multisig.OutputTx{ ReceiverAddress: decodedData.To, - Amount: 1000, + Amount: 1000, }) bitcoinAmountRequired = 1000 @@ -413,7 +419,7 @@ func CreateBitcoinMultisigTx( }) outputs = append(outputs, &multisig.OutputTx{ ReceiverAddress: relayersMultisigAddressStr, - Amount: 1000, + Amount: 1000, }) inputsSatNeeded = 1000 } @@ -421,7 +427,7 @@ func CreateBitcoinMultisigTx( inputsSatNeeded += bitcoinAmountRequired + txFee // todo: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo // query bitcoin UTXOs from unisat - bitcoinInputs, err := GetBitcoinUTXOs(server, relayersMultisigAddressStr, inputsSatNeeded, 3) + bitcoinInputs, err := p.GetBitcoinUTXOs(server, relayersMultisigAddressStr, inputsSatNeeded, 3) if err != nil { return nil, nil, "", nil, err } @@ -435,23 +441,23 @@ func CreateBitcoinMultisigTx( func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { p.logger.Info("starting to route message", zap.Any("message", message)) - if (message.Src == "0x2.icon" && message.Dst == "0x2.btc") { + if message.Src == "0x2.icon" && message.Dst == "0x2.btc" { // build unsigned tx // TODO: Build Multisig Wallet from config chainParam := &chaincfg.TestNet3Params _, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) - inputs, msgTx, _, txSigHashes, _ := CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) - tapSigParams := multisig.TapSigParams { - TxSigHashes: txSigHashes, + inputs, msgTx, _, txSigHashes, _ := p.CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - UserPKScript: []byte{}, - UserTapLeaf: txscript.TapLeaf{}, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: []byte{}, + UserTapLeaf: txscript.TapLeaf{}, } // TODO: Load priv key from config - relayerPrivKey := "RELAYER_PRIV_KEY" + relayerPrivKey := p.cfg.RelayerPrivKey // relayer sign tx relayerSigs, err := multisig.PartSignOnRawExternalTx(relayerPrivKey, msgTx, inputs, tapSigParams, chainParam, false) if err != nil { diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index 64f46019..eff65a51 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -9,8 +9,10 @@ import ( "os" ) -func startSlave(c *Config) { - http.HandleFunc("/", handleRoot) +func startSlave(c *Config, p *Provider) { + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + handleRoot(w, r, p) + }) port := c.Port server := &http.Server{ Addr: ":" + port, @@ -21,7 +23,7 @@ func startSlave(c *Config) { log.Fatal(server.ListenAndServe()) } -func handleRoot(w http.ResponseWriter, r *http.Request) { +func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { if r.Method == http.MethodPost { apiKey := r.Header.Get("x-api-key") if apiKey == "" { @@ -45,7 +47,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request) { http.Error(w, "Error decoding request body", http.StatusInternalServerError) return } - sigs, _ := loadSigsFromDb(rsi.MsgSn) + sigs, _ := loadSigsFromDb(rsi.MsgSn, p) // return sigs to master returnData, _ := json.Marshal(sigs) w.Write(returnData) @@ -54,8 +56,17 @@ func handleRoot(w http.ResponseWriter, r *http.Request) { } } -func loadSigsFromDb(sn *big.Int) ([][]byte, error) { - // TODO: read db to get keys - return [][]byte{}, nil -} +func loadSigsFromDb(sn *big.Int, p *Provider) ([][]byte, error) { + key := sn.String() + data, err := p.db.Get([]byte(key), nil) + if err != nil { + return nil, err + } + var sigs [][]byte + err = json.Unmarshal(data, &sigs) + if err != nil { + return nil, err + } + return sigs, nil +} From fd43ebcda3f4f07703cb9f59a249996ee04ab460 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 3 Sep 2024 18:12:43 +0700 Subject: [PATCH 063/113] update for signing and combining bitcoin relay message --- config.yaml | 12 +-- relayer/chains/bitcoin/provider.go | 91 +++++++++++-------- relayer/chains/bitcoin/provider_route_test.go | 11 ++- relayer/chains/bitcoin/slave.go | 19 +++- utils/multisig/multisig_test.go | 8 +- 5 files changed, 90 insertions(+), 51 deletions(-) diff --git a/config.yaml b/config.yaml index 2c42cd6d..dfb361b3 100644 --- a/config.yaml +++ b/config.yaml @@ -27,7 +27,7 @@ chains: protocals: - cx577f5e756abd89cbcba38a58508b60a12754d2f5 # - cxf5a0b146af1572e44775a40ef06c5a39b143ed1e - unisat-url: https://open-api.unisat.io/v1/indexer + unisat-url: https://open-api-testnet.unisat.io/v1/indexer unisat-key: 60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d # start-height: 2874137 # start-height: 2874459 @@ -42,8 +42,8 @@ chains: slave-server-2: http://localhost:8082 port: 8082 api-key: key - masterPubKey: string - slave1PubKey: string - slave2PubKey: string - relayerPrivKey: string - recoveryLockTime: 01234 + masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 + slave1PubKey: 0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052 + slave2PubKey: 021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833 + relayerPrivKey: cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy + recoveryLockTime: 1234 diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 5085eead..e08ccf84 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -3,6 +3,7 @@ package bitcoin import ( "bytes" "context" + "encoding/hex" "encoding/json" "fmt" "log" @@ -438,35 +439,58 @@ func (p *Provider) CreateBitcoinMultisigTx( return inputs, msgTx, hexRawTx, txSigHashes, err } +func (p *Provider) BuildAndPartSignBitcoinMessageTx(message *relayTypes.Message, messageDstNetwork string) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { + // get param for mainnet/testnet + var chainParam *chaincfg.Params + if messageDstNetwork == "0x1" { + chainParam = &chaincfg.MainNetParams + } else if messageDstNetwork == "0x2" { + chainParam = &chaincfg.TestNet3Params + } else { + return nil, nil, nil, nil, fmt.Errorf("invalid message dst network: %v", messageDstNetwork) + } + // build Multisig Wallet from config + masterPubKey, _ := hex.DecodeString(p.cfg.MasterPubKey) + slave1PubKey, _ := hex.DecodeString(p.cfg.Slave1PubKey) + slave2PubKey, _ := hex.DecodeString(p.cfg.Slave2PubKey) + relayersMultisigInfo := multisig.MultisigInfo{ + PubKeys: [][]byte{masterPubKey, slave1PubKey, slave2PubKey}, + EcPubKeys: nil, + NumberRequiredSigs: 3, + RecoveryPubKey: masterPubKey, + RecoveryLockTime: uint64(p.cfg.RecoveryLockTime), + } + relayersMultisigWallet, err := multisig.BuildMultisigWallet(&relayersMultisigInfo) + if err != nil { + return nil, nil, nil, nil, err + } + // build unsigned tx + inputs, msgTx, _, txSigHashes, err := p.CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + if err != nil { + return nil, nil, nil, nil, err + } + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, + RelayersPKScript: relayersMultisigWallet.PKScript, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: []byte{}, + UserTapLeaf: txscript.TapLeaf{}, + } + // relayer sign tx + relayerSigs, err := multisig.PartSignOnRawExternalTx(p.cfg.RelayerPrivKey, msgTx, inputs, tapSigParams, chainParam, false) + + return inputs, relayersMultisigWallet, msgTx, relayerSigs, err +} + func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { p.logger.Info("starting to route message", zap.Any("message", message)) - if message.Src == "0x2.icon" && message.Dst == "0x2.btc" { - // build unsigned tx - // TODO: Build Multisig Wallet from config - chainParam := &chaincfg.TestNet3Params - _, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) - relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) - - inputs, msgTx, _, txSigHashes, _ := p.CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - UserPKScript: []byte{}, - UserTapLeaf: txscript.TapLeaf{}, - } - // TODO: Load priv key from config - relayerPrivKey := p.cfg.RelayerPrivKey - // relayer sign tx - relayerSigs, err := multisig.PartSignOnRawExternalTx(relayerPrivKey, msgTx, inputs, tapSigParams, chainParam, false) - if err != nil { - fmt.Println("err sign: ", err) - } + messageDstDetail := strings.Split(message.Dst, ".") + if strings.Split(message.Src, ".")[1] == "icon" && messageDstDetail[1] == "btc" { if p.cfg.Mode == SlaveMode { - // Store the sigs in LevelDB - key := []byte(fmt.Sprintf("bitcoin_message_%s", message.Sn.String())) - value, _ := json.Marshal(relayerSigs) + // store the message in LevelDB + key := []byte(message.Sn.String()) + value, _ := json.Marshal(message) err := p.db.Put(key, value, nil) if err != nil { return fmt.Errorf("failed to store message in LevelDB: %v", err) @@ -475,6 +499,10 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) return nil } else if p.cfg.Mode == MasterMode { + inputs, relayersMultisigWallet, msgTx, relayerSigs, err := p.BuildAndPartSignBitcoinMessageTx(message, messageDstDetail[0]) + if err != nil { + return err + } totalSigs := [][][]byte{relayerSigs} // send unsigned raw tx and message sn to 2 slave relayers to get sign rsi := slaveRequestParams{ @@ -488,21 +516,12 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb if err != nil { fmt.Println("err combine tx: ", err) } - // broadcast tx + // TODO: Broadcast transaction to bitcoin network fmt.Println("signedMsgTx:", signedMsgTx) + // TODO: After successful broadcast, request slaves to remove the message from LevelDB if it exists } } - // MasterMode logic - // txid := "example_txid" // Replace with actual txid generation logic - // signatures := p.CallSlaves(txid) - - // TODO: Implement logic to build bitcoin transaction using signatures - - // TODO: Broadcast transaction to bitcoin network - - // After successful broadcast, remove the message from LevelDB if it exists - // TODO: Implement proper callback handling // callback(message.MessageKey(), txResponse, nil) diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index d656b63b..4fb4a531 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -37,16 +37,21 @@ func TestDecodeWithdrawToMessage(t *testing.T) { } func TestCreateBitcoinMultisigTx(t *testing.T) { + provider := &Provider{ + logger: nil, + cfg: &Config{Mode: SlaveMode}, + db: nil, + } + data := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" // Decode base64 dataBytes, _ := base64.StdEncoding.DecodeString(data) chainParam := &chaincfg.TestNet3Params - _, relayersMultisigInfo := // multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) - multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + _, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) - _, _, hexRawTx, _, err := CreateBitcoinMultisigTx(dataBytes, 5000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + _, _, hexRawTx, _, err := provider.CreateBitcoinMultisigTx(dataBytes, 5000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) fmt.Println("err: ", err) fmt.Println("hexRawTx: ", hexRawTx) } diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index eff65a51..3adcf0be 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -7,6 +7,9 @@ import ( "math/big" "net/http" "os" + "strings" + + relayTypes "github.com/icon-project/centralized-relay/relayer/types" ) func startSlave(c *Config, p *Provider) { @@ -47,7 +50,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { http.Error(w, "Error decoding request body", http.StatusInternalServerError) return } - sigs, _ := loadSigsFromDb(rsi.MsgSn, p) + sigs, _ := buildAndSignTxFromDbMessage(rsi.MsgSn, p) // return sigs to master returnData, _ := json.Marshal(sigs) w.Write(returnData) @@ -56,17 +59,23 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { } } -func loadSigsFromDb(sn *big.Int, p *Provider) ([][]byte, error) { +func buildAndSignTxFromDbMessage(sn *big.Int, p *Provider) ([][]byte, error) { key := sn.String() data, err := p.db.Get([]byte(key), nil) if err != nil { return nil, err } - var sigs [][]byte - err = json.Unmarshal(data, &sigs) + var message *relayTypes.Message + err = json.Unmarshal(data, &message) + if err != nil { + return nil, err + } + + _, _, _, relayerSigns, err := p.BuildAndPartSignBitcoinMessageTx(message, strings.Split(message.Dst, ".")[0]) if err != nil { return nil, err } - return sigs, nil + + return relayerSigns, nil } diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index c6c90454..7c6aaf3f 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -55,13 +55,19 @@ func TestRandomKeys(t *testing.T) { func TestBuildMultisigTapScript(t *testing.T) { chainParam := &chaincfg.TestNet3Params - _, relayersMultisigInfo := RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) + relayerPrivKeys, relayersMultisigInfo := RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) _, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) relayersMultisigAddress, err := AddressOnChain(chainParam, relayersMultisigWallet) fmt.Println("relayersMultisigAddress, err : ", relayersMultisigAddress, err) + fmt.Println("relayersPubKey Master : ", hex.EncodeToString(relayersMultisigInfo.PubKeys[0])) + fmt.Println("relayersPubKey Slave 1 : ", hex.EncodeToString(relayersMultisigInfo.PubKeys[1])) + fmt.Println("relayersPubKey Slave 2 : ", hex.EncodeToString(relayersMultisigInfo.PubKeys[2])) + fmt.Println("relayersPrivKey Master : ", relayerPrivKeys[0]) + fmt.Println("relayersPrivKey Slave 1 : ", relayerPrivKeys[1]) + fmt.Println("relayersPrivKey Slave 2 : ", relayerPrivKeys[2]) userMultisigAddress, err := AddressOnChain(chainParam, userMultisigWallet) fmt.Println("userMultisigAddress, err : ", userMultisigAddress, err) From 659dc232725d01c65e55895a1d4c625b5a2da6a8 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 3 Sep 2024 21:18:27 +0700 Subject: [PATCH 064/113] update to optimize params --- config.yaml | 2 +- relayer/chains/bitcoin/provider.go | 10 ++++---- relayer/chains/bitcoin/provider_route_test.go | 23 +++++++++++++++++++ relayer/chains/bitcoin/slave.go | 2 +- 4 files changed, 30 insertions(+), 7 deletions(-) diff --git a/config.yaml b/config.yaml index dfb361b3..e4432cc7 100644 --- a/config.yaml +++ b/config.yaml @@ -27,7 +27,7 @@ chains: protocals: - cx577f5e756abd89cbcba38a58508b60a12754d2f5 # - cxf5a0b146af1572e44775a40ef06c5a39b143ed1e - unisat-url: https://open-api-testnet.unisat.io/v1/indexer + unisat-url: https://open-api-testnet.unisat.io unisat-key: 60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d # start-height: 2874137 # start-height: 2874459 diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index e08ccf84..60a2b962 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -281,7 +281,7 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired uint64 ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired - resp, err := GetBtcUtxo(ctx, UNISAT_DEFAULT_TESTNET, p.cfg.UniSatKey, address, 0, 32) + resp, err := GetBtcUtxo(ctx, server, p.cfg.UniSatKey, address, 0, 32) if err != nil { return nil, fmt.Errorf("failed to query bitcoin UTXOs from unisat: %v", err) } @@ -308,7 +308,7 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired - resp, err := GetRuneUtxo(ctx, UNISAT_DEFAULT_TESTNET, address, runeId) + resp, err := GetRuneUtxo(ctx, server, address, runeId) if err != nil { return nil, 0, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) } @@ -439,7 +439,7 @@ func (p *Provider) CreateBitcoinMultisigTx( return inputs, msgTx, hexRawTx, txSigHashes, err } -func (p *Provider) BuildAndPartSignBitcoinMessageTx(message *relayTypes.Message, messageDstNetwork string) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { +func (p *Provider) BuildAndPartSignBitcoinMessageTx(messageData []byte, messageDstNetwork string) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { // get param for mainnet/testnet var chainParam *chaincfg.Params if messageDstNetwork == "0x1" { @@ -465,7 +465,7 @@ func (p *Provider) BuildAndPartSignBitcoinMessageTx(message *relayTypes.Message, return nil, nil, nil, nil, err } // build unsigned tx - inputs, msgTx, _, txSigHashes, err := p.CreateBitcoinMultisigTx(message.Data, 10000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) + inputs, msgTx, _, txSigHashes, err := p.CreateBitcoinMultisigTx(messageData, 10000, relayersMultisigWallet, chainParam, p.cfg.UniSatURL) if err != nil { return nil, nil, nil, nil, err } @@ -499,7 +499,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) return nil } else if p.cfg.Mode == MasterMode { - inputs, relayersMultisigWallet, msgTx, relayerSigs, err := p.BuildAndPartSignBitcoinMessageTx(message, messageDstDetail[0]) + inputs, relayersMultisigWallet, msgTx, relayerSigs, err := p.BuildAndPartSignBitcoinMessageTx(message.Data, messageDstDetail[0]) if err != nil { return err } diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index 4fb4a531..4ef71fe8 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -1,8 +1,10 @@ package bitcoin import ( + "bytes" "context" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" "math/big" @@ -56,6 +58,27 @@ func TestCreateBitcoinMultisigTx(t *testing.T) { fmt.Println("hexRawTx: ", hexRawTx) } +func TestBuildAndPartSignBitcoinMessageTx(t *testing.T) { + provider := &Provider{ + logger: nil, + cfg: &Config{Mode: SlaveMode}, + db: nil, + } + + data := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" + // Decode base64 + dataBytes, _ := base64.StdEncoding.DecodeString(data) + + _, _, msgTx, _, err := provider.BuildAndPartSignBitcoinMessageTx(dataBytes, "0x2") + fmt.Println("err: ", err) + + var rawTxBytes bytes.Buffer + msgTx.Serialize(&rawTxBytes) + + hexRawTx := hex.EncodeToString(rawTxBytes.Bytes()) + fmt.Println("hexRawTx: ", hexRawTx) +} + func TestProvider_Route(t *testing.T) { // Setup tempDir, err := os.MkdirTemp("", "bitcoin_provider_test") diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index 3adcf0be..3c51c842 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -72,7 +72,7 @@ func buildAndSignTxFromDbMessage(sn *big.Int, p *Provider) ([][]byte, error) { return nil, err } - _, _, _, relayerSigns, err := p.BuildAndPartSignBitcoinMessageTx(message, strings.Split(message.Dst, ".")[0]) + _, _, _, relayerSigns, err := p.BuildAndPartSignBitcoinMessageTx(message.Data, strings.Split(message.Dst, ".")[0]) if err != nil { return nil, err } From 033ec6dd86bacbf07e1fabebc90b921c326b2df8 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Mon, 9 Sep 2024 21:40:14 +0700 Subject: [PATCH 065/113] update connectors to bitcoin bridge OP_RETURN --- utils/multisig/multisig_test.go | 17 ++++-- utils/multisig/op_message.go | 91 ++++++++++++++++++++++++++++++--- 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 7c6aaf3f..188cc066 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -400,8 +400,6 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { // Add Bridge Message payload, _ := CreateBridgePayload( - 1, - "18403e24f5f5f7cf7a7bae8885d3e1d27ce5fd10", &XCallMessage{ Action: "Deposit", TokenAddress: "0:0", // bitcoin address @@ -409,7 +407,15 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { From: USER_MULTISIG_ADDRESS, //user Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), - }) + }, + 1, + "cx0000000000000000000000000000000000000009", + []string{ + "hx0000000000000000000000000000000000000001", + "hx0000000000000000000000000000000000000002", + "hx0000000000000000000000000000000000000003", + }, + ) scripts, _ := CreateBridgeMessageScripts(payload, 76) for i, script := range scripts { fmt.Println("OP_RETURN ", i, " script ", script) @@ -455,14 +461,15 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { decodedMessage, err := ReadBridgeMessage(signedMsgTx) fmt.Println("err decode: ", err) fmt.Println("-----------decodedMessage---------- ") - fmt.Println("ChainId: ", decodedMessage.ChainId) - fmt.Println("Address: ", decodedMessage.Address) fmt.Println("Message.Action: ", decodedMessage.Message.Action) fmt.Println("Message.TokenAddress: ", decodedMessage.Message.TokenAddress) fmt.Println("Message.From: ", decodedMessage.Message.From) fmt.Println("Message.To: ", decodedMessage.Message.To) fmt.Println("Message.Amount: ", decodedMessage.Message.Amount) fmt.Println("Message.Data: ", decodedMessage.Message.Data) + fmt.Println("ChainId: ", decodedMessage.ChainId) + fmt.Println("Address: ", decodedMessage.Receiver) + fmt.Println("Connectors: ", decodedMessage.Connectors) } func TestRadFiInitPool(t *testing.T) { diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index fa4b4ace..dbb29f4e 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -71,9 +71,10 @@ type RadFiIncreaseLiquidityMsg struct { } type BridgeDecodedMsg struct { - ChainId uint8 - Address string Message *XCallMessage + ChainId uint8 + Receiver string + Connectors []string } type RadFiDecodedMsg struct { @@ -85,18 +86,77 @@ type RadFiDecodedMsg struct { IncreaseLiquidityMsg *RadFiIncreaseLiquidityMsg } -func CreateBridgePayload(chainId uint8, address string, message *XCallMessage) ([]byte, error) { +func AddressToPayload(address string) ([]byte, error) { + prefix := address[0:2] + var prefixType uint8 // max number of supported type is 7 + switch prefix { + case "0x": + prefixType = 1 + case "hx": + prefixType = 2 + case "cx": + prefixType = 3 + default: + return nil, fmt.Errorf("address type not supported") + } + addressBytes, err := hex.DecodeString(address[2:]) + if err != nil { + return nil, fmt.Errorf("could decode string address - Error %v", err) + } + + addressBytesLen := uint8(len(addressBytes)) + if addressBytesLen > 32 { + return nil, fmt.Errorf("address length not supported") + } + prefixByte := byte((prefixType << 5) ^ (addressBytesLen - 1)) + + return append([]byte{prefixByte}, addressBytes...), nil +} + +func PayloadToAddress(payload []byte) (string, []byte, error) { + prefixByte := payload[0] + prefixType := uint8(prefixByte >> 5) + var prefix string + switch prefixType { + case 1: + prefix = "0x" + case 2: + prefix = "hx" + case 3: + prefix = "cx" + default: + return "", nil, fmt.Errorf("prefix type not supported") + } + addressBytesLen := uint8((prefixByte << 3 >> 3) + 1) + address := prefix + hex.EncodeToString(payload[1:addressBytesLen+1]) + remainPayload := payload[addressBytesLen+1:] + + return address, remainPayload, nil +} + +func CreateBridgePayload(message *XCallMessage, chainId uint8, receiver string, connectors []string) ([]byte, error) { payload, err := codec.RLP.MarshalToBytes(message) if err != nil { return nil, fmt.Errorf("could not marshal message - Error %v", err) } - bytesAddress, err := hex.DecodeString(address) + payload = append(payload, chainId) + + receiverBytes, err := AddressToPayload(receiver) if err != nil { - return nil, fmt.Errorf("could decode string address - Error %v", err) + return nil, err + } + payload = append(payload, receiverBytes...) + + for _, connector := range connectors { + connectorBytes, err := AddressToPayload(connector) + if err != nil { + return nil, err + } + payload = append(payload, connectorBytes...) } - return append(append(payload, chainId), bytesAddress...), nil + return payload, nil } func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { @@ -274,11 +334,26 @@ func ReadBridgeMessage(transaction *wire.MsgTx) (*BridgeDecodedMsg, error) { if err != nil { return nil, fmt.Errorf("could not unmarshal message - Error %v", err) } + chainId := uint8(remainData[0]) + receiver, remainData, err := PayloadToAddress(remainData[1:]) + if err != nil { + return nil, err + } + connectors := []string{} + var connector string + for len(remainData) > 0 { + connector, remainData, err = PayloadToAddress(remainData) + if err != nil { + return nil, err + } + connectors = append(connectors, connector) + } return &BridgeDecodedMsg { - ChainId: uint8(remainData[0]), - Address: hex.EncodeToString(remainData[1:]), Message: &message, + ChainId: chainId, + Receiver: receiver, + Connectors: connectors, }, nil } From 086587f579736ee4f6d2c60dc31e28a92864ed55 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 17 Sep 2024 10:45:24 +0700 Subject: [PATCH 066/113] update bitcoin deposit cases for provider route unit test --- relayer/chains/bitcoin/provider.go | 2 +- relayer/chains/bitcoin/provider_route_test.go | 396 ++++++++++++++++++ 2 files changed, 397 insertions(+), 1 deletion(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 60a2b962..70edb73a 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -1002,7 +1002,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err from := p.cfg.NID + "/" + p.cfg.Address decodeMessage, _ := codec.RLP.MarshalToBytes(messageInfo) - data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Address, uint(tx.Height), p.cfg.Protocals) + data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(tx.Height), p.cfg.Protocals) return &relayTypes.Message{ // TODO: diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index 4ef71fe8..abbdd132 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -13,6 +13,7 @@ import ( "testing" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/txscript" "github.com/icon-project/centralized-relay/relayer/events" "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" @@ -134,3 +135,398 @@ func TestProvider_Route(t *testing.T) { _, err = db.Get(key, nil) assert.Error(t, err) // Should return an error as the key no longer exists } + +func TestDepositBitcoinToIcon(t *testing.T) { + chainParam := &chaincfg.TestNet3Params + + inputs := []*multisig.UTXO{ + { + IsRelayersMultisig: false, + TxHash: "4933e04e3d9320df6e9f046ff83cfc3e9f884d8811df0539af7aaca0218189aa", + OutputIdx: 0, + OutputAmount: 4000000, + }, + } + + outputs := []*multisig.OutputTx{} + + // Add Bridge Message + payload, _ := multisig.CreateBridgePayload( + &multisig.XCallMessage{ + Action: "Deposit", + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), + }, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + ) + scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + + // Add transfering bitcoin to relayer multisig + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", + Amount: 1000000, + }) + + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + + tapSigParams := multisig.TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + // COMBINE SIGNS + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // TODO: test the signedMsgTx +} + +func TestDepositBitcoinToIconFail1(t *testing.T) { + chainParam := &chaincfg.TestNet3Params + + inputs := []*multisig.UTXO{ + { + IsRelayersMultisig: false, + TxHash: "eeb8c9f79ecfe7c084b2af95bf82acebd130185a0d188283d78abb58d85eddff", + OutputIdx: 4, + OutputAmount: 2999000, + }, + } + + outputs := []*multisig.OutputTx{} + + // Add Bridge Message + payload, _ := multisig.CreateBridgePayload( + &multisig.XCallMessage{ + Action: "Deposit", + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), + }, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + ) + scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + + // Add transfering bitcoin to relayer multisig + // outputs = append(outputs, &multisig.OutputTx{ + // ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", + // Amount: 1000000, + // }) + + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + + tapSigParams := multisig.TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + // COMBINE SIGNS + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // TODO: test the signedMsgTx +} + +func TestDepositBitcoinToIconFail2(t *testing.T) { + chainParam := &chaincfg.TestNet3Params + + inputs := []*multisig.UTXO{ + { + IsRelayersMultisig: false, + TxHash: "0416795b227e1a6a64eeb7bf7542d15964d18ac4c4732675d3189cda8d38bed7", + OutputIdx: 3, + OutputAmount: 2998000, + }, + } + + outputs := []*multisig.OutputTx{} + + // Add Bridge Message + payload, _ := multisig.CreateBridgePayload( + &multisig.XCallMessage{ + Action: "Deposit", + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), + }, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + ) + scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + + // Add transfering bitcoin to relayer multisig + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", + Amount: 1000, + }) + + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + + tapSigParams := multisig.TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + // COMBINE SIGNS + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // TODO: test the signedMsgTx +} + +func TestDepositBitcoinToIconFail3(t *testing.T) { + chainParam := &chaincfg.TestNet3Params + + inputs := []*multisig.UTXO{ + { + IsRelayersMultisig: false, + TxHash: "dc21f89436d9fbda2cc521ed9b8988c7cbf84cdc67d728b2b2709a5efe7e775a", + OutputIdx: 4, + OutputAmount: 2996000, + }, + } + + outputs := []*multisig.OutputTx{} + + // Add Bridge Message + payload, _ := multisig.CreateBridgePayload( + &multisig.XCallMessage{ + Action: "Deposit", + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000).Bytes(), + Data: []byte(""), + }, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + ) + scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + + // Add transfering bitcoin to relayer multisig + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", + Amount: 10000, + }) + + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + + tapSigParams := multisig.TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + // COMBINE SIGNS + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // TODO: test the signedMsgTx +} + +func TestDepositBitcoinToIconFail4(t *testing.T) { + chainParam := &chaincfg.TestNet3Params + + inputs := []*multisig.UTXO{ + { + IsRelayersMultisig: false, + TxHash: "1e29fa62942f92dd4cf688e219641b54229fbc2ec2dc74cc9c1c7f247c7172b2", + OutputIdx: 4, + OutputAmount: 2985000, + }, + } + + outputs := []*multisig.OutputTx{} + + // Add Bridge Message + payload, _ := multisig.CreateBridgePayload( + &multisig.XCallMessage{ + Action: "Withdraw", + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000).Bytes(), + Data: []byte(""), + }, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + ) + scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + + // Add transfering bitcoin to relayer multisig + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", + Amount: 10000, + }) + + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + + tapSigParams := multisig.TapSigParams { + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + // COMBINE SIGNS + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // TODO: test the signedMsgTx +} \ No newline at end of file From 008204e706afd48d7dbb69fee7ae87faf6a0fa7a Mon Sep 17 00:00:00 2001 From: Shall Date: Sun, 22 Sep 2024 19:57:17 +0700 Subject: [PATCH 067/113] feat: add logic to rollback message if an error occurs --- relayer/chains/bitcoin/client.go | 76 +- relayer/chains/bitcoin/master.go | 27 +- relayer/chains/bitcoin/provider.go | 738 ++++++++++-------- relayer/chains/bitcoin/provider_route_test.go | 241 +++--- relayer/chains/bitcoin/slave.go | 18 +- relayer/chains/icon/query.go | 5 - utils/multisig/tx.go | 66 +- utils/multisig/utils.go | 21 +- 8 files changed, 654 insertions(+), 538 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 76599fed..b319e795 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -3,7 +3,10 @@ package bitcoin import ( "bytes" "context" + "encoding/json" "fmt" + "io" + "net/http" "github.com/btcsuite/btcd/btcjson" "github.com/btcsuite/btcd/btcutil" @@ -16,6 +19,14 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" ) +type FeeResponse struct { + FastestFee uint64 `json:"fastestFee"` + HalfHourFee uint64 `json:"halfHourFee"` + HourFee uint64 `json:"hourFee"` + EconomyFee uint64 `json:"economyFee"` + MinimumFee uint64 `json:"minimumFee"` +} + type IClient interface { // IsConnected() bool // Reconnect() error @@ -26,8 +37,10 @@ type IClient interface { Subscribe(ctx context.Context, _, query string) error Unsubscribe(ctx context.Context, _, query string) error GetFee(ctx context.Context) (uint64, error) + GetFeeFromMempool(mempoolURL string) (uint64, error) DecodeAddress(btcAddr string) ([]byte, error) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearchRes, error) + SendRawTransaction(ctx context.Context, url string, rawMsg []json.RawMessage) (string, error) } // grouped rpc api clients @@ -64,13 +77,12 @@ func newClient(ctx context.Context, rpcUrl string, user string, password string, // query block height func (c *Client) GetLatestBlockHeight(ctx context.Context) (uint64, error) { // Get the current block height - // blockCount, err := c.client.GetBlockCount() - // if err != nil { - // return 0, err - // } + blockCount, err := c.client.GetBlockCount() + if err != nil { + return 0, err + } - // return uint64(blockCount), nil - return 2874461, nil + return uint64(blockCount), nil } // get transaction reciept @@ -177,3 +189,55 @@ func (c *Client) DecodeAddress(btcAddr string) ([]byte, error) { return destinationAddrByte, nil } + +func (c *Client) SendRawTransaction(ctx context.Context, url string, rawMsg []json.RawMessage) (string, error) { + + if len(rawMsg) == 0 { + return "", fmt.Errorf("empty raw message") + } + + resp, err := http.Post(url, "text/plain", bytes.NewReader(rawMsg[0])) + if err != nil { + c.log.Error("failed to send transaction", zap.Error(err)) + return "", err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil || resp.StatusCode != http.StatusOK { + c.log.Error("failed to broadcast transaction", zap.Int("status", resp.StatusCode), zap.String("response", string(body))) + return "", fmt.Errorf("broadcast failed: %v", err) + } + + return string(body), nil +} + +func (c *Client) GetFeeFromMempool(mempoolURL string) (uint64, error) { + + client := &http.Client{} + + req, err := http.NewRequest("GET", mempoolURL, nil) + + if err != nil { + c.log.Error("Failed to create request: %v", zap.Error(err)) + } + + resp, err := client.Do(req) + + if err != nil { + c.log.Error("Failed to send request: %v", zap.Error(err)) + } + + defer resp.Body.Close() + + if err != nil { + c.log.Error("Error reading response: %v", zap.Error(err)) + } + + var feeResponse FeeResponse + if err := json.NewDecoder(resp.Body).Decode(&feeResponse); err != nil { + return 0, err + } + + return feeResponse.FastestFee, nil +} diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index 94d210c8..27d7a898 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -71,33 +71,10 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(response) } -// func callSlaves(txId string) { -// fmt.Println("Master request slave") -// slavePort1 := os.Getenv("SLAVE_SERVER_1") -// slavePort2 := os.Getenv("SLAVE_SERVER_2") -// // Call slave to get more data -// var wg sync.WaitGroup -// responses := make(chan string, 2) - -// wg.Add(2) -// go requestPartialSign(slavePort1, txId, responses, &wg) -// go requestPartialSign(slavePort2, txId, responses, &wg) - -// go func() { -// wg.Wait() -// close(responses) -// }() - -// for res := range responses { -// fmt.Println("Received response from slave: ", res) -// } -// } - -func requestPartialSign(url string, slaveRequestData []byte, responses chan<- [][]byte, wg *sync.WaitGroup) { +func requestPartialSign(apiKey string, url string, slaveRequestData []byte, responses chan<- [][]byte, wg *sync.WaitGroup) { defer wg.Done() client := &http.Client{} - apiKeyHeader := os.Getenv("API_KEY") payload := bytes.NewBuffer(slaveRequestData) req, err := http.NewRequest("POST", url, payload) @@ -105,7 +82,7 @@ func requestPartialSign(url string, slaveRequestData []byte, responses chan<- [] log.Fatalf("Failed to create request: %v", err) } - req.Header.Add("x-api-key", apiKeyHeader) + req.Header.Add("x-api-key", apiKey) resp, err := client.Do(req) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 70edb73a..cf282ce1 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -9,16 +9,15 @@ import ( "log" "math/big" "runtime" + "sort" "strconv" "strings" "sync" "time" - wasmTypes "github.com/CosmWasm/wasmd/x/wasm/types" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - sdkTypes "github.com/cosmos/cosmos-sdk/types" "path/filepath" @@ -29,7 +28,7 @@ import ( relayTypes "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" "github.com/icon-project/goloop/common/codec" - jsoniter "github.com/json-iterator/go" + "github.com/syndtr/goleveldb/leveldb" "go.uber.org/zap" ) @@ -37,11 +36,14 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) var ( - BTCToken = "0:0" - MethodDeposit = "Deposit" - MasterMode = "master" - SlaveMode = "slave" - BtcSlaveDB = "btc_slave.db" + BTCToken = "0:0" + MethodDeposit = "Deposit" + MethodWithdrawTo = "WithdrawTo" + MasterMode = "master" + SlaveMode = "slave" + BtcDB = "btc.db" + MinSatsRequired = 1000 + WitnessSize = 385 ) var chainIdToName = map[uint8]string{ @@ -62,6 +64,18 @@ type MessageDecoded struct { type slaveRequestParams struct { MsgSn *big.Int `json:"msgSn"` } +type StoredMessageData struct { + OriginalMessage *relayTypes.Message + TxHash string + OutputIndex uint32 + Amount uint64 + RecipientAddress string + SenderAddress string + RuneId string + RuneAmount uint64 + ActionMethod string + TokenAddress string +} type Provider struct { logger *zap.Logger @@ -74,27 +88,28 @@ type Provider struct { bearToken string httpServer chan struct{} db *leveldb.DB + chainParam *chaincfg.Params } type Config struct { provider.CommonConfig `json:",inline" yaml:",inline"` - OpCode int `json:"op-code" yaml:"op-code"` - UniSatURL string `json:"unisat-url" yaml:"unisat-url"` - UniSatKey string `json:"unisat-key" yaml:"unisat-key"` - Type string `json:"type" yaml:"type"` - User string `json:"rpc-user" yaml:"rpc-user"` - Password string `json:"rpc-password" yaml:"rpc-password"` - Protocals []string `yaml:"protocals"` - Mode string `json:"mode" yaml:"mode"` - SlaveServer1 string `json:"slave-server-1" yaml:"slave-server-1"` - SlaveServer2 string `json:"slave-server-2" yaml:"slave-server-2"` - Port string `json:"port" yaml:"port"` - ApiKey string `json:"api-key" yaml:"api-key"` - MasterPubKey string `json:"masterPubKey" yaml:"masterPubKey"` - Slave1PubKey string `json:"slave1PubKey" yaml:"slave1PubKey"` - Slave2PubKey string `json:"slave2PubKey" yaml:"slave2PubKey"` - RelayerPrivKey string `json:"relayerPrivKey" yaml:"relayerPrivKey"` - RecoveryLockTime int `json:"recoveryLockTime" yaml:"recoveryLockTime"` + OpCode int `json:"op-code" yaml:"op-code"` + UniSatURL string `json:"unisat-url" yaml:"unisat-url"` + UniSatKey string `json:"unisat-key" yaml:"unisat-key"` + MempoolURL string `json:"mempool-url" yaml:"mempool-url"` + Type string `json:"type" yaml:"type"` + User string `json:"rpc-user" yaml:"rpc-user"` + Password string `json:"rpc-password" yaml:"rpc-password"` + Mode string `json:"mode" yaml:"mode"` + SlaveServer1 string `json:"slave-server-1" yaml:"slave-server-1"` + SlaveServer2 string `json:"slave-server-2" yaml:"slave-server-2"` + Port string `json:"port" yaml:"port"` + ApiKey string `json:"api-key" yaml:"api-key"` + MasterPubKey string `json:"masterPubKey" yaml:"masterPubKey"` + Slave1PubKey string `json:"slave1PubKey" yaml:"slave1PubKey"` + Slave2PubKey string `json:"slave2PubKey" yaml:"slave2PubKey"` + RelayerPrivKey string `json:"relayerPrivKey" yaml:"relayerPrivKey"` + RecoveryLockTime int `json:"recoveryLockTime" yaml:"recoveryLockTime"` } // NewProvider returns new Icon provider @@ -107,7 +122,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri } // Create the database file path - dbPath := filepath.Join(homepath+"/data", BtcSlaveDB) + dbPath := filepath.Join(homepath+"/data", BtcDB) // Open the database, creating it if it doesn't exist db, err := leveldb.OpenFile(dbPath, nil) @@ -120,8 +135,11 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri db.Close() // Close the database if client creation fails return nil, fmt.Errorf("failed to create new client: %v", err) } - - c.ChainName = chainName + chainParam := &chaincfg.TestNet3Params + if c.NID == "0x1.btc" { + chainParam = &chaincfg.MainNetParams + } + c.HomeDir = homepath c.HomeDir = homepath p := &Provider{ @@ -131,6 +149,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri LastSerialNumFunc: func() *big.Int { return big.NewInt(0) }, httpServer: make(chan struct{}), db: db, // Add the database to the Provider + chainParam: chainParam, } // Run an http server to help btc interact each others go func() { @@ -152,8 +171,8 @@ func (p *Provider) CallSlaves(slaveRequestData []byte) [][][]byte { var wg sync.WaitGroup wg.Add(2) - go requestPartialSign(p.cfg.SlaveServer1, slaveRequestData, responses, &wg) - go requestPartialSign(p.cfg.SlaveServer2, slaveRequestData, responses, &wg) + go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer1, slaveRequestData, responses, &wg) + go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer2, slaveRequestData, responses, &wg) go func() { wg.Wait() @@ -287,7 +306,14 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired uint64 } outputs := []*multisig.UTXO{} var totalAmount uint64 - for _, utxo := range resp.Data.Utxo { + + utxos := resp.Data.Utxo + // sort utxos by amount in descending order + sort.Slice(utxos, func(i, j int) bool { + return utxos[i].Satoshi.Cmp(utxos[j].Satoshi) == 1 + }) + + for _, utxo := range utxos { if totalAmount >= amountRequired { break } @@ -312,9 +338,16 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout if err != nil { return nil, 0, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) } + + utxos := resp.Data.Utxo + // sort utxos by amount in descending order + sort.Slice(utxos, func(i, j int) bool { + return utxos[i].Satoshi.Cmp(utxos[j].Satoshi) == 1 + }) + outputs := []*multisig.UTXO{} var totalAmount uint64 - for _, utxo := range resp.Data.Utxo { + for _, utxo := range utxos { if totalAmount >= amountRequired { break } @@ -336,77 +369,151 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout func (p *Provider) CreateBitcoinMultisigTx( messageData []byte, - feePerOutput uint64, - relayersMultisigWallet *multisig.MultisigWallet, - chainParam *chaincfg.Params, - server string, + feeRate uint64, + decodedData *MessageDecoded, + msWallet *multisig.MultisigWallet, ) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { // ----- BUILD OUTPUTS ----- outputs := []*multisig.OutputTx{} - var bitcoinAmountRequired, runeAmountRequired uint64 + var bitcoinAmountRequired uint64 = uint64(MinSatsRequired) + var runeAmountRequired uint64 var runeRequired multisig.Rune - decodedData, opreturnData, err := decodeWithdrawToMessage(messageData) - // add bridge message to output - scripts, _ := multisig.CreateBridgeMessageScripts(opreturnData, 76) - for _, script := range scripts { - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, - }) - } + // add withdraw output - if err == nil { - amount := new(big.Int).SetBytes(decodedData.Amount).Uint64() - if decodedData.Action == "WithdrawTo" { - if decodedData.TokenAddress == "0:0" { - // transfer btc - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: decodedData.To, - Amount: amount, - }) - - bitcoinAmountRequired = amount - } else { - // transfer rune - runeAddress := strings.Split(decodedData.TokenAddress, ":") - blockNumber, _ := strconv.ParseUint(runeAddress[0], 10, 64) - txIndex, _ := strconv.ParseUint(runeAddress[0], 10, 32) - runeRequired = multisig.Rune{ - BlockNumber: blockNumber, - TxIndex: uint32(txIndex), - } - runeScript, _ := multisig.CreateRuneTransferScript( - runeRequired, - new(big.Int).SetUint64(amount), - uint64(len(outputs)+2), - ) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: runeScript, - }) - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: decodedData.To, - Amount: 1000, - }) - - bitcoinAmountRequired = 1000 - runeAmountRequired = amount + + amount := new(big.Int).SetBytes(decodedData.Amount).Uint64() + if decodedData.Action == MethodWithdrawTo || decodedData.Action == MethodDeposit { + if decodedData.TokenAddress == BTCToken { + // transfer btc + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: decodedData.To, + Amount: amount, + }) + + bitcoinAmountRequired = amount + } else { + // transfer rune + runeAddress := strings.Split(decodedData.TokenAddress, ":") + blockNumber, _ := strconv.ParseUint(runeAddress[0], 10, 64) + txIndex, _ := strconv.ParseUint(runeAddress[0], 10, 32) + runeRequired = multisig.Rune{ + BlockNumber: blockNumber, + TxIndex: uint32(txIndex), } + runeScript, _ := multisig.CreateRuneTransferScript( + runeRequired, + new(big.Int).SetUint64(amount), + uint64(len(outputs)+2), + ) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: runeScript, + }) + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: decodedData.To, + Amount: uint64(MinSatsRequired), + }) + runeAmountRequired = amount } } // ----- BUILD INPUTS ----- - relayersMultisigAddress, err := multisig.AddressOnChain(chainParam, relayersMultisigWallet) + rlMsAddress, err := multisig.AddressOnChain(p.chainParam, msWallet) if err != nil { return nil, nil, "", nil, err } - relayersMultisigAddressStr := relayersMultisigAddress.String() + msAddressStr := rlMsAddress.String() + + inputs, estFee, err := p.computeTx(feeRate, bitcoinAmountRequired, runeAmountRequired, decodedData.TokenAddress, msAddressStr, runeRequired, outputs, msWallet) + if err != nil { + return nil, nil, "", nil, err + } + // create raw tx + msgTx, hexRawTx, txSigHashes, err := multisig.CreateMultisigTx(inputs, outputs, estFee, msWallet, nil, p.chainParam, msAddressStr, 0) + + return inputs, msgTx, hexRawTx, txSigHashes, err +} + +// calculateTxSize calculates the size of a transaction given the inputs, outputs, estimated fee, change address, chain parameters, and multisig wallet. +// It returns the size of the transaction in bytes and an error if any occurs during the process. +func (p *Provider) calculateTxSize(inputs []*multisig.UTXO, outputs []*multisig.OutputTx, estFee uint64, changeAddress string, msWallet *multisig.MultisigWallet) (int, error) { + msgTx, _, _, err := multisig.CreateMultisigTx(inputs, outputs, estFee, msWallet, msWallet, p.chainParam, changeAddress, 0) + if err != nil { + return 0, err + } + var rawTxBytes bytes.Buffer + err = msgTx.Serialize(&rawTxBytes) + if err != nil { + return 0, err + } + txSize := len(rawTxBytes.Bytes()) + WitnessSize + return txSize, nil +} + +func (p *Provider) computeTx(feeRate, satsToSend, runeToSend uint64, runeId, changeAddress string, runeRequired multisig.Rune, outputs []*multisig.OutputTx, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, uint64, error) { + + outputsCopy := make([]*multisig.OutputTx, len(outputs)) + copy(outputsCopy, outputs) + + inputs, err := p.selectUnspentOutputs(satsToSend, runeToSend, runeId, runeRequired, outputsCopy, changeAddress) + sumSelectedOutputs := multisig.SumInputsSat(inputs) + if err != nil { + return nil, 0, err + } + + txSize, err := p.calculateTxSize(inputs, outputsCopy, 0, changeAddress, msWallet) + if err != nil { + return nil, 0, err + } + + estFee := uint64(txSize) * feeRate + count := 0 + loopEntered := false + var iterationOutputs []*multisig.OutputTx + + for sumSelectedOutputs < satsToSend+estFee { + loopEntered = true + // Create a fresh copy of outputs for each iteration + iterationOutputs := make([]*multisig.OutputTx, len(outputs)) + copy(iterationOutputs, outputs) + + newSatsToSend := satsToSend + estFee + var err error + selectedUnspentOutputs, err := p.selectUnspentOutputs(newSatsToSend, runeToSend, runeId, runeRequired, iterationOutputs, changeAddress) + if err != nil { + return nil, 0, err + } + + sumSelectedOutputs = multisig.SumInputsSat(selectedUnspentOutputs) + + txSize, err := p.calculateTxSize(selectedUnspentOutputs, iterationOutputs, estFee, changeAddress, msWallet) + if err != nil { + return nil, 0, err + } + + estFee = feeRate * uint64(txSize) + + count += 1 + if count > 500 { + return nil, 0, fmt.Errorf("Not enough sats for fee") + } + } + // Need to do that cause avoid the same outputs being used for multiple transactions + outputs = outputsCopy + if loopEntered { + outputs = iterationOutputs + } + + return inputs, estFee, nil +} + +func (p *Provider) selectUnspentOutputs(satToSend uint64, runeToSend uint64, runeId string, runeRequired multisig.Rune, outputs []*multisig.OutputTx, changeAddress string) ([]*multisig.UTXO, error) { // add tx fee the the required bitcoin amount inputs := []*multisig.UTXO{} - var inputsSatNeeded uint64 - if runeAmountRequired != 0 { + if runeToSend != 0 { // query rune UTXOs from unisat - runeInputs, runeChangeAmount, err := GetRuneUTXOs(server, relayersMultisigAddressStr, decodedData.TokenAddress, runeAmountRequired, 3) + runeInputs, runeChangeAmount, err := GetRuneUTXOs(p.cfg.UniSatURL, changeAddress, runeId, runeToSend, 3) if err != nil { - return nil, nil, "", nil, err + return nil, err } inputs = append(inputs, runeInputs...) // add rune change to outputs @@ -419,67 +526,75 @@ func (p *Provider) CreateBitcoinMultisigTx( OpReturnScript: runeScript, }) outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: relayersMultisigAddressStr, - Amount: 1000, + ReceiverAddress: changeAddress, + Amount: uint64(MinSatsRequired), }) - inputsSatNeeded = 1000 } - txFee := uint64(len(outputs)) * feePerOutput - inputsSatNeeded += bitcoinAmountRequired + txFee - // todo: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo + + // TODO: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo // query bitcoin UTXOs from unisat - bitcoinInputs, err := p.GetBitcoinUTXOs(server, relayersMultisigAddressStr, inputsSatNeeded, 3) + bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, changeAddress, satToSend, 3) if err != nil { - return nil, nil, "", nil, err + return nil, err } inputs = append(inputs, bitcoinInputs...) - // create raw tx - msgTx, hexRawTx, txSigHashes, err := multisig.CreateMultisigTx(inputs, outputs, txFee, relayersMultisigWallet, nil, chainParam, relayersMultisigAddressStr, 0) - return inputs, msgTx, hexRawTx, txSigHashes, err + return inputs, nil } -func (p *Provider) BuildAndPartSignBitcoinMessageTx(messageData []byte, messageDstNetwork string) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { - // get param for mainnet/testnet - var chainParam *chaincfg.Params - if messageDstNetwork == "0x1" { - chainParam = &chaincfg.MainNetParams - } else if messageDstNetwork == "0x2" { - chainParam = &chaincfg.TestNet3Params - } else { - return nil, nil, nil, nil, fmt.Errorf("invalid message dst network: %v", messageDstNetwork) - } - // build Multisig Wallet from config +// add tx fee the the required bitcoin amount + +func (p *Provider) buildMultisigWallet() (*multisig.MultisigWallet, error) { masterPubKey, _ := hex.DecodeString(p.cfg.MasterPubKey) slave1PubKey, _ := hex.DecodeString(p.cfg.Slave1PubKey) slave2PubKey, _ := hex.DecodeString(p.cfg.Slave2PubKey) relayersMultisigInfo := multisig.MultisigInfo{ - PubKeys: [][]byte{masterPubKey, slave1PubKey, slave2PubKey}, - EcPubKeys: nil, - NumberRequiredSigs: 3, - RecoveryPubKey: masterPubKey, - RecoveryLockTime: uint64(p.cfg.RecoveryLockTime), + PubKeys: [][]byte{masterPubKey, slave1PubKey, slave2PubKey}, + EcPubKeys: nil, + NumberRequiredSigs: 3, + RecoveryPubKey: masterPubKey, + RecoveryLockTime: uint64(p.cfg.RecoveryLockTime), } - relayersMultisigWallet, err := multisig.BuildMultisigWallet(&relayersMultisigInfo) + msWallet, err := multisig.BuildMultisigWallet(&relayersMultisigInfo) if err != nil { - return nil, nil, nil, nil, err - } - // build unsigned tx - inputs, msgTx, _, txSigHashes, err := p.CreateBitcoinMultisigTx(messageData, 10000, relayersMultisigWallet, chainParam, p.cfg.UniSatURL) - if err != nil { - return nil, nil, nil, nil, err + p.logger.Error("failed to build multisig wallet: %v", zap.Error(err)) + return nil, err } + + return msWallet, nil +} + +func (p *Provider) partSignTx(msgTx *wire.MsgTx, inputs []*multisig.UTXO, msWallet *multisig.MultisigWallet, txSigHashes *txscript.TxSigHashes) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { tapSigParams := multisig.TapSigParams{ TxSigHashes: txSigHashes, - RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + RelayersPKScript: msWallet.PKScript, + RelayersTapLeaf: msWallet.TapLeaves[0], UserPKScript: []byte{}, UserTapLeaf: txscript.TapLeaf{}, } // relayer sign tx - relayerSigs, err := multisig.PartSignOnRawExternalTx(p.cfg.RelayerPrivKey, msgTx, inputs, tapSigParams, chainParam, false) + relayerSigs, err := multisig.PartSignOnRawExternalTx(p.cfg.RelayerPrivKey, msgTx, inputs, tapSigParams, p.chainParam, false) - return inputs, relayersMultisigWallet, msgTx, relayerSigs, err + return inputs, msWallet, msgTx, relayerSigs, err +} + +func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { + msWallet, err := p.buildMultisigWallet() + if err != nil { + return nil, nil, nil, nil, err + } + feeRate, err := p.client.GetFeeFromMempool(p.cfg.MempoolURL + "/fees/recommended") + if err != nil { + p.logger.Error("failed to get recommended fee from mempool", zap.Error(err)) + feeRate = 0 + } + inputs, msgTx, _, txSigHashes, err := p.buildTxMessage(message, feeRate, msWallet) + if err != nil { + p.logger.Error("failed to build tx message: %v", zap.Error(err)) + return nil, nil, nil, nil, err + } + inputs, msWallet, msgTx, relayerSigs, err := p.partSignTx(msgTx, inputs, msWallet, txSigHashes) + return inputs, msWallet, msgTx, relayerSigs, err } func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { @@ -487,20 +602,23 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb messageDstDetail := strings.Split(message.Dst, ".") if strings.Split(message.Src, ".")[1] == "icon" && messageDstDetail[1] == "btc" { + if p.cfg.Mode == SlaveMode { // store the message in LevelDB key := []byte(message.Sn.String()) value, _ := json.Marshal(message) err := p.db.Put(key, value, nil) if err != nil { - return fmt.Errorf("failed to store message in LevelDB: %v", err) + p.logger.Error("failed to store message in LevelDB: %v", zap.Error(err)) + return err } - p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) return nil } else if p.cfg.Mode == MasterMode { - inputs, relayersMultisigWallet, msgTx, relayerSigs, err := p.BuildAndPartSignBitcoinMessageTx(message.Data, messageDstDetail[0]) + + inputs, msWallet, msgTx, relayerSigs, err := p.HandleBitcoinMessageTx(message) if err != nil { + p.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) return err } totalSigs := [][][]byte{relayerSigs} @@ -510,14 +628,36 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb } slaveRequestData, _ := json.Marshal(rsi) slaveSigs := p.CallSlaves(slaveRequestData) + p.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) totalSigs = append(totalSigs, slaveSigs...) // combine sigs - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, relayersMultisigWallet, 0, totalSigs) + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, msWallet, 0, msWallet, 0, totalSigs) + + if err != nil { + p.logger.Error("err combine tx: ", zap.Error(err)) + } + p.logger.Info("signedMsgTx", zap.Any("transaction", signedMsgTx)) + var buf bytes.Buffer + err = signedMsgTx.Serialize(&buf) + + if err != nil { + log.Fatal(err) + } + + txSize := len(buf.Bytes()) + p.logger.Info("--------------------txSize--------------------", zap.Int("size", txSize)) + signedMsgTxHex := hex.EncodeToString(buf.Bytes()) + p.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + + // Broadcast transaction to bitcoin network + txHash, err := p.client.SendRawTransaction(ctx, p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(`"` + signedMsgTxHex + `"`)}) + if err != nil { - fmt.Println("err combine tx: ", err) + p.logger.Error("failed to send raw transaction", zap.Error(err)) + return err } - // TODO: Broadcast transaction to bitcoin network - fmt.Println("signedMsgTx:", signedMsgTx) + + p.logger.Info("txHash", zap.String("transaction_hash", txHash)) // TODO: After successful broadcast, request slaves to remove the message from LevelDB if it exists } } @@ -528,47 +668,57 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb return nil } +func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { + outputs := []*multisig.OutputTx{} + decodedData := &MessageDecoded{} + switch message.EventType { + case events.EmitMessage: + data, opreturnData, err := decodeWithdrawToMessage(message.Data) + decodedData = data + if err != nil { + p.logger.Error("failed to decode message: %v", zap.Error(err)) + return nil, nil, "", nil, err + } + scripts, _ := multisig.CreateBridgeMessageScripts(opreturnData, 76) + for _, script := range scripts { + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + case events.RollbackMessage: + data, err := p.db.Get([]byte(message.Sn.String()), nil) + if err != nil { + return nil, nil, "", nil, fmt.Errorf("failed to retrieve stored data: %v", err) + } + var storedData StoredMessageData + err = json.Unmarshal(data, &storedData) + if err != nil { + return nil, nil, "", nil, fmt.Errorf("failed to unmarshal stored data: %v", err) + } + decodedData.Action = storedData.ActionMethod + decodedData.To = storedData.SenderAddress + decodedData.TokenAddress = storedData.TokenAddress + decodedData.Amount = []byte(fmt.Sprintf("%d", storedData.Amount)) + if storedData.RuneId != "" { + decodedData.Amount = []byte(fmt.Sprintf("%d", storedData.RuneAmount)) + } + return nil, nil, "", nil, nil + default: + return nil, nil, "", nil, fmt.Errorf("unknown event type: %s", message.EventType) + } + + inputs, msgTx, hexRawTx, txSigHashes, err := p.CreateBitcoinMultisigTx(message.Data, feeRate, decodedData, msWallet) + return inputs, msgTx, hexRawTx, txSigHashes, err +} + // call the smart contract to send the message func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (string, error) { - // rawMsg, err := p.getRawContractMessage(message) - // if err != nil { - // return nil, err - // } - - // var contract string - - // switch message.EventType { - // case events.EmitMessage, events.RevertMessage, events.SetAdmin, events.ClaimFee, events.SetFee: - // //contract = p.cfg.Contracts[relayTypes.ConnectionContract] - // case events.CallMessage, events.RollbackMessage: - // //contract = p.cfg.Contracts[relayTypes.XcallContract] - // default: - // return nil, fmt.Errorf("unknown event type: %s ", message.EventType) - // } - - // msg := &wasmTypes.MsgExecuteContract{ - // Sender: p.Wallet().String(), - // Contract: contract, - // Msg: rawMsg, - // } - - // msgs := []sdkTypes.Msg{msg} - - // res, err := p.sendMessage(ctx, msgs...) - // if err != nil { - // if strings.Contains(err.Error(), errors.ErrWrongSequence.Error()) { - // if mmErr := p.handleSequence(ctx); mmErr != nil { - // return res, fmt.Errorf("failed to handle sequence mismatch error: %v || %v", mmErr, err) - // } - // return p.sendMessage(ctx, msgs...) - // } - // } + return "", nil } -func (p *Provider) sendMessage(ctx context.Context, msgs ...sdkTypes.Msg) (string, error) { +func (p *Provider) sendTx(ctx context.Context, signedMsg *wire.MsgTx) (string, error) { - // return p.prepareAndPushTxToMemPool(ctx, p.wallet.GetAccountNumber(), p.wallet.GetSequence(), msgs...) return "", nil } @@ -587,166 +737,34 @@ func (p *Provider) logTxFailed(err error, txHash string, code uint8) { func (p *Provider) logTxSuccess(height uint64, txHash string) { p.logger.Info("successful transaction", zap.Uint64("block_height", height), - //zap.String("chain_id", p.cfg.ChainID), + zap.String("chain_id", p.cfg.NID), zap.String("tx_hash", txHash), ) } -func (p *Provider) prepareAndPushTxToMemPool(ctx context.Context, acc, seq uint64, msgs ...sdkTypes.Msg) (*sdkTypes.TxResponse, error) { - - return nil, nil -} - func (p *Provider) waitForTxResult(ctx context.Context, mk *relayTypes.MessageKey, txHash string, callback relayTypes.TxResponseFunc) { - //for txWaitRes := range p.subscribeTxResultStream(ctx, txHash, p.cfg.TxConfirmationInterval) { - // if txWaitRes.Error != nil && txWaitRes.Error != context.DeadlineExceeded { - // p.logTxFailed(txWaitRes.Error, txHash, uint8(txWaitRes.TxResult.Code)) - // callback(mk, txWaitRes.TxResult, txWaitRes.Error) - // return - // } - // p.logTxSuccess(uint64(txWaitRes.TxResult.Height), txHash) - // callback(mk, txWaitRes.TxResult, nil) - //} + } func (p *Provider) pollTxResultStream(ctx context.Context, txHash string, maxWaitInterval time.Duration) <-chan *types.TxResult { txResChan := make(chan *types.TxResult) - //startTime := time.Now() - //go func(txChan chan *types.TxResult) { - // defer close(txChan) - // for range time.NewTicker(p.cfg.TxConfirmationInterval).C { - // res, err := p.client.GetTransactionReceipt(ctx, txHash) - // if err == nil { - // txChan <- &types.TxResult{ - // TxResult: &relayTypes.TxResponse{ - // Height: res.TxResponse.Height, - // TxHash: res.TxResponse.TxHash, - // Codespace: res.TxResponse.Codespace, - // Code: relayTypes.ResponseCode(res.TxResponse.Code), - // Data: res.TxResponse.Data, - // }, - // } - // return - // } else if time.Since(startTime) > maxWaitInterval { - // txChan <- &types.TxResult{ - // Error: err, - // } - // return - // } - // } - //}(txResChan) + return txResChan } func (p *Provider) subscribeTxResultStream(ctx context.Context, txHash string, maxWaitInterval time.Duration) <-chan *types.TxResult { txResChan := make(chan *types.TxResult) - //go func(txRes chan *types.TxResult) { - // defer close(txRes) - // - // newCtx, cancel := context.WithTimeout(ctx, maxWaitInterval) - // defer cancel() - // - // query := fmt.Sprintf("tm.event = 'Tx' AND tx.hash = '%s'", txHash) - // resultEventChan, err := p.client.Subscribe(newCtx, "tx-result-waiter", query) - // if err != nil { - // txRes <- &types.TxResult{ - // TxResult: &relayTypes.TxResponse{ - // TxHash: txHash, - // }, - // Error: err, - // } - // return - // } - // defer p.client.Unsubscribe(newCtx, "tx-result-waiter", query) - // - // for { - // select { - // case <-ctx.Done(): - // return - // case e := <-resultEventChan: - // eventDataJSON, err := jsoniter.Marshal(e.Data) - // if err != nil { - // txRes <- &types.TxResult{ - // TxResult: &relayTypes.TxResponse{ - // TxHash: txHash, - // }, Error: err, - // } - // return - // } - // - // txWaitRes := new(types.TxResultWaitResponse) - // if err := jsoniter.Unmarshal(eventDataJSON, txWaitRes); err != nil { - // txRes <- &types.TxResult{ - // TxResult: &relayTypes.TxResponse{ - // TxHash: txHash, - // }, Error: err, - // } - // return - // } - // if uint32(txWaitRes.Result.Code) != types.CodeTypeOK { - // txRes <- &types.TxResult{ - // Error: fmt.Errorf(txWaitRes.Result.Log), - // TxResult: &relayTypes.TxResponse{ - // Height: txWaitRes.Height, - // TxHash: txHash, - // Codespace: txWaitRes.Result.Codespace, - // Code: relayTypes.ResponseCode(txWaitRes.Result.Code), - // Data: string(txWaitRes.Result.Data), - // }, - // } - // return - // } - // - // txRes <- &types.TxResult{ - // TxResult: &relayTypes.TxResponse{ - // Height: txWaitRes.Height, - // TxHash: txHash, - // Codespace: txWaitRes.Result.Codespace, - // Code: relayTypes.ResponseCode(txWaitRes.Result.Code), - // Data: string(txWaitRes.Result.Data), - // }, - // } - // return - // } - // } - //}(txResChan) + return txResChan } func (p *Provider) MessageReceived(ctx context.Context, key *relayTypes.MessageKey) (bool, error) { - //queryMsg := &types.QueryReceiptMsg{ - // GetReceipt: &types.GetReceiptMsg{ - // SrcNetwork: key.Src, - // ConnSn: strconv.FormatUint(key.Sn, 10), - // }, - //} - //rawQueryMsg, err := jsoniter.Marshal(queryMsg) - //if err != nil { - // return false, err - //} - // - //res, err := p.client.QuerySmartContract(ctx, p.cfg.Contracts[relayTypes.ConnectionContract], rawQueryMsg) - //if err != nil { - // p.logger.Error("failed to check if message is received: ", zap.Error(err)) - // return false, err - //} - // - //receiptMsgRes := types.QueryReceiptMsgResponse{} - //return receiptMsgRes.Status, jsoniter.Unmarshal(res.Data, &receiptMsgRes.Status) return false, nil } func (p *Provider) QueryBalance(ctx context.Context, addr string) (*relayTypes.Coin, error) { - //coin, err := p.client.GetBalance(ctx, addr, p.cfg.Denomination) - //if err != nil { - // p.logger.Error("failed to query balance: ", zap.Error(err)) - // return nil, err - //} - //return &relayTypes.Coin{ - // Denom: coin.Denom, - // Amount: coin.Amount.BigInt().Uint64(), - //}, nil + return nil, nil } @@ -832,7 +850,6 @@ func (p *Provider) ExecuteRollback(ctx context.Context, sn *big.Int) error { return nil } -// todo: func (p *Provider) getStartHeight(latestHeight, lastSavedHeight uint64) (uint64, error) { startHeight := lastSavedHeight if p.cfg.StartHeight > 0 && p.cfg.StartHeight < latestHeight { @@ -925,6 +942,10 @@ func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRan } func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, error) { + receiverAddresses := []string{} + runeId := "" + runeAmount := big.NewInt(0) + actionMethod := "" // handle for bitcoin bridge // decode message from OP_RETURN p.logger.Info("parseMessageFromTx", @@ -936,7 +957,8 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } messageInfo := bridgeMessage.Message - if messageInfo.Action == MethodDeposit && messageInfo.To == p.assetManagerAddrIcon { + if messageInfo.Action == MethodDeposit { + actionMethod = MethodDeposit // maybe get this function name from cf file // todo verify transfer amount match in calldata if it // call 3rd to check rune amount @@ -945,14 +967,17 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err amount.SetBytes(messageInfo.Amount) destContract := messageInfo.To - fmt.Println(tokenId) - fmt.Println(amount.String()) - fmt.Println(destContract) + p.logger.Info("tokenId", zap.String("tokenId", tokenId)) + p.logger.Info("amount", zap.String("amount", amount.String())) + p.logger.Info("destContract", zap.String("destContract", destContract)) // call api to verify the data // https://docs.unisat.io/dev/unisat-developer-center/runes/get-utxo-runes-balance verified := false + for i, out := range tx.Tx.TxOut { + receiverAddresses = append(receiverAddresses, p.getAddressesFromTx(out, p.chainParam)...) + // TODO: question: why need to compare multisigAddrScript? if bytes.Compare(out.PkScript, p.multisigAddrScript) != 0 { continue } @@ -980,6 +1005,8 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } if amount.Cmp(runeTokenBal) == 0 && runeOut.RuneId == messageInfo.TokenAddress { + runeId = runeOut.RuneId + runeAmount = runeTokenBal verified = true break } @@ -999,22 +1026,56 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err // todo: handle for rad fi // TODO: call xcallformat and then replace to data + sn := new(big.Int).SetUint64(tx.Height<<32 + tx.TxIndex) from := p.cfg.NID + "/" + p.cfg.Address decodeMessage, _ := codec.RLP.MarshalToBytes(messageInfo) - data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(tx.Height), p.cfg.Protocals) + data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(sn.Uint64()), bridgeMessage.Connectors) - return &relayTypes.Message{ - // TODO: + relayMessage := &relayTypes.Message{ Dst: "0x2.icon", - // Dst: chainIdToName[bridgeMessage.ChainId], - Src: p.NID(), - // Sn: p.LastSerialNumFunc(), - Sn: new(big.Int).SetUint64(tx.Height<<32 + tx.TxIndex), + // TODO: + // Dst: chainIdToName[bridgeMessage.ChainId], + Src: p.NID(), + Sn: sn, Data: data, MessageHeight: tx.Height, EventType: events.EmitMessage, - }, nil + } + + var senderAddress string + // Find sender address to store in db + for _, address := range receiverAddresses { + if address != p.cfg.Address { + senderAddress = address + break + } + } + + // When storing the message + storedData := StoredMessageData{ + OriginalMessage: relayMessage, + TxHash: tx.Tx.TxHash().String(), + OutputIndex: uint32(tx.TxIndex), + Amount: big.NewInt(0).SetBytes(messageInfo.Amount).Uint64(), + RecipientAddress: p.cfg.Address, + SenderAddress: senderAddress, + RuneId: runeId, + RuneAmount: runeAmount.Uint64(), + ActionMethod: actionMethod, + TokenAddress: messageInfo.TokenAddress, + } + + data, err = json.Marshal(storedData) + if err != nil { + return nil, fmt.Errorf("failed to marshal stored data: %v", err) + } + + err = p.db.Put([]byte(sn.String()), data, nil) + if err != nil { + return nil, fmt.Errorf("failed to store message data: %v", err) + } + return relayMessage, nil } func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayTypes.BlockInfo, error) { @@ -1040,34 +1101,6 @@ func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayT return messages, nil } -func (p *Provider) getRawContractMessage(message *relayTypes.Message) (wasmTypes.RawContractMessage, error) { - switch message.EventType { - case events.EmitMessage: - rcvMsg := types.NewExecRecvMsg(message) - return jsoniter.Marshal(rcvMsg) - case events.CallMessage: - execMsg := types.NewExecExecMsg(message) - return jsoniter.Marshal(execMsg) - case events.RevertMessage: - revertMsg := types.NewExecRevertMsg(message) - return jsoniter.Marshal(revertMsg) - case events.SetAdmin: - setAdmin := types.NewExecSetAdmin(message.Dst) - return jsoniter.Marshal(setAdmin) - case events.ClaimFee: - claimFee := types.NewExecClaimFee() - return jsoniter.Marshal(claimFee) - case events.SetFee: - setFee := types.NewExecSetFee(message.Src, message.Sn, message.ReqID) - return jsoniter.Marshal(setFee) - case events.RollbackMessage: - executeRollback := types.NewExecExecuteRollback(message.Sn) - return jsoniter.Marshal(executeRollback) - default: - return nil, fmt.Errorf("unknown event type: %s ", message.EventType) - } -} - func (p *Provider) getNumOfPipelines(diff int) int { if diff <= runtime.NumCPU() { return diff @@ -1110,6 +1143,23 @@ func (p *Provider) runBlockQuery(ctx context.Context, blockInfoChan chan *relayT return toHeight + 1 } +func (p *Provider) getAddressesFromTx(txOut *wire.TxOut, chainParams *chaincfg.Params) []string { + receiverAddresses := []string{} + + scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(txOut.PkScript, chainParams) + if err != nil { + fmt.Printf(" Script: Unable to parse (possibly OP_RETURN)\n") + } else { + fmt.Printf(" Script Class: %s\n", scriptClass) + if len(addresses) > 0 { + fmt.Printf(" Receiver Address: %s\n", addresses[0].String()) + receiverAddresses = append(receiverAddresses, addresses[0].String()) + } + } + + return receiverAddresses +} + // SubscribeMessageEvents subscribes to the message events // Expermental: Allows to subscribe to the message events realtime without fully syncing the chain func (p *Provider) SubscribeMessageEvents(ctx context.Context, blockInfoChan chan *relayTypes.BlockInfo, opts *types.SubscribeOpts, resetFunc func()) error { diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index abbdd132..06b16413 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" "github.com/icon-project/centralized-relay/relayer/events" "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" @@ -39,47 +40,6 @@ func TestDecodeWithdrawToMessage(t *testing.T) { assert.Equal(t, "0:0", result.TokenAddress) } -func TestCreateBitcoinMultisigTx(t *testing.T) { - provider := &Provider{ - logger: nil, - cfg: &Config{Mode: SlaveMode}, - db: nil, - } - - data := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" - // Decode base64 - dataBytes, _ := base64.StdEncoding.DecodeString(data) - - chainParam := &chaincfg.TestNet3Params - _, relayersMultisigInfo := multisig.RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) - relayersMultisigWallet, _ := multisig.BuildMultisigWallet(relayersMultisigInfo) - - _, _, hexRawTx, _, err := provider.CreateBitcoinMultisigTx(dataBytes, 5000, relayersMultisigWallet, chainParam, UNISAT_DEFAULT_TESTNET) - fmt.Println("err: ", err) - fmt.Println("hexRawTx: ", hexRawTx) -} - -func TestBuildAndPartSignBitcoinMessageTx(t *testing.T) { - provider := &Provider{ - logger: nil, - cfg: &Config{Mode: SlaveMode}, - db: nil, - } - - data := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" - // Decode base64 - dataBytes, _ := base64.StdEncoding.DecodeString(data) - - _, _, msgTx, _, err := provider.BuildAndPartSignBitcoinMessageTx(dataBytes, "0x2") - fmt.Println("err: ", err) - - var rawTxBytes bytes.Buffer - msgTx.Serialize(&rawTxBytes) - - hexRawTx := hex.EncodeToString(rawTxBytes.Bytes()) - fmt.Println("hexRawTx: ", hexRawTx) -} - func TestProvider_Route(t *testing.T) { // Setup tempDir, err := os.MkdirTemp("", "bitcoin_provider_test") @@ -142,9 +102,9 @@ func TestDepositBitcoinToIcon(t *testing.T) { inputs := []*multisig.UTXO{ { IsRelayersMultisig: false, - TxHash: "4933e04e3d9320df6e9f046ff83cfc3e9f884d8811df0539af7aaca0218189aa", - OutputIdx: 0, - OutputAmount: 4000000, + TxHash: "4933e04e3d9320df6e9f046ff83cfc3e9f884d8811df0539af7aaca0218189aa", + OutputIdx: 0, + OutputAmount: 4000000, }, } @@ -154,11 +114,11 @@ func TestDepositBitcoinToIcon(t *testing.T) { payload, _ := multisig.CreateBridgePayload( &multisig.XCallMessage{ Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), - Data: []byte(""), + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), }, 1, "cx8b52dfea0aa1e548288102df15ad7159f7266106", @@ -186,13 +146,12 @@ func TestDepositBitcoinToIcon(t *testing.T) { changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -221,9 +180,9 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { inputs := []*multisig.UTXO{ { IsRelayersMultisig: false, - TxHash: "eeb8c9f79ecfe7c084b2af95bf82acebd130185a0d188283d78abb58d85eddff", - OutputIdx: 4, - OutputAmount: 2999000, + TxHash: "eeb8c9f79ecfe7c084b2af95bf82acebd130185a0d188283d78abb58d85eddff", + OutputIdx: 4, + OutputAmount: 2999000, }, } @@ -233,11 +192,11 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { payload, _ := multisig.CreateBridgePayload( &multisig.XCallMessage{ Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), - Data: []byte(""), + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), }, 1, "cx8b52dfea0aa1e548288102df15ad7159f7266106", @@ -265,13 +224,12 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -300,9 +258,9 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { inputs := []*multisig.UTXO{ { IsRelayersMultisig: false, - TxHash: "0416795b227e1a6a64eeb7bf7542d15964d18ac4c4732675d3189cda8d38bed7", - OutputIdx: 3, - OutputAmount: 2998000, + TxHash: "0416795b227e1a6a64eeb7bf7542d15964d18ac4c4732675d3189cda8d38bed7", + OutputIdx: 3, + OutputAmount: 2998000, }, } @@ -312,11 +270,11 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { payload, _ := multisig.CreateBridgePayload( &multisig.XCallMessage{ Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), - Data: []byte(""), + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), }, 1, "cx8b52dfea0aa1e548288102df15ad7159f7266106", @@ -344,13 +302,12 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -379,9 +336,9 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { inputs := []*multisig.UTXO{ { IsRelayersMultisig: false, - TxHash: "dc21f89436d9fbda2cc521ed9b8988c7cbf84cdc67d728b2b2709a5efe7e775a", - OutputIdx: 4, - OutputAmount: 2996000, + TxHash: "dc21f89436d9fbda2cc521ed9b8988c7cbf84cdc67d728b2b2709a5efe7e775a", + OutputIdx: 4, + OutputAmount: 2996000, }, } @@ -391,11 +348,11 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { payload, _ := multisig.CreateBridgePayload( &multisig.XCallMessage{ Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000).Bytes(), - Data: []byte(""), + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000).Bytes(), + Data: []byte(""), }, 1, "cx8b52dfea0aa1e548288102df15ad7159f7266106", @@ -423,13 +380,12 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -458,9 +414,9 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { inputs := []*multisig.UTXO{ { IsRelayersMultisig: false, - TxHash: "1e29fa62942f92dd4cf688e219641b54229fbc2ec2dc74cc9c1c7f247c7172b2", - OutputIdx: 4, - OutputAmount: 2985000, + TxHash: "1e29fa62942f92dd4cf688e219641b54229fbc2ec2dc74cc9c1c7f247c7172b2", + OutputIdx: 4, + OutputAmount: 2985000, }, } @@ -470,11 +426,11 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { payload, _ := multisig.CreateBridgePayload( &multisig.XCallMessage{ Action: "Withdraw", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000).Bytes(), - Data: []byte(""), + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000).Bytes(), + Data: []byte(""), }, 1, "cx8b52dfea0aa1e548288102df15ad7159f7266106", @@ -502,13 +458,12 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -529,4 +484,66 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { fmt.Println("err sign: ", err) // TODO: test the signedMsgTx -} \ No newline at end of file +} + +// ... existing code ... + +func TestDecodeBitcoinTransaction(t *testing.T) { + // The raw transaction hex string + rawTxHex := "02000000000101b272717c247f1c9ccc74dcc22ebc9f22541b6419e288f64cdd922f9462fa291e040000000001000000050000000000000000506a5e4c4cf88588576974686472617783303a31b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a7835736876760000000000000000506a5e4c4c377375b33078322e69636f6e2f6878343532653233356639663166643130303662313934316564316164313965663531643131393266368203e88001738b52dfea0aa1e548288102df15ad7100000000000000001d6a5e1a59f726610673577f5e756abd89cbcba38a58508b60a12754d2f510270000000000002251204bfab0ad4d88b3fd71ae844e1b0eeacd4ac03638a4b1c6c7a754061bcf61cd2830612d0000000000225120408c73bc891f8076a047682eea3e13c72a9adf6ea62713bdf1a557c1608591a903405a713aad72e1a2717cab16446e84a0de1c9f908a100c5903086a97910adc1327db65d21c8533c4fe087027195db4ebe7d8595624382e39b7aba829e3b29a29dc2551b275207303e7756826cf3fabc2f9c06978c542039effbb7493627cad22236e3ff10ee4ac41c18a23958fc9bf526c81a09bca529d685adc6900a04e2f520a26c63aa0b61a770f27c71b203eebab28e2e37b992abd8e6e5f9d887bdc2d5ab0efde76df79d3520400000000" + + // Decode the raw transaction + txBytes, err := hex.DecodeString(rawTxHex) + assert.NoError(t, err) + + var tx wire.MsgTx + err = tx.Deserialize(bytes.NewReader(txBytes)) + assert.NoError(t, err) + + // Extract sender information (from the input) + assert.Equal(t, 1, len(tx.TxIn), "Expected 1 input") + prevOutHash := tx.TxIn[0].PreviousOutPoint.Hash.String() + prevOutIndex := tx.TxIn[0].PreviousOutPoint.Index + fmt.Printf("Sender (Input): %s:%d\n", prevOutHash, prevOutIndex) + + // Extract receiver information (from the outputs) + assert.Equal(t, 5, len(tx.TxOut), "Expected 5 outputs") + + for i, out := range tx.TxOut { + fmt.Printf("Output %d:\n", i) + fmt.Printf(" Amount: %d satoshis\n", out.Value) + + // Attempt to parse the output script + scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(out.PkScript, &chaincfg.TestNet3Params) + if err != nil { + fmt.Printf(" Script: Unable to parse (possibly OP_RETURN)\n") + } else { + fmt.Printf(" Script Class: %s\n", scriptClass) + if len(addresses) > 0 { + fmt.Printf(" Receiver Address: %s\n", addresses[0].String()) + } + } + + // If it's an OP_RETURN output, print the data + if scriptClass == txscript.NullDataTy { + fmt.Printf(" OP_RETURN Data: %x\n", out.PkScript[2:]) + } + + fmt.Println() + } + + // Add assertions for specific outputs + assert.Equal(t, txscript.NullDataTy, txscript.GetScriptClass(tx.TxOut[0].PkScript)) + assert.Equal(t, txscript.NullDataTy, txscript.GetScriptClass(tx.TxOut[1].PkScript)) + assert.Equal(t, txscript.NullDataTy, txscript.GetScriptClass(tx.TxOut[2].PkScript)) + + _, addresses, _, err := txscript.ExtractPkScriptAddrs(tx.TxOut[3].PkScript, &chaincfg.TestNet3Params) + assert.NoError(t, err) + assert.Equal(t, 1, len(addresses)) + assert.Equal(t, "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", addresses[0].String()) + + _, addresses, _, err = txscript.ExtractPkScriptAddrs(tx.TxOut[4].PkScript, &chaincfg.TestNet3Params) + assert.NoError(t, err) + assert.Equal(t, 1, len(addresses)) + assert.Equal(t, "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", addresses[0].String()) +} diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index 3c51c842..ae8ace2e 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -3,13 +3,11 @@ package bitcoin import ( "encoding/json" "io" - "log" "math/big" "net/http" - "os" - "strings" relayTypes "github.com/icon-project/centralized-relay/relayer/types" + "go.uber.org/zap" ) func startSlave(c *Config, p *Provider) { @@ -22,24 +20,28 @@ func startSlave(c *Config, p *Provider) { Handler: nil, } - log.Printf("Slave starting on port %s", port) - log.Fatal(server.ListenAndServe()) + p.logger.Info("Slave starting on port", zap.String("port", port)) + p.logger.Fatal("Failed to start slave", zap.Error(server.ListenAndServe())) } func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { + p.logger.Info("Slave starting on port", zap.String("port", p.cfg.Port)) if r.Method == http.MethodPost { apiKey := r.Header.Get("x-api-key") if apiKey == "" { + p.logger.Error("Missing API Key") http.Error(w, "Missing API Key", http.StatusUnauthorized) return } - apiKeyHeader := os.Getenv("API_KEY") + apiKeyHeader := p.cfg.ApiKey if apiKey != apiKeyHeader { + p.logger.Error("Invalid API Key", zap.String("apiKey", apiKey)) http.Error(w, "Invalid API Key", http.StatusForbidden) return } body, err := io.ReadAll(r.Body) if err != nil { + p.logger.Error("Error reading request body", zap.Error(err)) http.Error(w, "Error reading request body", http.StatusInternalServerError) return } @@ -47,6 +49,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { var rsi slaveRequestParams err = json.Unmarshal(body, &rsi) if err != nil { + p.logger.Error("Error decoding request body", zap.Error(err)) http.Error(w, "Error decoding request body", http.StatusInternalServerError) return } @@ -55,6 +58,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { returnData, _ := json.Marshal(sigs) w.Write(returnData) } else { + p.logger.Error("Method not allowed", zap.String("method", r.Method)) http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } } @@ -72,7 +76,7 @@ func buildAndSignTxFromDbMessage(sn *big.Int, p *Provider) ([][]byte, error) { return nil, err } - _, _, _, relayerSigns, err := p.BuildAndPartSignBitcoinMessageTx(message.Data, strings.Split(message.Dst, ".")[0]) + _, _, _, relayerSigns, err := p.HandleBitcoinMessageTx(message) if err != nil { return nil, err } diff --git a/relayer/chains/icon/query.go b/relayer/chains/icon/query.go index 77a010a1..b1c8466d 100644 --- a/relayer/chains/icon/query.go +++ b/relayer/chains/icon/query.go @@ -7,7 +7,6 @@ import ( "strings" "github.com/icon-project/centralized-relay/relayer/chains/icon/types" - "github.com/icon-project/centralized-relay/relayer/transmission" providerTypes "github.com/icon-project/centralized-relay/relayer/types" "go.uber.org/zap" ) @@ -87,10 +86,6 @@ func (p *Provider) GenerateMessages(ctx context.Context, key *providerTypes.Mess if err != nil { return nil, fmt.Errorf("GenerateMessage:GetTransactionResult %v", err) } - // TODO: Bitcoin - if err == nil { - transmission.CallBitcoinRelay(string(txResult.BlockHeight)) - } for _, el := range txResult.EventLogs { var ( dst string diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index e61bb2cd..c4c9c060 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -48,7 +48,7 @@ func CreateMultisigTx( totalInputAmount += in.OutputAmount var pkScript []byte - if (in.IsRelayersMultisig) { + if in.IsRelayersMultisig { pkScript = relayersMultisigWallet.PKScript } else { pkScript = userMultisigWallet.PKScript @@ -147,7 +147,7 @@ func PartSignOnRawExternalTx( sigs := [][]byte{} for i := range msgTx.TxIn { - if (inputs[i].IsRelayersMultisig) { + if inputs[i].IsRelayersMultisig { sig, err := txscript.RawTxInTapscriptSignature( msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.RelayersPKScript, tapSigParams.RelayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { @@ -155,7 +155,7 @@ func PartSignOnRawExternalTx( } sigs = append(sigs, sig) - } else if (isMasterRelayer) { + } else if isMasterRelayer { sig, err := txscript.RawTxInTapscriptSignature( msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.UserPKScript, tapSigParams.UserTapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { @@ -212,13 +212,13 @@ func CombineMultisigSigs( for idxInput, v := range transposedSigs { reverseV := [][]byte{} for i := len(v) - 1; i >= 0; i-- { - if (len(v[i]) != 0) { + if len(v[i]) != 0 { reverseV = append(reverseV, v[i]) } } witness := append([][]byte{}, reverseV...) - if (inputs[idxInput].IsRelayersMultisig) { + if inputs[idxInput].IsRelayersMultisig { witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes) } else { witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlockBytes) @@ -267,36 +267,36 @@ func GetRelayerReceivedUTXO( var sequenceNumberUTXO *UTXO bitcoinUTXOs := []*UTXO{} runeUTXOs := []*RuneUTXO{} - Exit: - for idx, output := range msgTx.TxOut { - // Skip non-relayer received UTXO - if !bytes.Equal(output.PkScript, relayerScriptAddress) { - continue - } - currentUTXO := &UTXO{ - IsRelayersMultisig: true, - TxHash: msgTx.TxHash().String(), - OutputIdx: uint32(idx), - OutputAmount: uint64(output.Value), - } - // check if is sequenceNumber UTXO - if idx == sequenceNumberIdx { - sequenceNumberUTXO = currentUTXO - continue - } - // check if is rune UTXO - for edictIdx, edictOutput := range edictOutputs { - if idx == int(edictOutput) { - runeUTXOs = append(runeUTXOs, &RuneUTXO{ - edict: artifact.Runestone.Edicts[edictIdx], - edictUTXO: currentUTXO, - }) - continue Exit - } +Exit: + for idx, output := range msgTx.TxOut { + // Skip non-relayer received UTXO + if !bytes.Equal(output.PkScript, relayerScriptAddress) { + continue + } + currentUTXO := &UTXO{ + IsRelayersMultisig: true, + TxHash: msgTx.TxHash().String(), + OutputIdx: uint32(idx), + OutputAmount: uint64(output.Value), + } + // check if is sequenceNumber UTXO + if idx == sequenceNumberIdx { + sequenceNumberUTXO = currentUTXO + continue + } + // check if is rune UTXO + for edictIdx, edictOutput := range edictOutputs { + if idx == int(edictOutput) { + runeUTXOs = append(runeUTXOs, &RuneUTXO{ + edict: artifact.Runestone.Edicts[edictIdx], + edictUTXO: currentUTXO, + }) + continue Exit } - // or else it will be bitcoin UTXO - bitcoinUTXOs = append(bitcoinUTXOs, currentUTXO) } + // or else it will be bitcoin UTXO + bitcoinUTXOs = append(bitcoinUTXOs, currentUTXO) + } return sequenceNumberUTXO, bitcoinUTXOs, runeUTXOs, nil } diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 29873085..813cc214 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -2,6 +2,7 @@ package multisig import ( "crypto/sha256" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil/hdkeychain" @@ -45,12 +46,20 @@ func randomKeys(n int, chainParam *chaincfg.Params, seeds []int) ([]string, [][] func RandomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, recoveryKeyIdx int, recoveryLockTime uint64) ([]string, *MultisigInfo) { privKeys, pubKeys, EcPubKeys := randomKeys(n, chainParam, seeds) vaultInfo := MultisigInfo{ - PubKeys: pubKeys, - EcPubKeys: EcPubKeys, - NumberRequiredSigs: k, - RecoveryPubKey: pubKeys[recoveryKeyIdx], - RecoveryLockTime: recoveryLockTime, + PubKeys: pubKeys, + EcPubKeys: EcPubKeys, + NumberRequiredSigs: k, + RecoveryPubKey: pubKeys[recoveryKeyIdx], + RecoveryLockTime: recoveryLockTime, } return privKeys, &vaultInfo -} \ No newline at end of file +} + +func SumInputsSat(inputs []*UTXO) uint64 { + total := uint64(0) + for _, in := range inputs { + total += in.OutputAmount + } + return total +} From 9bfdf0670f712efb09d2c20e103825eed68168e1 Mon Sep 17 00:00:00 2001 From: Shall Date: Wed, 25 Sep 2024 09:27:04 +0700 Subject: [PATCH 068/113] feat: update condition to check transaction send to multisign wallet --- relayer/chains/bitcoin/provider.go | 106 +++++++++++++++++------------ 1 file changed, 63 insertions(+), 43 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index cf282ce1..44279011 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -9,6 +9,7 @@ import ( "log" "math/big" "runtime" + "slices" "sort" "strconv" "strings" @@ -36,7 +37,7 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) var ( - BTCToken = "0:0" + BTCToken = "0:1" MethodDeposit = "Deposit" MethodWithdrawTo = "WithdrawTo" MasterMode = "master" @@ -78,38 +79,38 @@ type StoredMessageData struct { } type Provider struct { - logger *zap.Logger - cfg *Config - client IClient - LastSavedHeightFunc func() uint64 - LastSerialNumFunc func() *big.Int - multisigAddrScript []byte - assetManagerAddrIcon string - bearToken string - httpServer chan struct{} - db *leveldb.DB - chainParam *chaincfg.Params + logger *zap.Logger + cfg *Config + client IClient + LastSavedHeightFunc func() uint64 + LastSerialNumFunc func() *big.Int + multisigAddrScript []byte + bearToken string + httpServer chan struct{} + db *leveldb.DB + chainParam *chaincfg.Params } type Config struct { provider.CommonConfig `json:",inline" yaml:",inline"` - OpCode int `json:"op-code" yaml:"op-code"` - UniSatURL string `json:"unisat-url" yaml:"unisat-url"` - UniSatKey string `json:"unisat-key" yaml:"unisat-key"` - MempoolURL string `json:"mempool-url" yaml:"mempool-url"` - Type string `json:"type" yaml:"type"` - User string `json:"rpc-user" yaml:"rpc-user"` - Password string `json:"rpc-password" yaml:"rpc-password"` - Mode string `json:"mode" yaml:"mode"` - SlaveServer1 string `json:"slave-server-1" yaml:"slave-server-1"` - SlaveServer2 string `json:"slave-server-2" yaml:"slave-server-2"` - Port string `json:"port" yaml:"port"` - ApiKey string `json:"api-key" yaml:"api-key"` - MasterPubKey string `json:"masterPubKey" yaml:"masterPubKey"` - Slave1PubKey string `json:"slave1PubKey" yaml:"slave1PubKey"` - Slave2PubKey string `json:"slave2PubKey" yaml:"slave2PubKey"` - RelayerPrivKey string `json:"relayerPrivKey" yaml:"relayerPrivKey"` - RecoveryLockTime int `json:"recoveryLockTime" yaml:"recoveryLockTime"` + OpCode int `json:"op-code" yaml:"op-code"` + UniSatURL string `json:"unisat-url" yaml:"unisat-url"` + UniSatKey string `json:"unisat-key" yaml:"unisat-key"` + MempoolURL string `json:"mempool-url" yaml:"mempool-url"` + Type string `json:"type" yaml:"type"` + User string `json:"rpc-user" yaml:"rpc-user"` + Password string `json:"rpc-password" yaml:"rpc-password"` + Mode string `json:"mode" yaml:"mode"` + SlaveServer1 string `json:"slave-server-1" yaml:"slave-server-1"` + SlaveServer2 string `json:"slave-server-2" yaml:"slave-server-2"` + Port string `json:"port" yaml:"port"` + ApiKey string `json:"api-key" yaml:"api-key"` + MasterPubKey string `json:"masterPubKey" yaml:"masterPubKey"` + Slave1PubKey string `json:"slave1PubKey" yaml:"slave1PubKey"` + Slave2PubKey string `json:"slave2PubKey" yaml:"slave2PubKey"` + RelayerPrivKey string `json:"relayerPrivKey" yaml:"relayerPrivKey"` + RecoveryLockTime int `json:"recoveryLockTime" yaml:"recoveryLockTime"` + Connections []string `json:"connections" yaml:"connections"` } // NewProvider returns new Icon provider @@ -142,14 +143,20 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri c.HomeDir = homepath c.HomeDir = homepath + msPubkey, err := client.DecodeAddress(c.Address) + if err != nil { + return nil, err + } + p := &Provider{ - logger: log.With(zap.Stringp("nid", &c.NID), zap.Stringp("name", &c.ChainName)), - cfg: c, - client: client, - LastSerialNumFunc: func() *big.Int { return big.NewInt(0) }, - httpServer: make(chan struct{}), - db: db, // Add the database to the Provider - chainParam: chainParam, + logger: log.With(zap.Stringp("nid", &c.NID), zap.Stringp("name", &c.ChainName)), + cfg: c, + client: client, + LastSerialNumFunc: func() *big.Int { return big.NewInt(0) }, + httpServer: make(chan struct{}), + db: db, // Add the database to the Provider + chainParam: chainParam, + multisigAddrScript: msPubkey, } // Run an http server to help btc interact each others go func() { @@ -223,8 +230,8 @@ func (p *Provider) Init(ctx context.Context, homePath string, kms kms.KMS) error } // Wallet returns the wallet of the provider -func (p *Provider) Wallet() error { - return nil +func (p *Provider) Wallet() (*multisig.MultisigWallet, error) { + return p.buildMultisigWallet() } func (p *Provider) Type() string { @@ -232,7 +239,7 @@ func (p *Provider) Type() string { } func (p *Provider) Config() provider.Config { - return nil + return p.cfg } func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockInfoChan chan *relayTypes.BlockInfo) error { @@ -940,6 +947,13 @@ func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRan return p.getMessagesFromTxList(messages) } +func (p *Provider) extractOutputReceiver(tx *wire.MsgTx) []string { + receiverAddresses := []string{} + for _, out := range tx.TxOut { + receiverAddresses = append(receiverAddresses, p.getAddressesFromTx(out, p.chainParam)...) + } + return receiverAddresses +} func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, error) { receiverAddresses := []string{} @@ -957,7 +971,15 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } messageInfo := bridgeMessage.Message - if messageInfo.Action == MethodDeposit { + isValidConnector := false + for _, connector := range bridgeMessage.Connectors { + if slices.Contains(p.cfg.Connections, connector) { + isValidConnector = true + break + } + } + + if messageInfo.Action == MethodDeposit && isValidConnector { actionMethod = MethodDeposit // maybe get this function name from cf file // todo verify transfer amount match in calldata if it @@ -974,10 +996,8 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err // call api to verify the data // https://docs.unisat.io/dev/unisat-developer-center/runes/get-utxo-runes-balance verified := false - + receiverAddresses = p.extractOutputReceiver(tx.Tx) for i, out := range tx.Tx.TxOut { - receiverAddresses = append(receiverAddresses, p.getAddressesFromTx(out, p.chainParam)...) - // TODO: question: why need to compare multisigAddrScript? if bytes.Compare(out.PkScript, p.multisigAddrScript) != 0 { continue } From a05ed4edf45d348dee46bf6c43df4e1cfb614d02 Mon Sep 17 00:00:00 2001 From: homelander Date: Wed, 25 Sep 2024 12:25:39 +0700 Subject: [PATCH 069/113] added mess type --- relayer/chains/bitcoin/helper.go | 8 ++++---- relayer/chains/bitcoin/provider.go | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index 25289cbb..ea3f41f3 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -108,9 +108,9 @@ func ToXCallMessage(data interface{}, from, to string, sn uint, protocols []stri } //from := "0x3.BTC/bc1qvqkshkdj67uwvlwschyq8wja6df4juhewkg5fg" - + // todo: s, extract message type from OP_RETURN DATA // encode to xcall format - res, err = XcallFormat(provideLiquidity, from, to, sn, protocols) + res, err = XcallFormat(provideLiquidity, from, to, sn, protocols, uint8(CALL_MESSAGE_TYPE)) if err != nil { return nil, err } @@ -123,13 +123,13 @@ func ToXCallMessage(data interface{}, from, to string, sn uint, protocols []stri return res, nil } -func XcallFormat(callData []byte, from, to string, sn uint, protocols []string) ([]byte, error) { +func XcallFormat(callData []byte, from, to string, sn uint, protocols []string, messType uint8) ([]byte, error) { // csV2 := CSMessageRequestV2{ From: from, To: to, Sn: big.NewInt(int64(sn)).Bytes(), - MessageType: uint8(CALL_MESSAGE_TYPE), + MessageType: messType, Data: callData, Protocols: protocols, } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 44279011..d14a39d3 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -1050,7 +1050,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err from := p.cfg.NID + "/" + p.cfg.Address decodeMessage, _ := codec.RLP.MarshalToBytes(messageInfo) - data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(sn.Uint64()), bridgeMessage.Connectors) + data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(sn.Uint64()), bridgeMessage.Connectors, uint8(CALL_MESSAGE_ROLLBACK_TYPE)) relayMessage := &relayTypes.Message{ Dst: "0x2.icon", From c5e4d2a57384a1511e9dff9586dd99b2d24dc78b Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Wed, 25 Sep 2024 17:30:12 +0700 Subject: [PATCH 070/113] update messageType to xCall OP_RETURN --- utils/multisig/multisig_test.go | 2 ++ utils/multisig/op_message.go | 13 +++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 188cc066..1979aa6c 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -401,6 +401,7 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { // Add Bridge Message payload, _ := CreateBridgePayload( &XCallMessage{ + MessageType: 123, Action: "Deposit", TokenAddress: "0:0", // bitcoin address To: "0x2.icon/hx39eddef484f6bb08072c59cc0a206e6713fc6d7d", //(receiver) @@ -461,6 +462,7 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { decodedMessage, err := ReadBridgeMessage(signedMsgTx) fmt.Println("err decode: ", err) fmt.Println("-----------decodedMessage---------- ") + fmt.Println("Message.MessageType: ", decodedMessage.Message.MessageType) fmt.Println("Message.Action: ", decodedMessage.Message.Action) fmt.Println("Message.TokenAddress: ", decodedMessage.Message.TokenAddress) fmt.Println("Message.From: ", decodedMessage.Message.From) diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index dbb29f4e..3aa9b391 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -25,12 +25,13 @@ const ( ) type XCallMessage struct { - Action string - TokenAddress string - From string - To string - Amount []byte - Data []byte + MessageType uint8 + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte } type RadFiProvideLiquidityDetail struct { From ccdcc320a76c8ec4d7850a7682eaac0420afa3ef Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 27 Sep 2024 20:08:40 +0700 Subject: [PATCH 071/113] update to fix rune transfer code and add test --- relayer/chains/bitcoin/provider.go | 90 +++++++------ relayer/chains/bitcoin/provider_route_test.go | 120 ++++++++++++++++++ 2 files changed, 163 insertions(+), 47 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index d14a39d3..fa4a8a56 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -19,6 +19,8 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/bxelab/runestone" + "lukechampine.com/uint128" "path/filepath" @@ -43,7 +45,7 @@ var ( MasterMode = "master" SlaveMode = "slave" BtcDB = "btc.db" - MinSatsRequired = 1000 + MinSatsRequired uint64 = 1000 WitnessSize = 385 ) @@ -337,13 +339,13 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired uint64 return outputs, nil } -func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, uint64, error) { +func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired resp, err := GetRuneUtxo(ctx, server, address, runeId) if err != nil { - return nil, 0, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) + return nil, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) } utxos := resp.Data.Utxo @@ -352,26 +354,26 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout return utxos[i].Satoshi.Cmp(utxos[j].Satoshi) == 1 }) - outputs := []*multisig.UTXO{} + inputs := []*multisig.UTXO{} var totalAmount uint64 for _, utxo := range utxos { if totalAmount >= amountRequired { break } - outputs = append(outputs, &multisig.UTXO{ + inputs = append(inputs, &multisig.UTXO{ IsRelayersMultisig: true, TxHash: utxo.TxId, OutputIdx: uint32(utxo.Vout), OutputAmount: utxo.Satoshi.Uint64(), }) if len(utxo.Runes) != 1 { - return nil, 0, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) + return nil, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) } runeAmount, _ := strconv.ParseUint(utxo.Runes[0].Amount, 10, 64) totalAmount += runeAmount } - return outputs, totalAmount - amountRequired, nil + return inputs, nil } func (p *Provider) CreateBitcoinMultisigTx( @@ -382,12 +384,16 @@ func (p *Provider) CreateBitcoinMultisigTx( ) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { // ----- BUILD OUTPUTS ----- outputs := []*multisig.OutputTx{} - var bitcoinAmountRequired uint64 = uint64(MinSatsRequired) + var bitcoinAmountRequired uint64 var runeAmountRequired uint64 - var runeRequired multisig.Rune - // add withdraw output + rlMsAddress, err := multisig.AddressOnChain(p.chainParam, msWallet) + if err != nil { + return nil, nil, "", nil, err + } + msAddressStr := rlMsAddress.String() + // add withdraw output amount := new(big.Int).SetBytes(decodedData.Amount).Uint64() if decodedData.Action == MethodWithdrawTo || decodedData.Action == MethodDeposit { if decodedData.TokenAddress == BTCToken { @@ -400,37 +406,40 @@ func (p *Provider) CreateBitcoinMultisigTx( bitcoinAmountRequired = amount } else { // transfer rune - runeAddress := strings.Split(decodedData.TokenAddress, ":") - blockNumber, _ := strconv.ParseUint(runeAddress[0], 10, 64) - txIndex, _ := strconv.ParseUint(runeAddress[0], 10, 32) - runeRequired = multisig.Rune{ - BlockNumber: blockNumber, - TxIndex: uint32(txIndex), + runeRequired, _ := runestone.RuneIdFromString(decodedData.TokenAddress) + changeOutputId := uint32(len(outputs)+2) + runeOutput := &runestone.Runestone{ + Edicts: []runestone.Edict{ + { + ID: *runeRequired, + Amount: uint128.FromBytes(decodedData.Amount), + Output: uint32(len(outputs)+1), + }, + }, + Pointer: &changeOutputId, } - runeScript, _ := multisig.CreateRuneTransferScript( - runeRequired, - new(big.Int).SetUint64(amount), - uint64(len(outputs)+2), - ) + runeScript, _ := runeOutput.Encipher() + // add runestone OP_RETURN outputs = append(outputs, &multisig.OutputTx{ OpReturnScript: runeScript, }) + // add receiver output outputs = append(outputs, &multisig.OutputTx{ ReceiverAddress: decodedData.To, - Amount: uint64(MinSatsRequired), + Amount: MinSatsRequired, + }) + // add change output + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: msAddressStr, + Amount: MinSatsRequired, }) runeAmountRequired = amount + bitcoinAmountRequired = MinSatsRequired*2 } } // ----- BUILD INPUTS ----- - rlMsAddress, err := multisig.AddressOnChain(p.chainParam, msWallet) - if err != nil { - return nil, nil, "", nil, err - } - msAddressStr := rlMsAddress.String() - - inputs, estFee, err := p.computeTx(feeRate, bitcoinAmountRequired, runeAmountRequired, decodedData.TokenAddress, msAddressStr, runeRequired, outputs, msWallet) + inputs, estFee, err := p.computeTx(feeRate, bitcoinAmountRequired, runeAmountRequired, decodedData.TokenAddress, msAddressStr, outputs, msWallet) if err != nil { return nil, nil, "", nil, err } @@ -456,12 +465,12 @@ func (p *Provider) calculateTxSize(inputs []*multisig.UTXO, outputs []*multisig. return txSize, nil } -func (p *Provider) computeTx(feeRate, satsToSend, runeToSend uint64, runeId, changeAddress string, runeRequired multisig.Rune, outputs []*multisig.OutputTx, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, uint64, error) { +func (p *Provider) computeTx(feeRate, satsToSend, runeToSend uint64, runeId, changeAddress string, outputs []*multisig.OutputTx, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, uint64, error) { outputsCopy := make([]*multisig.OutputTx, len(outputs)) copy(outputsCopy, outputs) - inputs, err := p.selectUnspentOutputs(satsToSend, runeToSend, runeId, runeRequired, outputsCopy, changeAddress) + inputs, err := p.selectUnspentUTXOs(satsToSend, runeToSend, runeId, outputsCopy, changeAddress) sumSelectedOutputs := multisig.SumInputsSat(inputs) if err != nil { return nil, 0, err @@ -485,7 +494,7 @@ func (p *Provider) computeTx(feeRate, satsToSend, runeToSend uint64, runeId, cha newSatsToSend := satsToSend + estFee var err error - selectedUnspentOutputs, err := p.selectUnspentOutputs(newSatsToSend, runeToSend, runeId, runeRequired, iterationOutputs, changeAddress) + selectedUnspentOutputs, err := p.selectUnspentUTXOs(newSatsToSend, runeToSend, runeId, iterationOutputs, changeAddress) if err != nil { return nil, 0, err } @@ -513,29 +522,16 @@ func (p *Provider) computeTx(feeRate, satsToSend, runeToSend uint64, runeId, cha return inputs, estFee, nil } -func (p *Provider) selectUnspentOutputs(satToSend uint64, runeToSend uint64, runeId string, runeRequired multisig.Rune, outputs []*multisig.OutputTx, changeAddress string) ([]*multisig.UTXO, error) { +func (p *Provider) selectUnspentUTXOs(satToSend uint64, runeToSend uint64, runeId string, outputs []*multisig.OutputTx, changeAddress string) ([]*multisig.UTXO, error) { // add tx fee the the required bitcoin amount inputs := []*multisig.UTXO{} if runeToSend != 0 { // query rune UTXOs from unisat - runeInputs, runeChangeAmount, err := GetRuneUTXOs(p.cfg.UniSatURL, changeAddress, runeId, runeToSend, 3) + runeInputs, err := GetRuneUTXOs(p.cfg.UniSatURL, changeAddress, runeId, runeToSend, 3) if err != nil { return nil, err } inputs = append(inputs, runeInputs...) - // add rune change to outputs - runeScript, _ := multisig.CreateRuneTransferScript( - runeRequired, - new(big.Int).SetUint64(runeChangeAmount), - uint64(len(outputs)+2), - ) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: runeScript, - }) - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: changeAddress, - Amount: uint64(MinSatsRequired), - }) } // TODO: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index 06b16413..82e55d77 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -15,12 +15,14 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/bxelab/runestone" "github.com/icon-project/centralized-relay/relayer/events" "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" "github.com/stretchr/testify/assert" "github.com/syndtr/goleveldb/leveldb" "go.uber.org/zap" + "lukechampine.com/uint128" ) func TestDecodeWithdrawToMessage(t *testing.T) { @@ -547,3 +549,121 @@ func TestDecodeBitcoinTransaction(t *testing.T) { assert.Equal(t, 1, len(addresses)) assert.Equal(t, "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", addresses[0].String()) } + +func TestDepositRuneToIcon(t *testing.T) { + chainParam := &chaincfg.TestNet3Params + + inputs := []*multisig.UTXO{ + // user rune UTXOs to spend + { + IsRelayersMultisig: false, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 0, + OutputAmount: 1000, + }, + // user bitcoin UTXOs to pay tx fee + { + IsRelayersMultisig: false, + TxHash: "4933e04e3d9320df6e9f046ff83cfc3e9f884d8811df0539af7aaca0218189aa", + OutputIdx: 0, + OutputAmount: 4000000, + }, + } + + outputs := []*multisig.OutputTx{} + + // Add Bridge Message + payload, _ := multisig.CreateBridgePayload( + &multisig.XCallMessage{ + Action: "Deposit", + TokenAddress: "840000:3", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), + }, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + ) + scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + + // Add transfering rune to relayer multisig + runeId, _ := runestone.NewRuneId(840000, 3) + changeReceiver := uint32(len(outputs)+2) + runeStone := &runestone.Runestone{ + Edicts: []runestone.Edict{ + { + ID: *runeId, + Amount: uint128.From64(1000000000), + Output: uint32(len(outputs)+1), + }, + }, + Pointer: &changeReceiver, + } + runeScript, _ := runeStone.Encipher() + // Runestone OP_RETURN + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: runeScript, + }) + // Rune UTXO send to relayer multisig + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", + Amount: 1000, + }) + // Rune change UTXO send back to user + changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: changeReceiverAddress, + Amount: 1000, + }) + + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + + tapSigParams := multisig.TapSigParams{ + TxSigHashes: txSigHashes, + RelayersPKScript: []byte{}, + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], + } + + totalSigs := [][][]byte{} + + // USER SIGN TX + userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) + totalSigs = append(totalSigs, userSigs) + // COMBINE SIGNS + signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decipher runestone + r := &runestone.Runestone{} + artifact, err := r.Decipher(signedMsgTx) + if err != nil { + fmt.Println(err) + return + } + a, _ := json.Marshal(artifact) + fmt.Printf("Artifact: %s\n", string(a)) + // TODO: test the signedMsgTx +} \ No newline at end of file From e4f6614aa48c0d980fefa1008ed60569aa104ed2 Mon Sep 17 00:00:00 2001 From: Shall Date: Sun, 29 Sep 2024 20:33:10 +0700 Subject: [PATCH 072/113] feat: update logic to handle revert message --- relayer/chains/bitcoin/provider.go | 157 +++++--- relayer/chains/bitcoin/provider_route_test.go | 123 ++++++- relayer/chains/bitcoin/slave.go | 7 +- relayer/chains/bitcoin/types.go | 6 +- relayer/chains/icon/client.go | 3 +- relayer/chains/icon/route.go | 25 +- utils/multisig/multisig_test.go | 337 +++++++++--------- utils/multisig/op_message.go | 316 ++++++++-------- 8 files changed, 562 insertions(+), 412 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index fa4a8a56..37c0eeeb 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -39,14 +39,14 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) var ( - BTCToken = "0:1" - MethodDeposit = "Deposit" - MethodWithdrawTo = "WithdrawTo" - MasterMode = "master" - SlaveMode = "slave" - BtcDB = "btc.db" - MinSatsRequired uint64 = 1000 - WitnessSize = 385 + BTCToken = "0:1" + MethodDeposit = "Deposit" + MethodWithdrawTo = "WithdrawTo" + MasterMode = "master" + SlaveMode = "slave" + BtcDB = "btc.db" + MinSatsRequired uint64 = 1000 + WitnessSize = 385 ) var chainIdToName = map[uint8]string{ @@ -64,8 +64,14 @@ type MessageDecoded struct { Amount []byte } +type CSMessageResult struct { + Sn *big.Int + Code uint8 + Message []byte +} + type slaveRequestParams struct { - MsgSn *big.Int `json:"msgSn"` + MsgSn string `json:"msgSn"` } type StoredMessageData struct { OriginalMessage *relayTypes.Message @@ -377,13 +383,15 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout } func (p *Provider) CreateBitcoinMultisigTx( - messageData []byte, + outputData []*multisig.OutputTx, + feeRate uint64, decodedData *MessageDecoded, msWallet *multisig.MultisigWallet, ) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { // ----- BUILD OUTPUTS ----- outputs := []*multisig.OutputTx{} + outputs = append(outputs, outputData...) var bitcoinAmountRequired uint64 var runeAmountRequired uint64 @@ -394,7 +402,7 @@ func (p *Provider) CreateBitcoinMultisigTx( msAddressStr := rlMsAddress.String() // add withdraw output - amount := new(big.Int).SetBytes(decodedData.Amount).Uint64() + amount, _ := strconv.ParseUint(string(decodedData.Amount), 10, 64) if decodedData.Action == MethodWithdrawTo || decodedData.Action == MethodDeposit { if decodedData.TokenAddress == BTCToken { // transfer btc @@ -407,13 +415,13 @@ func (p *Provider) CreateBitcoinMultisigTx( } else { // transfer rune runeRequired, _ := runestone.RuneIdFromString(decodedData.TokenAddress) - changeOutputId := uint32(len(outputs)+2) + changeOutputId := uint32(len(outputs) + 2) runeOutput := &runestone.Runestone{ Edicts: []runestone.Edict{ { - ID: *runeRequired, + ID: *runeRequired, Amount: uint128.FromBytes(decodedData.Amount), - Output: uint32(len(outputs)+1), + Output: uint32(len(outputs) + 1), }, }, Pointer: &changeOutputId, @@ -434,7 +442,7 @@ func (p *Provider) CreateBitcoinMultisigTx( Amount: MinSatsRequired, }) runeAmountRequired = amount - bitcoinAmountRequired = MinSatsRequired*2 + bitcoinAmountRequired = MinSatsRequired * 2 } } @@ -581,23 +589,23 @@ func (p *Provider) partSignTx(msgTx *wire.MsgTx, inputs []*multisig.UTXO, msWall return inputs, msWallet, msgTx, relayerSigs, err } -func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { +func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, bool, *big.Int, error) { msWallet, err := p.buildMultisigWallet() if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, false, nil, err } feeRate, err := p.client.GetFeeFromMempool(p.cfg.MempoolURL + "/fees/recommended") if err != nil { p.logger.Error("failed to get recommended fee from mempool", zap.Error(err)) feeRate = 0 } - inputs, msgTx, _, txSigHashes, err := p.buildTxMessage(message, feeRate, msWallet) + inputs, msgTx, _, txSigHashes, isRollbackMessage, rollbackSn, err := p.buildTxMessage(message, feeRate, msWallet) if err != nil { p.logger.Error("failed to build tx message: %v", zap.Error(err)) - return nil, nil, nil, nil, err + return nil, nil, nil, nil, false, nil, err } inputs, msWallet, msgTx, relayerSigs, err := p.partSignTx(msgTx, inputs, msWallet, txSigHashes) - return inputs, msWallet, msgTx, relayerSigs, err + return inputs, msWallet, msgTx, relayerSigs, isRollbackMessage, rollbackSn, err } func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { @@ -619,7 +627,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb return nil } else if p.cfg.Mode == MasterMode { - inputs, msWallet, msgTx, relayerSigs, err := p.HandleBitcoinMessageTx(message) + inputs, msWallet, msgTx, relayerSigs, isRollbackMessage, rollbackSn, err := p.HandleBitcoinMessageTx(message) if err != nil { p.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) return err @@ -627,8 +635,12 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb totalSigs := [][][]byte{relayerSigs} // send unsigned raw tx and message sn to 2 slave relayers to get sign rsi := slaveRequestParams{ - MsgSn: message.Sn, + MsgSn: message.Sn.String(), + } + if !isRollbackMessage { + rsi.MsgSn = "RB" + rollbackSn.String() } + slaveRequestData, _ := json.Marshal(rsi) slaveSigs := p.CallSlaves(slaveRequestData) p.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) @@ -663,55 +675,88 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("txHash", zap.String("transaction_hash", txHash)) // TODO: After successful broadcast, request slaves to remove the message from LevelDB if it exists } + + } + return nil +} + +// TODO: Implement proper callback handling +// callback(message.MessageKey(), txResponse, nil) + +func (p *Provider) decodeMessage(message *relayTypes.Message) (CSMessageResult, error) { + + wrapperInfo := CSMessage{} + _, err := codec.RLP.UnmarshalFromBytes(message.Data, &wrapperInfo) + if err != nil { + p.logger.Error("failed to unmarshal message: %v", zap.Error(err)) + return CSMessageResult{}, err } - // TODO: Implement proper callback handling - // callback(message.MessageKey(), txResponse, nil) + messageDecoded := CSMessageResult{} + _, err = codec.RLP.UnmarshalFromBytes(wrapperInfo.Payload, &messageDecoded) + if err != nil { + p.logger.Error("failed to unmarshal message: %v", zap.Error(err)) + return CSMessageResult{}, err + } - return nil + return messageDecoded, nil } -func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { +func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, bool, *big.Int, error) { outputs := []*multisig.OutputTx{} decodedData := &MessageDecoded{} + isRollbackMessage := false + rollbackSn := new(big.Int) switch message.EventType { case events.EmitMessage: - data, opreturnData, err := decodeWithdrawToMessage(message.Data) - decodedData = data + messageDecoded, err := p.decodeMessage(message) if err != nil { p.logger.Error("failed to decode message: %v", zap.Error(err)) - return nil, nil, "", nil, err } - scripts, _ := multisig.CreateBridgeMessageScripts(opreturnData, 76) - for _, script := range scripts { - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, - }) - } - case events.RollbackMessage: - data, err := p.db.Get([]byte(message.Sn.String()), nil) - if err != nil { - return nil, nil, "", nil, fmt.Errorf("failed to retrieve stored data: %v", err) - } - var storedData StoredMessageData - err = json.Unmarshal(data, &storedData) - if err != nil { - return nil, nil, "", nil, fmt.Errorf("failed to unmarshal stored data: %v", err) - } - decodedData.Action = storedData.ActionMethod - decodedData.To = storedData.SenderAddress - decodedData.TokenAddress = storedData.TokenAddress - decodedData.Amount = []byte(fmt.Sprintf("%d", storedData.Amount)) - if storedData.RuneId != "" { - decodedData.Amount = []byte(fmt.Sprintf("%d", storedData.RuneAmount)) + // 0 is need to rollback + if messageDecoded.Code == 0 { + isRollbackMessage = true + rollbackSn = new(big.Int).SetBytes(messageDecoded.Sn.Bytes()) + // Process RollbackMessage + data, err := p.db.Get([]byte("RB"+messageDecoded.Sn.String()), nil) + if err != nil { + return nil, nil, "", nil, isRollbackMessage, nil, fmt.Errorf("failed to retrieve stored data: %v", err) + } + var storedData StoredMessageData + err = json.Unmarshal(data, &storedData) + if err != nil { + return nil, nil, "", nil, isRollbackMessage, nil, fmt.Errorf("failed to unmarshal stored data: %v", err) + } + decodedData = &MessageDecoded{ + Action: storedData.ActionMethod, + To: storedData.SenderAddress, + TokenAddress: storedData.TokenAddress, + Amount: []byte(fmt.Sprintf("%d", storedData.Amount)), + } + if storedData.RuneId != "" { + decodedData.Amount = []byte(fmt.Sprintf("%d", storedData.RuneAmount)) + } + } else { + // Perform WithdrawData + data, opreturnData, err := decodeWithdrawToMessage(message.Data) + decodedData = data + if err != nil { + p.logger.Error("failed to decode message: %v", zap.Error(err)) + return nil, nil, "", nil, isRollbackMessage, nil, err + } + scripts, _ := multisig.CreateBridgeMessageScripts(opreturnData, 76) + for _, script := range scripts { + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } } - return nil, nil, "", nil, nil default: - return nil, nil, "", nil, fmt.Errorf("unknown event type: %s", message.EventType) + return nil, nil, "", nil, isRollbackMessage, nil, fmt.Errorf("unknown event type: %s", message.EventType) } - inputs, msgTx, hexRawTx, txSigHashes, err := p.CreateBitcoinMultisigTx(message.Data, feeRate, decodedData, msWallet) - return inputs, msgTx, hexRawTx, txSigHashes, err + inputs, msgTx, hexRawTx, txSigHashes, err := p.CreateBitcoinMultisigTx(outputs, feeRate, decodedData, msWallet) + return inputs, msgTx, hexRawTx, txSigHashes, isRollbackMessage, rollbackSn, err } // call the smart contract to send the message @@ -1087,7 +1132,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err return nil, fmt.Errorf("failed to marshal stored data: %v", err) } - err = p.db.Put([]byte(sn.String()), data, nil) + err = p.db.Put([]byte("RB"+sn.String()), data, nil) if err != nil { return nil, fmt.Errorf("failed to store message data: %v", err) } diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index 82e55d77..fa9574f9 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -12,6 +12,8 @@ import ( "path/filepath" "testing" + "github.com/btcsuite/btcd/btcec/v2/schnorr" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -104,9 +106,9 @@ func TestDepositBitcoinToIcon(t *testing.T) { inputs := []*multisig.UTXO{ { IsRelayersMultisig: false, - TxHash: "4933e04e3d9320df6e9f046ff83cfc3e9f884d8811df0539af7aaca0218189aa", - OutputIdx: 0, - OutputAmount: 4000000, + TxHash: "e57c10e27f75dbf0856163ca5f825b5af7ffbb3874f606b31330464ddd9df9a1", + OutputIdx: 4, + OutputAmount: 2974000, }, } @@ -115,15 +117,16 @@ func TestDepositBitcoinToIcon(t *testing.T) { // Add Bridge Message payload, _ := multisig.CreateBridgePayload( &multisig.XCallMessage{ + MessageType: 1, Action: "Deposit", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), + Amount: new(big.Int).SetUint64(100000).Bytes(), Data: []byte(""), }, 1, - "cx8b52dfea0aa1e548288102df15ad7159f7266106", + "cxfc86ee7687e1bf681b5548b2667844485c0e7192", []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, @@ -139,14 +142,18 @@ func TestDepositBitcoinToIcon(t *testing.T) { // Add transfering bitcoin to relayer multisig outputs = append(outputs, &multisig.OutputTx{ ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - Amount: 1000000, + Amount: 100000, }) userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + rlMsAddress, _ := multisig.AddressOnChain(chainParam, userMultisigWallet) + + msAddressStr := rlMsAddress.String() + fmt.Printf(msAddressStr) changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) + msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 100000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) tapSigParams := multisig.TapSigParams{ TxSigHashes: txSigHashes, @@ -598,13 +605,13 @@ func TestDepositRuneToIcon(t *testing.T) { // Add transfering rune to relayer multisig runeId, _ := runestone.NewRuneId(840000, 3) - changeReceiver := uint32(len(outputs)+2) + changeReceiver := uint32(len(outputs) + 2) runeStone := &runestone.Runestone{ Edicts: []runestone.Edict{ { - ID: *runeId, + ID: *runeId, Amount: uint128.From64(1000000000), - Output: uint32(len(outputs)+1), + Output: uint32(len(outputs) + 1), }, }, Pointer: &changeReceiver, @@ -666,4 +673,98 @@ func TestDepositRuneToIcon(t *testing.T) { a, _ := json.Marshal(artifact) fmt.Printf("Artifact: %s\n", string(a)) // TODO: test the signedMsgTx -} \ No newline at end of file +} + +func TestCreateAndSignBitcoinTransaction(t *testing.T) { + // Set up the network parameters (use TestNet3 for testing) + chainParam := &chaincfg.TestNet3Params + wif, _ := btcutil.DecodeWIF("your_private_key") + // Get the private key from WIF + privateKey := wif.PrivKey + // Create a Taproot address + internalKey := privateKey.PubKey() + taprootKey := txscript.ComputeTaprootOutputKey(internalKey, nil) + taprootAddress, err := btcutil.NewAddressTaproot(schnorr.SerializePubKey(taprootKey), chainParam) + assert.NoError(t, err) + + // Create the output script (witness program) + pkScript, err := txscript.PayToAddrScript(taprootAddress) + assert.NoError(t, err) + + prevOutputAmount := uint64(99800000) + sendingAmount := uint64(100000) + fees := uint64(200000) + + inputs := []*multisig.UTXO{ + { + IsRelayersMultisig: false, + TxHash: "9dbd6f6f976f9f31895214c6c3034c80c567a38e1e816b8eb6bed972df0fdad9", + OutputIdx: 4, + OutputAmount: prevOutputAmount, + }, + } + + outputs := []*multisig.OutputTx{} + + // Add Bridge Message + payload, _ := multisig.CreateBridgePayload( + &multisig.XCallMessage{MessageType: 1, + Action: "Deposit", + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1peg65qks0qum848kq8udf3n3psvkpkaxsr7wq60ukr7w2symtt83qwd7cmx", + Amount: new(big.Int).SetUint64(sendingAmount).Bytes(), + Data: []byte(""), + }, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + ) + scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) + for i, script := range scripts { + fmt.Println("OP_RETURN ", i, " script ", script) + outputs = append(outputs, &multisig.OutputTx{ + OpReturnScript: script, + }) + } + // Add transfering bitcoin to relayer multisig + outputs = append(outputs, &multisig.OutputTx{ + ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", + Amount: sendingAmount, + }) + + changeReceiverAddress := "tb1peg65qks0qum848kq8udf3n3psvkpkaxsr7wq60ukr7w2symtt83qwd7cmx" + msgTx, _, _, _ := multisig.CreateMultisigTx(inputs, outputs, fees, &multisig.MultisigWallet{}, &multisig.MultisigWallet{}, chainParam, changeReceiverAddress, 1) + + // Sign the transaction using Taproot + for i, txIn := range msgTx.TxIn { + // Create the signing hash + prevOutputFetcher := txscript.NewCannedPrevOutputFetcher(pkScript, int64(prevOutputAmount)) + sigHashes := txscript.NewTxSigHashes(msgTx, prevOutputFetcher) + + // Create the Taproot signature + witness, err := txscript.TaprootWitnessSignature( + msgTx, + sigHashes, + i, + int64(prevOutputAmount), + pkScript, + txscript.SigHashDefault, + privateKey, + ) + assert.NoError(t, err) + + // Set the witness data + txIn.Witness = witness + } + + // Serialize the transaction + var signedTx bytes.Buffer + err = msgTx.Serialize(&signedTx) + assert.NoError(t, err) + + // Print the hex-encoded transaction + fmt.Printf("Signed Taproot transaction: %x\n", signedTx.Bytes()) +} diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index ae8ace2e..e3f4e893 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -3,7 +3,6 @@ package bitcoin import ( "encoding/json" "io" - "math/big" "net/http" relayTypes "github.com/icon-project/centralized-relay/relayer/types" @@ -63,8 +62,8 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { } } -func buildAndSignTxFromDbMessage(sn *big.Int, p *Provider) ([][]byte, error) { - key := sn.String() +func buildAndSignTxFromDbMessage(sn string, p *Provider) ([][]byte, error) { + key := sn data, err := p.db.Get([]byte(key), nil) if err != nil { return nil, err @@ -76,7 +75,7 @@ func buildAndSignTxFromDbMessage(sn *big.Int, p *Provider) ([][]byte, error) { return nil, err } - _, _, _, relayerSigns, err := p.HandleBitcoinMessageTx(message) + _, _, _, relayerSigns, _, _, err := p.HandleBitcoinMessageTx(message) if err != nil { return nil, err } diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index 6a8a93e3..63147852 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -15,7 +15,7 @@ const ( type CallMessageType int const ( - CALL_MESSAGE_TYPE MessageType = iota + CALL_MESSAGE_TYPE CallMessageType = iota CALL_MESSAGE_ROLLBACK_TYPE PERSISTENT_MESSAGE_TYPE ) @@ -27,8 +27,8 @@ type TxSearchParam struct { } type TxSearchRes struct { - Tx *wire.MsgTx - Height uint64 + Tx *wire.MsgTx + Height uint64 TxIndex uint64 } diff --git a/relayer/chains/icon/client.go b/relayer/chains/icon/client.go index 2bba2865..e289ae34 100644 --- a/relayer/chains/icon/client.go +++ b/relayer/chains/icon/client.go @@ -268,7 +268,8 @@ func (c *Client) Monitor(ctx context.Context, reqUrl string, reqPtr, respPtr int c.log.Debug(fmt.Sprintf("Monitor finish %s", conn.RemoteAddr().String())) c.wsClose(conn) }() - + //TODO: should remove after test + // if err = c.wsRequest(conn, interface{}("")); err != nil { if err = c.wsRequest(conn, reqPtr); err != nil { return err } diff --git a/relayer/chains/icon/route.go b/relayer/chains/icon/route.go index 7146dffa..f156aa21 100644 --- a/relayer/chains/icon/route.go +++ b/relayer/chains/icon/route.go @@ -12,18 +12,23 @@ import ( ) func (p *Provider) Route(ctx context.Context, message *providerTypes.Message, callback providerTypes.TxResponseFunc) error { - p.log.Info("starting to route message", zap.Any("message", message)) - iconMessage, err := p.MakeIconMessage(message) - if err != nil { - return err - } - messageKey := message.MessageKey() + // TODO: remove this after testing + if message.Src == "0x2.btc" || message.Dst == "0x2.btc" { + p.log.Info("starting to route message", zap.Any("message", message)) + iconMessage, err := p.MakeIconMessage(message) - txhash, err := p.SendTransaction(ctx, iconMessage) - if err != nil { - return errors.Wrapf(err, "error occured while sending transaction") + if err != nil { + return err + } + messageKey := message.MessageKey() + + txhash, err := p.SendTransaction(ctx, iconMessage) + if err != nil { + return errors.Wrapf(err, "error occured while sending transaction") + } + return p.WaitForTxResult(ctx, txhash, messageKey, iconMessage.Method, callback) } - return p.WaitForTxResult(ctx, txhash, messageKey, iconMessage.Method, callback) + return nil } func (p *Provider) MakeIconMessage(message *providerTypes.Message) (*IconMessage, error) { diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 1979aa6c..7df01948 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -17,10 +17,10 @@ import ( "github.com/holiman/uint256" ) -const( - TX_FEE = 10000 +const ( + TX_FEE = 10000 RELAYER_MULTISIG_ADDRESS = "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u" - USER_MULTISIG_ADDRESS = "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + USER_MULTISIG_ADDRESS = "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" ) func TestGenerateKeys(t *testing.T) { @@ -29,7 +29,7 @@ func TestGenerateKeys(t *testing.T) { for i := 0; i < 3; i++ { privKey := GeneratePrivateKeyFromSeed([]byte{byte(i)}, chainParam) wif, _ := btcutil.NewWIF(privKey, chainParam, true) - pubKey := wif.SerializePubKey(); + pubKey := wif.SerializePubKey() witnessProg := btcutil.Hash160(pubKey) p2wpkh, _ := btcutil.NewAddressWitnessPubKeyHash(witnessProg, chainParam) @@ -41,7 +41,7 @@ func TestLoadWalletFromPrivateKey(t *testing.T) { chainParam := &chaincfg.TestNet3Params wif, _ := btcutil.DecodeWIF("cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy") - pubKey := wif.SerializePubKey(); + pubKey := wif.SerializePubKey() witnessProg := btcutil.Hash160(pubKey) p2wpkh, _ := btcutil.NewAddressWitnessPubKeyHash(witnessProg, chainParam) @@ -79,9 +79,9 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: true, - TxHash: "9ed822adb7c3623fcc6776bc93dadb030bf3b887e36975521d540c2a49510e27", - OutputIdx: 1, - OutputAmount: 3901, + TxHash: "9ed822adb7c3623fcc6776bc93dadb030bf3b887e36975521d540c2a49510e27", + OutputIdx: 1, + OutputAmount: 3901, }, } @@ -97,12 +97,12 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - UserPKScript: []byte{}, - UserTapLeaf: txscript.TapLeaf{}, + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: []byte{}, + UserTapLeaf: txscript.TapLeaf{}, } totalSigs := [][][]byte{} @@ -116,9 +116,9 @@ func TestMultisigUserClaimLiquidity(t *testing.T) { router := SetUpRouter() // create post body using an instance of the requestSignInput struct rsi := requestSignInput{ - MsgTx: hexRawTx, - UTXOs: inputs, - TapSigInfo: tapSigParams, + MsgTx: hexRawTx, + UTXOs: inputs, + TapSigInfo: tapSigParams, } requestJson, _ := json.Marshal(rsi) @@ -151,15 +151,15 @@ func TestMultisigUserSwap(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", - OutputIdx: 0, - OutputAmount: 1501, + TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", + OutputIdx: 0, + OutputAmount: 1501, }, { IsRelayersMultisig: true, - TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", - OutputIdx: 1, - OutputAmount: 4234, + TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", + OutputIdx: 1, + OutputAmount: 4234, }, } @@ -177,12 +177,12 @@ func TestMultisigUserSwap(t *testing.T) { changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[0], + RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[0], } totalSigs := [][][]byte{} @@ -196,9 +196,9 @@ func TestMultisigUserSwap(t *testing.T) { router := SetUpRouter() // create post body using an instance of the requestSignInput struct rsi := requestSignInput{ - MsgTx: hexRawTx, - UTXOs: inputs, - TapSigInfo: tapSigParams, + MsgTx: hexRawTx, + UTXOs: inputs, + TapSigInfo: tapSigParams, } requestJson, _ := json.Marshal(rsi) @@ -217,7 +217,7 @@ func TestMultisigUserSwap(t *testing.T) { // add user sign to total sigs for i := range msgTx.TxIn { - if (!inputs[i].IsRelayersMultisig) { + if !inputs[i].IsRelayersMultisig { totalSigs[1][i] = userSigs[i] } } @@ -268,9 +268,9 @@ func TestUserRecoveryTimeLock(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", - OutputIdx: 4, - OutputAmount: 1929000, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, }, } @@ -286,12 +286,12 @@ func TestUserRecoveryTimeLock(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -319,9 +319,9 @@ func TestTransferRune(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 3808, + TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", + OutputIdx: 1, + OutputAmount: 3808, }, } @@ -342,12 +342,12 @@ func TestTransferRune(t *testing.T) { script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) msgTx.AddTxOut(wire.NewTxOut(0, script1)) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -385,9 +385,9 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "88cce50b4c9ff0d1c3f58f769fdb8b2e2bfbd3a637664c78b1a38c0f1e492b8f", - OutputIdx: 0, - OutputAmount: 2000000, + TxHash: "88cce50b4c9ff0d1c3f58f769fdb8b2e2bfbd3a637664c78b1a38c0f1e492b8f", + OutputIdx: 0, + OutputAmount: 2000000, }, } @@ -401,11 +401,11 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { // Add Bridge Message payload, _ := CreateBridgePayload( &XCallMessage{ - MessageType: 123, + MessageType: 1, Action: "Deposit", - TokenAddress: "0:0", // bitcoin address - To: "0x2.icon/hx39eddef484f6bb08072c59cc0a206e6713fc6d7d", //(receiver) - From: USER_MULTISIG_ADDRESS, //user + TokenAddress: "0:0", // bitcoin address + To: "0x2.icon/hx39eddef484f6bb08072c59cc0a206e6713fc6d7d", //(receiver) + From: USER_MULTISIG_ADDRESS, //user Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), }, @@ -431,13 +431,12 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -480,22 +479,22 @@ func TestRadFiInitPool(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: false, - TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", - OutputIdx: 4, - OutputAmount: 1929000, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, }, } // OP_RETURN RadFi Init pool Message - radfiMsg := RadFiProvideLiquidityMsg { + radfiMsg := RadFiProvideLiquidityMsg{ Detail: &RadFiProvideLiquidityDetail{ - Fee: 30, - UpperTick: 12345, - LowerTick: -12345, - Min0: 0, - Min1: 10000, + Fee: 30, + UpperTick: 12345, + LowerTick: -12345, + Min0: 0, + Min1: 10000, }, - InitPrice: uint256.MustFromDecimal("123456789"), + InitPrice: uint256.MustFromDecimal("123456789"), } script, _ := CreateProvideLiquidityScript(&radfiMsg) @@ -515,12 +514,12 @@ func TestRadFiInitPool(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -558,32 +557,32 @@ func TestRadFiProvideLiquidity(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: true, - TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", - OutputIdx: 0, - OutputAmount: 1000, + TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", + OutputIdx: 0, + OutputAmount: 1000, }, { IsRelayersMultisig: false, - TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", - OutputIdx: 2, - OutputAmount: 1918000, + TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", + OutputIdx: 2, + OutputAmount: 1918000, }, { IsRelayersMultisig: false, - TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", - OutputIdx: 0, - OutputAmount: 1000, + TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", + OutputIdx: 0, + OutputAmount: 1000, }, } // OP_RETURN RadFi Provive Liquidity Message - radfiMsg := RadFiProvideLiquidityMsg { + radfiMsg := RadFiProvideLiquidityMsg{ Detail: &RadFiProvideLiquidityDetail{ - Fee: 30, - UpperTick: 12345, - LowerTick: -12345, - Min0: 0, - Min1: 10000, + Fee: 30, + UpperTick: 12345, + LowerTick: -12345, + Min0: 0, + Min1: 10000, }, } script1, _ := CreateProvideLiquidityScript(&radfiMsg) @@ -618,12 +617,12 @@ func TestRadFiProvideLiquidity(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -677,27 +676,27 @@ func TestRadFiSwap(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: true, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 0, - OutputAmount: 1000, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 0, + OutputAmount: 1000, }, { IsRelayersMultisig: false, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 5, - OutputAmount: 1888000, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 5, + OutputAmount: 1888000, }, { IsRelayersMultisig: false, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 4, - OutputAmount: 1000, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 4, + OutputAmount: 1000, }, } // OP_RETURN RadFi Swap Message - radfiMsg := RadFiSwapMsg { - IsExactInOut: true, + radfiMsg := RadFiSwapMsg{ + IsExactInOut: true, TokenOutIndex: 2, } script1, _ := CreateSwapScript(&radfiMsg) @@ -741,12 +740,12 @@ func TestRadFiSwap(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -781,35 +780,35 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: true, - TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", - OutputIdx: 0, - OutputAmount: 1000, + TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", + OutputIdx: 0, + OutputAmount: 1000, }, { IsRelayersMultisig: true, - TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", - OutputIdx: 4, - OutputAmount: 10000, + TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", + OutputIdx: 4, + OutputAmount: 10000, }, { IsRelayersMultisig: true, - TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", - OutputIdx: 6, - OutputAmount: 1000, + TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", + OutputIdx: 6, + OutputAmount: 1000, }, { IsRelayersMultisig: false, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 5, - OutputAmount: 1867000, + TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", + OutputIdx: 5, + OutputAmount: 1867000, }, } // OP_RETURN RadFi Withdraw Liquidity Message - radfiMsg := RadFiWithdrawLiquidityMsg { - RecipientIndex: 2, + radfiMsg := RadFiWithdrawLiquidityMsg{ + RecipientIndex: 2, LiquidityValue: uint256.MustFromDecimal("123456"), - NftId: uint256.MustFromDecimal("123456789"), + NftId: uint256.MustFromDecimal("123456789"), } script1, _ := CreateWithdrawLiquidityScript(&radfiMsg) // OP_RETURN Rune transfering @@ -855,12 +854,12 @@ func TestRadFiWithdrawLiquidity(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -896,34 +895,34 @@ func TestRadFiCollectFees(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: true, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 0, - OutputAmount: 1000, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 0, + OutputAmount: 1000, }, { IsRelayersMultisig: true, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 5, - OutputAmount: 5000, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 5, + OutputAmount: 5000, }, { IsRelayersMultisig: true, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 7, - OutputAmount: 1000, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 7, + OutputAmount: 1000, }, { IsRelayersMultisig: false, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 8, - OutputAmount: 1856000, + TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", + OutputIdx: 8, + OutputAmount: 1856000, }, } // OP_RETURN RadFi Collect Fees - radfiMsg := RadFiCollectFeesMsg { - RecipientIndex: 2, - NftId: uint256.MustFromDecimal("123456789"), + radfiMsg := RadFiCollectFeesMsg{ + RecipientIndex: 2, + NftId: uint256.MustFromDecimal("123456789"), } script1, _ := CreateCollectFeesScript(&radfiMsg) // OP_RETURN Rune transfering @@ -970,12 +969,12 @@ func TestRadFiCollectFees(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} @@ -1010,29 +1009,29 @@ func TestRadFiIncreaseLiquidity(t *testing.T) { inputs := []*UTXO{ { IsRelayersMultisig: true, - TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", - OutputIdx: 0, - OutputAmount: 1000, + TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", + OutputIdx: 0, + OutputAmount: 1000, }, { IsRelayersMultisig: false, - TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", - OutputIdx: 8, - OutputAmount: 1845000, + TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", + OutputIdx: 8, + OutputAmount: 1845000, }, { IsRelayersMultisig: false, - TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", - OutputIdx: 0, - OutputAmount: 1000, + TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", + OutputIdx: 0, + OutputAmount: 1000, }, } // OP_RETURN RadFi Increase Liquidity Message - radfiMsg := RadFiIncreaseLiquidityMsg { - Min0: 0, - Min1: 10000, - NftId: uint256.MustFromDecimal("123456789"), + radfiMsg := RadFiIncreaseLiquidityMsg{ + Min0: 0, + Min1: 10000, + NftId: uint256.MustFromDecimal("123456789"), } script1, _ := CreateIncreaseLiquidityScript(&radfiMsg) // OP_RETURN Rune transfering @@ -1066,12 +1065,12 @@ func TestRadFiIncreaseLiquidity(t *testing.T) { changeReceiverAddress := USER_MULTISIG_ADDRESS msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams { - TxSigHashes: txSigHashes, + tapSigParams := TapSigParams{ + TxSigHashes: txSigHashes, RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + RelayersTapLeaf: txscript.TapLeaf{}, + UserPKScript: userMultisigWallet.PKScript, + UserTapLeaf: userMultisigWallet.TapLeaves[1], } totalSigs := [][][]byte{} diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go index 3aa9b391..bb30dc83 100644 --- a/utils/multisig/op_message.go +++ b/utils/multisig/op_message.go @@ -13,92 +13,92 @@ import ( ) const ( - OP_RADFI_IDENT = txscript.OP_12 - OP_RUNE_IDENT = txscript.OP_13 - OP_BRIDGE_IDENT = txscript.OP_14 - - OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 - OP_RADFI_SWAP = txscript.OP_2 - OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 - OP_RADFI_COLLECT_FEES = txscript.OP_4 - OP_RADFI_INCREASE_LIQUIDITY = txscript.OP_5 + OP_RADFI_IDENT = txscript.OP_12 + OP_RUNE_IDENT = txscript.OP_13 + OP_BRIDGE_IDENT = txscript.OP_14 + + OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 + OP_RADFI_SWAP = txscript.OP_2 + OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 + OP_RADFI_COLLECT_FEES = txscript.OP_4 + OP_RADFI_INCREASE_LIQUIDITY = txscript.OP_5 ) type XCallMessage struct { - MessageType uint8 - Action string - TokenAddress string - From string - To string - Amount []byte - Data []byte + MessageType uint8 + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte } type RadFiProvideLiquidityDetail struct { - Fee uint8 - UpperTick int32 - LowerTick int32 - Min0 uint16 - Min1 uint16 + Fee uint8 + UpperTick int32 + LowerTick int32 + Min0 uint16 + Min1 uint16 } type RadFiProvideLiquidityMsg struct { - Detail *RadFiProvideLiquidityDetail - InitPrice *uint256.Int + Detail *RadFiProvideLiquidityDetail + InitPrice *uint256.Int } type RadFiSwapMsg struct { - IsExactInOut bool - TokenOutIndex uint32 + IsExactInOut bool + TokenOutIndex uint32 // TokenOutId *Rune // TokenOutAmount *uint256.Int } type RadFiWithdrawLiquidityMsg struct { - RecipientIndex uint32 - LiquidityValue *uint256.Int - NftId *uint256.Int + RecipientIndex uint32 + LiquidityValue *uint256.Int + NftId *uint256.Int } type RadFiCollectFeesMsg struct { - RecipientIndex uint32 - NftId *uint256.Int + RecipientIndex uint32 + NftId *uint256.Int } type RadFiIncreaseLiquidityMsg struct { - Min0 uint16 - Min1 uint16 - NftId *uint256.Int + Min0 uint16 + Min1 uint16 + NftId *uint256.Int } type BridgeDecodedMsg struct { - Message *XCallMessage - ChainId uint8 - Receiver string + Message *XCallMessage + ChainId uint8 + Receiver string Connectors []string } type RadFiDecodedMsg struct { - Flag byte - ProvideLiquidityMsg *RadFiProvideLiquidityMsg - SwapMsg *RadFiSwapMsg - WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg - CollectFeesMsg *RadFiCollectFeesMsg - IncreaseLiquidityMsg *RadFiIncreaseLiquidityMsg + Flag byte + ProvideLiquidityMsg *RadFiProvideLiquidityMsg + SwapMsg *RadFiSwapMsg + WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg + CollectFeesMsg *RadFiCollectFeesMsg + IncreaseLiquidityMsg *RadFiIncreaseLiquidityMsg } func AddressToPayload(address string) ([]byte, error) { prefix := address[0:2] var prefixType uint8 // max number of supported type is 7 switch prefix { - case "0x": - prefixType = 1 - case "hx": - prefixType = 2 - case "cx": - prefixType = 3 - default: - return nil, fmt.Errorf("address type not supported") + case "0x": + prefixType = 1 + case "hx": + prefixType = 2 + case "cx": + prefixType = 3 + default: + return nil, fmt.Errorf("address type not supported") } addressBytes, err := hex.DecodeString(address[2:]) if err != nil { @@ -119,14 +119,14 @@ func PayloadToAddress(payload []byte) (string, []byte, error) { prefixType := uint8(prefixByte >> 5) var prefix string switch prefixType { - case 1: - prefix = "0x" - case 2: - prefix = "hx" - case 3: - prefix = "cx" - default: - return "", nil, fmt.Errorf("prefix type not supported") + case 1: + prefix = "0x" + case 2: + prefix = "hx" + case 3: + prefix = "cx" + default: + return "", nil, fmt.Errorf("prefix type not supported") } addressBytesLen := uint8((prefixByte << 3 >> 3) + 1) address := prefix + hex.EncodeToString(payload[1:addressBytesLen+1]) @@ -197,7 +197,7 @@ func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) builder.AddOp(OP_RADFI_PROVIDE_LIQUIDITY) // encode message content buf := new(bytes.Buffer) - var data = []any{ msg.Detail.Fee, msg.Detail.UpperTick, msg.Detail.LowerTick, msg.Detail.Min0, msg.Detail.Min1 } + var data = []any{msg.Detail.Fee, msg.Detail.UpperTick, msg.Detail.LowerTick, msg.Detail.Min0, msg.Detail.Min1} for _, v := range data { err := binary.Write(buf, binary.BigEndian, v) if err != nil { @@ -293,7 +293,7 @@ func CreateIncreaseLiquidityScript(msg *RadFiIncreaseLiquidityMsg) ([]byte, erro builder.AddOp(OP_RADFI_INCREASE_LIQUIDITY) // encode message content buf := new(bytes.Buffer) - var data = []any{ msg.Min0, msg.Min1 } + var data = []any{msg.Min0, msg.Min1} for _, v := range data { err := binary.Write(buf, binary.BigEndian, v) if err != nil { @@ -350,10 +350,10 @@ func ReadBridgeMessage(transaction *wire.MsgTx) (*BridgeDecodedMsg, error) { connectors = append(connectors, connector) } - return &BridgeDecodedMsg { - Message: &message, - ChainId: chainId, - Receiver: receiver, + return &BridgeDecodedMsg{ + Message: &message, + ChainId: chainId, + Receiver: receiver, Connectors: connectors, }, nil } @@ -390,103 +390,103 @@ func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { // Decode RadFi message switch flag { - case OP_RADFI_PROVIDE_LIQUIDITY: - r := bytes.NewReader(payload[:13]) - var provideLiquidityDetail RadFiProvideLiquidityDetail - if err := binary.Read(r, binary.BigEndian, &provideLiquidityDetail); err != nil { - return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_PROVIDE_LIQUIDITY Read failed") - } - - if len(payload) > 13 { - return &RadFiDecodedMsg { - Flag : flag, - ProvideLiquidityMsg : &RadFiProvideLiquidityMsg{ - Detail : &provideLiquidityDetail, - InitPrice : new(uint256.Int).SetBytes(payload[13:]), - }, - }, nil - } - - return &RadFiDecodedMsg { - Flag : flag, - ProvideLiquidityMsg : &RadFiProvideLiquidityMsg{ - Detail : &provideLiquidityDetail, - }, - }, nil - - case OP_RADFI_SWAP: - // singleByte := uint8(payload[0]) - // isExactInOut := (singleByte >> 7) != 0 - // tokenOutIdBlockNumberLen := singleByte << 1 >> 4 - // tokenOutIdTxIndexLen := singleByte << 5 >> 5 - - // payload = payload[1:] - // tokenOutIdBlockNumber := binary.BigEndian.Uint64(payload[:tokenOutIdBlockNumberLen]) - - // payload = payload[tokenOutIdBlockNumberLen:] - // tokenOutIdTxIndex := binary.BigEndian.Uint32(payload[:tokenOutIdTxIndexLen]) - - // TokenOutAmount := new(uint256.Int).SetBytes(payload[tokenOutIdTxIndexLen:]) - - return &RadFiDecodedMsg { - Flag : flag, - SwapMsg: &RadFiSwapMsg{ - IsExactInOut : payload[0] != 0, - TokenOutIndex : binary.BigEndian.Uint32(payload[1:]), - // TokenOutId : &Rune{ - // BlockNumber : tokenOutIdBlockNumber, - // TxIndex : tokenOutIdTxIndex, - // }, - // TokenOutAmount : TokenOutAmount, - }, - }, nil - - case OP_RADFI_WITHDRAW_LIQUIDITY: - // singleByte := uint8(payload[0]) - // recipientIndexLen := singleByte >> 5 - // fmt.Println("recipientIndexLen", recipientIndexLen) - // liquidityValueBytesLen := singleByte << 3 >> 3 - liquidityValueBytesLen := uint8(payload[0]) - // fmt.Println("liquidityValueBytesLen", liquidityValueBytesLen) - payload = payload[1:] - recipientIndex := binary.BigEndian.Uint32(payload[:4]) - payload = payload[4:] - liquidityValue := new(uint256.Int).SetBytes(payload[:liquidityValueBytesLen]) - nftId := new(uint256.Int).SetBytes(payload[liquidityValueBytesLen:]) - // fmt.Println("OP_RADFI_WITHDRAW_LIQUIDITY", recipientIndex, liquidityValue, NftId) - - return &RadFiDecodedMsg { - Flag : flag, - WithdrawLiquidityMsg: &RadFiWithdrawLiquidityMsg{ - RecipientIndex : recipientIndex, - LiquidityValue : liquidityValue, - NftId : nftId, - }, - }, nil - - case OP_RADFI_COLLECT_FEES: - recipientIndex := binary.BigEndian.Uint32(payload[:4]) - nftId := new(uint256.Int).SetBytes(payload[4:]) - - return &RadFiDecodedMsg { - Flag : flag, - CollectFeesMsg : &RadFiCollectFeesMsg{ - RecipientIndex : recipientIndex, - NftId : nftId, - }, - }, nil + case OP_RADFI_PROVIDE_LIQUIDITY: + r := bytes.NewReader(payload[:13]) + var provideLiquidityDetail RadFiProvideLiquidityDetail + if err := binary.Read(r, binary.BigEndian, &provideLiquidityDetail); err != nil { + return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_PROVIDE_LIQUIDITY Read failed") + } - case OP_RADFI_INCREASE_LIQUIDITY: - return &RadFiDecodedMsg { - Flag : flag, - IncreaseLiquidityMsg: &RadFiIncreaseLiquidityMsg{ - Min0 : binary.BigEndian.Uint16(payload[:2]), - Min1 : binary.BigEndian.Uint16(payload[2:4]), - NftId : new(uint256.Int).SetBytes(payload[4:]), + if len(payload) > 13 { + return &RadFiDecodedMsg{ + Flag: flag, + ProvideLiquidityMsg: &RadFiProvideLiquidityMsg{ + Detail: &provideLiquidityDetail, + InitPrice: new(uint256.Int).SetBytes(payload[13:]), }, }, nil + } - default: - return nil, fmt.Errorf("ReadRadFiMessage - invalid flag") + return &RadFiDecodedMsg{ + Flag: flag, + ProvideLiquidityMsg: &RadFiProvideLiquidityMsg{ + Detail: &provideLiquidityDetail, + }, + }, nil + + case OP_RADFI_SWAP: + // singleByte := uint8(payload[0]) + // isExactInOut := (singleByte >> 7) != 0 + // tokenOutIdBlockNumberLen := singleByte << 1 >> 4 + // tokenOutIdTxIndexLen := singleByte << 5 >> 5 + + // payload = payload[1:] + // tokenOutIdBlockNumber := binary.BigEndian.Uint64(payload[:tokenOutIdBlockNumberLen]) + + // payload = payload[tokenOutIdBlockNumberLen:] + // tokenOutIdTxIndex := binary.BigEndian.Uint32(payload[:tokenOutIdTxIndexLen]) + + // TokenOutAmount := new(uint256.Int).SetBytes(payload[tokenOutIdTxIndexLen:]) + + return &RadFiDecodedMsg{ + Flag: flag, + SwapMsg: &RadFiSwapMsg{ + IsExactInOut: payload[0] != 0, + TokenOutIndex: binary.BigEndian.Uint32(payload[1:]), + // TokenOutId : &Rune{ + // BlockNumber : tokenOutIdBlockNumber, + // TxIndex : tokenOutIdTxIndex, + // }, + // TokenOutAmount : TokenOutAmount, + }, + }, nil + + case OP_RADFI_WITHDRAW_LIQUIDITY: + // singleByte := uint8(payload[0]) + // recipientIndexLen := singleByte >> 5 + // fmt.Println("recipientIndexLen", recipientIndexLen) + // liquidityValueBytesLen := singleByte << 3 >> 3 + liquidityValueBytesLen := uint8(payload[0]) + // fmt.Println("liquidityValueBytesLen", liquidityValueBytesLen) + payload = payload[1:] + recipientIndex := binary.BigEndian.Uint32(payload[:4]) + payload = payload[4:] + liquidityValue := new(uint256.Int).SetBytes(payload[:liquidityValueBytesLen]) + nftId := new(uint256.Int).SetBytes(payload[liquidityValueBytesLen:]) + // fmt.Println("OP_RADFI_WITHDRAW_LIQUIDITY", recipientIndex, liquidityValue, NftId) + + return &RadFiDecodedMsg{ + Flag: flag, + WithdrawLiquidityMsg: &RadFiWithdrawLiquidityMsg{ + RecipientIndex: recipientIndex, + LiquidityValue: liquidityValue, + NftId: nftId, + }, + }, nil + + case OP_RADFI_COLLECT_FEES: + recipientIndex := binary.BigEndian.Uint32(payload[:4]) + nftId := new(uint256.Int).SetBytes(payload[4:]) + + return &RadFiDecodedMsg{ + Flag: flag, + CollectFeesMsg: &RadFiCollectFeesMsg{ + RecipientIndex: recipientIndex, + NftId: nftId, + }, + }, nil + + case OP_RADFI_INCREASE_LIQUIDITY: + return &RadFiDecodedMsg{ + Flag: flag, + IncreaseLiquidityMsg: &RadFiIncreaseLiquidityMsg{ + Min0: binary.BigEndian.Uint16(payload[:2]), + Min1: binary.BigEndian.Uint16(payload[2:4]), + NftId: new(uint256.Int).SetBytes(payload[4:]), + }, + }, nil + + default: + return nil, fmt.Errorf("ReadRadFiMessage - invalid flag") } } From d06ffe51338fabe31b92bacd3c3e9b1b2cbbae1e Mon Sep 17 00:00:00 2001 From: Shall Date: Sun, 29 Sep 2024 21:41:09 +0700 Subject: [PATCH 073/113] feat: update condition rollback message --- relayer/chains/bitcoin/provider.go | 2 +- relayer/chains/bitcoin/slave.go | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 37c0eeeb..6d6e8fe9 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -637,7 +637,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb rsi := slaveRequestParams{ MsgSn: message.Sn.String(), } - if !isRollbackMessage { + if isRollbackMessage { rsi.MsgSn = "RB" + rollbackSn.String() } diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index e3f4e893..d770686e 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -63,6 +63,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { } func buildAndSignTxFromDbMessage(sn string, p *Provider) ([][]byte, error) { + p.logger.Info("Slave start to build and sign tx from db message", zap.String("sn", sn)) key := sn data, err := p.db.Get([]byte(key), nil) if err != nil { From 1c4d188d46a7779bc2e22d44ee4fbdb0835e762c Mon Sep 17 00:00:00 2001 From: Shall Date: Sun, 29 Sep 2024 22:28:54 +0700 Subject: [PATCH 074/113] feat: change logic to get rollback message from db --- relayer/chains/bitcoin/provider.go | 38 +++++++++++++----------------- relayer/chains/bitcoin/slave.go | 8 ++++++- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 6d6e8fe9..c271ff04 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -589,23 +589,23 @@ func (p *Provider) partSignTx(msgTx *wire.MsgTx, inputs []*multisig.UTXO, msWall return inputs, msWallet, msgTx, relayerSigs, err } -func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, bool, *big.Int, error) { +func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { msWallet, err := p.buildMultisigWallet() if err != nil { - return nil, nil, nil, nil, false, nil, err + return nil, nil, nil, nil, err } feeRate, err := p.client.GetFeeFromMempool(p.cfg.MempoolURL + "/fees/recommended") if err != nil { p.logger.Error("failed to get recommended fee from mempool", zap.Error(err)) feeRate = 0 } - inputs, msgTx, _, txSigHashes, isRollbackMessage, rollbackSn, err := p.buildTxMessage(message, feeRate, msWallet) + inputs, msgTx, _, txSigHashes, err := p.buildTxMessage(message, feeRate, msWallet) if err != nil { p.logger.Error("failed to build tx message: %v", zap.Error(err)) - return nil, nil, nil, nil, false, nil, err + return nil, nil, nil, nil, err } inputs, msWallet, msgTx, relayerSigs, err := p.partSignTx(msgTx, inputs, msWallet, txSigHashes) - return inputs, msWallet, msgTx, relayerSigs, isRollbackMessage, rollbackSn, err + return inputs, msWallet, msgTx, relayerSigs, err } func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { @@ -627,7 +627,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb return nil } else if p.cfg.Mode == MasterMode { - inputs, msWallet, msgTx, relayerSigs, isRollbackMessage, rollbackSn, err := p.HandleBitcoinMessageTx(message) + inputs, msWallet, msgTx, relayerSigs, err := p.HandleBitcoinMessageTx(message) if err != nil { p.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) return err @@ -637,9 +637,6 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb rsi := slaveRequestParams{ MsgSn: message.Sn.String(), } - if isRollbackMessage { - rsi.MsgSn = "RB" + rollbackSn.String() - } slaveRequestData, _ := json.Marshal(rsi) slaveSigs := p.CallSlaves(slaveRequestData) @@ -702,11 +699,10 @@ func (p *Provider) decodeMessage(message *relayTypes.Message) (CSMessageResult, return messageDecoded, nil } -func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, bool, *big.Int, error) { +func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { outputs := []*multisig.OutputTx{} decodedData := &MessageDecoded{} - isRollbackMessage := false - rollbackSn := new(big.Int) + switch message.EventType { case events.EmitMessage: messageDecoded, err := p.decodeMessage(message) @@ -715,17 +711,16 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, m } // 0 is need to rollback if messageDecoded.Code == 0 { - isRollbackMessage = true - rollbackSn = new(big.Int).SetBytes(messageDecoded.Sn.Bytes()) + p.logger.Info("Detected rollback message", zap.String("sn", messageDecoded.Sn.String())) // Process RollbackMessage data, err := p.db.Get([]byte("RB"+messageDecoded.Sn.String()), nil) if err != nil { - return nil, nil, "", nil, isRollbackMessage, nil, fmt.Errorf("failed to retrieve stored data: %v", err) + return nil, nil, "", nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) } var storedData StoredMessageData err = json.Unmarshal(data, &storedData) if err != nil { - return nil, nil, "", nil, isRollbackMessage, nil, fmt.Errorf("failed to unmarshal stored data: %v", err) + return nil, nil, "", nil, fmt.Errorf("failed to unmarshal stored rollback message data: %v", err) } decodedData = &MessageDecoded{ Action: storedData.ActionMethod, @@ -742,7 +737,7 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, m decodedData = data if err != nil { p.logger.Error("failed to decode message: %v", zap.Error(err)) - return nil, nil, "", nil, isRollbackMessage, nil, err + return nil, nil, "", nil, err } scripts, _ := multisig.CreateBridgeMessageScripts(opreturnData, 76) for _, script := range scripts { @@ -752,11 +747,11 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, m } } default: - return nil, nil, "", nil, isRollbackMessage, nil, fmt.Errorf("unknown event type: %s", message.EventType) + return nil, nil, "", nil, fmt.Errorf("unknown event type: %s", message.EventType) } inputs, msgTx, hexRawTx, txSigHashes, err := p.CreateBitcoinMultisigTx(outputs, feeRate, decodedData, msWallet) - return inputs, msgTx, hexRawTx, txSigHashes, isRollbackMessage, rollbackSn, err + return inputs, msgTx, hexRawTx, txSigHashes, err } // call the smart contract to send the message @@ -1127,14 +1122,15 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err TokenAddress: messageInfo.TokenAddress, } + p.logger.Info("Stored message for rollback case", zap.Any("storedData", storedData)) data, err = json.Marshal(storedData) if err != nil { - return nil, fmt.Errorf("failed to marshal stored data: %v", err) + return nil, fmt.Errorf("failed to marshal stored rollback message data: %v", err) } err = p.db.Put([]byte("RB"+sn.String()), data, nil) if err != nil { - return nil, fmt.Errorf("failed to store message data: %v", err) + return nil, fmt.Errorf("failed to store rollback message data: %v", err) } return relayMessage, nil } diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index d770686e..fbd26de8 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -4,6 +4,7 @@ import ( "encoding/json" "io" "net/http" + "strings" relayTypes "github.com/icon-project/centralized-relay/relayer/types" "go.uber.org/zap" @@ -70,13 +71,18 @@ func buildAndSignTxFromDbMessage(sn string, p *Provider) ([][]byte, error) { return nil, err } + if strings.Contains(sn, "RB") { + p.logger.Info("Rollback message", zap.String("sn", sn)) + return nil, nil + } + var message *relayTypes.Message err = json.Unmarshal(data, &message) if err != nil { return nil, err } - _, _, _, relayerSigns, _, _, err := p.HandleBitcoinMessageTx(message) + _, _, _, relayerSigns, err := p.HandleBitcoinMessageTx(message) if err != nil { return nil, err } From b0582f09af94362810db2a78b328d16b23fad37a Mon Sep 17 00:00:00 2001 From: Shall Date: Mon, 30 Sep 2024 10:29:44 +0700 Subject: [PATCH 075/113] feat: change logic to get multisig by order --- relayer/chains/bitcoin/master.go | 10 ++++++++-- relayer/chains/bitcoin/provider.go | 13 ++++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index 27d7a898..1dfd9476 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -71,7 +71,10 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(response) } -func requestPartialSign(apiKey string, url string, slaveRequestData []byte, responses chan<- [][]byte, wg *sync.WaitGroup) { +func requestPartialSign(apiKey string, url string, slaveRequestData []byte, responses chan<- struct { + order int + sigs [][]byte +}, order int, wg *sync.WaitGroup) { defer wg.Done() client := &http.Client{} @@ -101,5 +104,8 @@ func requestPartialSign(apiKey string, url string, slaveRequestData []byte, resp fmt.Println("err Unmarshal: ", err) } - responses <- sigs + responses <- struct { + order int + sigs [][]byte + }{order: order, sigs: sigs} } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index c271ff04..6643086f 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -182,21 +182,24 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri func (p *Provider) CallSlaves(slaveRequestData []byte) [][][]byte { resultChan := make(chan [][][]byte) go func() { - responses := make(chan [][]byte, 2) + responses := make(chan struct { + order int + sigs [][]byte + }, 2) var wg sync.WaitGroup wg.Add(2) - go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer1, slaveRequestData, responses, &wg) - go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer2, slaveRequestData, responses, &wg) + go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer1, slaveRequestData, responses, 1, &wg) + go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer2, slaveRequestData, responses, 2, &wg) go func() { wg.Wait() close(responses) }() - var results [][][]byte + results := make([][][]byte, 2) for res := range responses { - results = append(results, res) + results[res.order-1] = res.sigs } resultChan <- results }() From 50d7fc593e17bdcde99c07ba3a59b48b3907e5cb Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Fri, 4 Oct 2024 20:25:23 +0700 Subject: [PATCH 076/113] clean bitcoin tx code --- go.mod | 9 +- go.sum | 851 +++++++++++++- relayer/chains/bitcoin/decode_test.go | 40 - relayer/chains/bitcoin/helper.go | 77 -- relayer/chains/bitcoin/provider.go | 227 ++-- relayer/chains/bitcoin/provider_route_test.go | 588 ++++------ utils/multisig/bridge_script.go | 198 ++++ utils/multisig/bridge_tx.go | 99 ++ utils/multisig/constants.go | 9 +- utils/multisig/multisig_test.go | 1022 ++--------------- utils/multisig/op_message.go | 492 -------- utils/multisig/structure.go | 31 +- utils/multisig/test_utils.go | 79 -- utils/multisig/tx.go | 326 ++---- utils/multisig/utils.go | 4 +- 15 files changed, 1686 insertions(+), 2366 deletions(-) create mode 100644 utils/multisig/bridge_script.go create mode 100644 utils/multisig/bridge_tx.go delete mode 100644 utils/multisig/op_message.go delete mode 100644 utils/multisig/test_utils.go diff --git a/go.mod b/go.mod index 3c534cfc..4492fe06 100644 --- a/go.mod +++ b/go.mod @@ -12,10 +12,10 @@ require ( github.com/cosmos/cosmos-sdk v0.50.8 github.com/cosmos/relayer/v2 v2.5.2 github.com/ethereum/go-ethereum v1.14.7 - github.com/gin-gonic/gin v1.8.1 github.com/gofrs/flock v0.8.1 github.com/gorilla/websocket v1.5.3 github.com/icon-project/goloop v1.3.11 + github.com/icon-project/icon-bridge v0.0.11 github.com/json-iterator/go v1.1.12 github.com/jsternberg/zap-logfmt v1.3.0 github.com/pkg/errors v0.9.1 @@ -27,6 +27,7 @@ require ( golang.org/x/sync v0.7.0 google.golang.org/grpc v1.64.0 gopkg.in/yaml.v3 v3.0.1 + lukechampine.com/uint128 v1.3.0 ) @@ -50,7 +51,6 @@ require ( 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 - github.com/cespare/cp v1.1.1 // indirect github.com/cockroachdb/fifo v0.0.0-20240606204812-0bbfbd93a7ce // indirect github.com/cosmos/ibc-go/v8 v8.3.2 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect @@ -60,15 +60,12 @@ require ( github.com/evalphobia/logrus_fluent v0.5.4 // indirect github.com/fluent/fluent-logger-golang v1.9.0 // indirect github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 // indirect - github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-kit/log v0.2.1 // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.1 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.11.1 // indirect - github.com/goccy/go-json v0.10.2 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -95,7 +92,6 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/tinylib/msgp v1.1.9 // indirect github.com/tyler-smith/go-bip39 v1.1.0 // indirect - github.com/ugorji/go/codec v1.2.11 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/vmihailenco/msgpack/v4 v4.3.13 // indirect @@ -115,7 +111,6 @@ require ( gopkg.in/go-playground/validator.v9 v9.31.0 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - lukechampine.com/uint128 v1.3.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 351f0eb5..6b2c46d4 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,14 @@ +cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= @@ -59,6 +62,7 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigquery v1.42.0/go.mod h1:8dRTJxhtG+vwBKzE5OseQn/hiydoQN3EedCaOdYmxRA= +cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= cloud.google.com/go/billing v1.4.0/go.mod h1:g9IdKBEFlItS8bTtlrZdVLWSSdSyFUZKXNS02zKMOZY= cloud.google.com/go/billing v1.5.0/go.mod h1:mztb1tBc3QekhjSgmpf/CV4LzWXLzCArwpLmP2Gm88s= cloud.google.com/go/binaryauthorization v1.1.0/go.mod h1:xwnoWu3Y84jbuHa0zd526MJYmtnVXn0syOjaJgy4+dM= @@ -100,6 +104,7 @@ cloud.google.com/go/domains v0.6.0/go.mod h1:T9Rz3GasrpYk6mEGHh4rymIhjlnIuB4ofT1 cloud.google.com/go/domains v0.7.0/go.mod h1:PtZeqS1xjnXuRPKE/88Iru/LdfoRyEHYA9nFQf4UKpg= cloud.google.com/go/edgecontainer v0.1.0/go.mod h1:WgkZ9tp10bFxqO8BLPqv2LlfmQF1X8lZqwW4r1BTajk= cloud.google.com/go/edgecontainer v0.2.0/go.mod h1:RTmLijy+lGpQ7BXuTDa4C4ssxyXT34NIuHIgKuP4s5w= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/functions v1.6.0/go.mod h1:3H1UA3qiIPRWD7PeZKLvHZ9SaQhR26XIJcC0A5GbvAk= cloud.google.com/go/functions v1.7.0/go.mod h1:+d+QBcWM+RsrgZfV9xo6KfA1GlzJfxcfZcRPEhDDfzg= cloud.google.com/go/gaming v1.5.0/go.mod h1:ol7rGcxP/qHTRQE/RO4bxkXq+Fix0j6D4LFPzYTIrDM= @@ -186,6 +191,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= +collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= +contrib.go.opencensus.io/exporter/prometheus v0.1.0/go.mod h1:cGFniUXGZlKRjzOyuZJ6mgB+PgBcCIa79kEKR8YCW+A= contrib.go.opencensus.io/exporter/prometheus v0.4.2 h1:sqfsYl5GIY/L570iT+l93ehxaWJs2/OwXtiWwew3oAg= contrib.go.opencensus.io/exporter/prometheus v0.4.2/go.mod h1:dvEHbiKmgvbr5pjaF9fpw1KeYcjrnC1J8B+JKjsZyRQ= cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= @@ -225,63 +232,102 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= +github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/CosmWasm/wasmd v0.52.0 h1:VRylqes1AMXqIgz/jUH9EzhjBZKsRXrrjCTAni0ILRM= github.com/CosmWasm/wasmd v0.52.0/go.mod h1:hyy1wt7c589Cs4kOK2cYdtphzCd2Xo20q/t7tfby7oI= github.com/CosmWasm/wasmvm/v2 v2.1.0 h1:bleLhNA36hM8iPjFJsNRi9RjrQW6MtXafw2+wVjAWAE= github.com/CosmWasm/wasmvm/v2 v2.1.0/go.mod h1:bMhLQL4Yp9CzJi9A83aR7VO9wockOsSlZbT4ztOl6bg= +github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible h1:qSG2N4FghB1He/r2mFrWKCaL7dXCilEuNEeAn20fdD4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= +github.com/MuhammedIrfan/testify-mock v0.0.0-20220912121829-185fc90cd1b6/go.mod h1:VQGYR98EwSYg7KCoLAS0kKaPN27Iydp6i8ifKxIbQfY= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/Workiva/go-datastructures v1.0.50/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg= 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= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= -github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/aristanetworks/goarista v0.0.0-20190607111240-52c2a7864a08/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.30.1/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.44.76/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.44.122/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go v1.53.2 h1:KhTx/eMkavqkpmrV+aBc+bWADSTzwKxTXOvGmRImgFs= github.com/aws/aws-sdk-go v1.53.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= github.com/aws/aws-sdk-go-v2 v1.26.0 h1:/Ce4OCiM3EkpW7Y+xUnfAFpchU78K7/Ug01sZni9PgA= github.com/aws/aws-sdk-go-v2 v1.26.0/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I= +github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= github.com/aws/aws-sdk-go-v2/config v1.27.9 h1:gRx/NwpNEFSk+yQlgmk1bmxxvQ5TyJ76CWXs9XScTqg= github.com/aws/aws-sdk-go-v2/config v1.27.9/go.mod h1:dK1FQfpwpql83kbD873E9vz4FyAxuJtR22wzoXn3qq0= +github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= github.com/aws/aws-sdk-go-v2/credentials v1.17.9 h1:N8s0/7yW+h8qR8WaRlPQeJ6czVMNQVNtNdUqf6cItao= github.com/aws/aws-sdk-go-v2/credentials v1.17.9/go.mod h1:446YhIdmSV0Jf/SLafGZalQo+xr2iw7/fzXGDPTU1yQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0 h1:af5YzcLf80tv4Em4jWVD75lpnOHSBkPUZxZfGkrI3HI= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.0/go.mod h1:nQ3how7DMnFMWiU1SpECohgC82fpn4cKZ875NDMmwtA= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.4 h1:0ScVK/4qZ8CIW0k8jOeFVsyS/sAiXpYxRBLolMkuLQM= @@ -292,18 +338,26 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7 github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6 h1:b+E7zIUHMmcB4Dckjpkapoy47W6C9QBv/zoUP+Hn8Kc= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.6/go.mod h1:S2fNV0rxrP78NhPbCZeQgY8H9jdDMeGtwcfZIRxzBqU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0 h1:yS0JkEdV6h9JOo8sy2JSpjX+i7vsKifU8SIeHrqiDhU= github.com/aws/aws-sdk-go-v2/service/kms v1.30.0/go.mod h1:+I8VUUSVD4p5ISQtzpgSva4I8cJ4SQ4b1dcBcof7O+g= +github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= +github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= github.com/aws/aws-sdk-go-v2/service/sso v1.20.3 h1:mnbuWHOcM70/OFUlZZ5rcdfA8PflGXXiefU/O+1S3+8= github.com/aws/aws-sdk-go-v2/service/sso v1.20.3/go.mod h1:5HFu51Elk+4oRBZVxmHrSds5jFXmFj8C3w7DVF2gnrs= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3 h1:uLq0BKatTmDzWa/Nu4WO0M1AaQDaPpwTKAeByEc6WFM= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.3/go.mod h1:b+qdhjnxj8GSR6t5YfphOffeoQSQ1KmpoVVuBn+PWxs= +github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= github.com/aws/aws-sdk-go-v2/service/sts v1.28.5 h1:J/PpTf/hllOjx8Xu9DMflff3FajfLxqM5+tepvVXmxg= github.com/aws/aws-sdk-go-v2/service/sts v1.28.5/go.mod h1:0ih0Z83YDH/QeQ6Ori2yGE2XvWYv/Xm+cZc01LC6oK0= +github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw= github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/beevik/ntp v0.3.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NRpg= +github.com/benbjohnson/clock v1.0.2/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 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= @@ -314,13 +368,25 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s= github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/biter777/countries v1.3.4/go.mod h1:1HSpZ526mYqKJcpT5Ti1kcGQ0L0SrXWIaptUWjFfv2E= github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE= github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= +github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= +github.com/bombsimon/wsl v1.2.5/go.mod h1:43lEF/i0kpXbLCeDXL9LMT8c92HyBywXb0AsgMHYngM= +github.com/bombsimon/wsl/v2 v2.0.0/go.mod h1:mf25kr/SqFEPhhcxW1+7pxzGlW+hIl/hYTKY95VwV8U= +github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= github.com/btcsuite/btcd v0.24.0 h1:gL3uHE/IaFj6fcZSu03SvqPMSx7s/dPzfpG/atRwWdo= @@ -339,7 +405,9 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6 github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= @@ -353,13 +421,16 @@ github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28 github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE= github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9 h1:vQzL9/RqazAbUe0o5OwVCMIQllDl1Nfzvx2JYcwGurI= github.com/bxelab/runestone v0.0.0-20240428164824-a36ade29b6f9/go.mod h1:pieyLaoNj2JsfnMzZm9McEZmGU804aTBsRQNTwqeqVk= +github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU= github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= @@ -383,6 +454,8 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= +github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -410,22 +483,30 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coinbase/rosetta-sdk-go v0.4.6/go.mod h1:Luv0AhzZH81eul2hYZ3w0hBGwmFPiexwbntYxihEZck= github.com/cometbft/cometbft v0.38.10 h1:2ePuglchT+j0Iao+cfmt/nw5U7K2lnGDzXSUPGVdXaU= github.com/cometbft/cometbft v0.38.10/go.mod h1:jHPx9vQpWzPHEAiYI/7EDKaB1NXhK6o3SArrrY8ExKc= github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= +github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= +github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg= github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAKs= @@ -458,6 +539,7 @@ github.com/cosmos/relayer/v2 v2.5.2/go.mod h1:h4Ng2QsVpxExIq5S+WvLr8slDb9MSBh82g github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c h1:uQYC5Z1mdLRPrZhHjHxufI8+2UG/i25QG92j0Er9p6I= @@ -466,13 +548,23 @@ github.com/crate-crypto/go-kzg-4844 v1.0.0 h1:TsSgHwrkTKecKJ4kadtHi4b3xHW5dCFUDF github.com/crate-crypto/go-kzg-4844 v1.0.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/danieljoos/wincred v1.2.1 h1:dl9cBrupW8+r5250DYkYxocLeZ1Y4vB1kxgtjxw8GQs= github.com/danieljoos/wincred v1.2.1/go.mod h1:uGaFL9fDn3OLTvzCGulzE+SzjEe5NGlh5FdCcyfPwps= +github.com/dave/dst v0.23.1/go.mod h1:LjPcLEauK4jC5hQ1fE/wr05O41zK91Pr4Qs22Ljq7gs= +github.com/dave/gopackages v0.0.0-20170318123100-46e7023ec56e/go.mod h1:i00+b/gKdIDIxuLDFob7ustLAVqhsZRk2qVZrArELGQ= +github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/dave/kerr v0.0.0-20170318121727-bc25dd6abe8e/go.mod h1:qZqlPyPvfsDJt+3wHJ1EvSXDuVjFTK0j2p/ca+gtsb8= +github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWEmXBA= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidlazar/go-crypto v0.0.0-20170701192655-dcfb0a7ac018/go.mod h1:rQYf4tfk5sSwFsnDg3qYaBxSjsD9S8+59vW0dKUgme4= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM= github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= @@ -482,35 +574,58 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= +github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ= +github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= +github.com/dgraph-io/badger v1.6.1/go.mod h1:FRmFw3uxvcpa8zG3Rxs0th+hCLIuaQg8HlNV5bjgnuU= +github.com/dgraph-io/badger v1.6.2/go.mod h1:JW2yswe3V058sS0kZ2h/AXeDSqFjxnZcRrVH//y2UQE= +github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= github.com/dgraph-io/badger/v2 v2.2007.4 h1:TRWBQg8UrlUhaFdco01nO2uXwzKS7zd+HVdwV/GHc4o= github.com/dgraph-io/badger/v2 v2.2007.4/go.mod h1:vSw/ax2qojzbN6eXHIx6KPKtCSHJN/Uz0X0VPruTIhk= +github.com/dgraph-io/ristretto v0.0.2/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= +github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= +github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY= github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/emicklei/dot v1.6.1 h1:ujpDlBkkwgWUY+qPId5IwapRW/xEoligRSYjioR6DFI= github.com/emicklei/dot v1.6.1/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s= +github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -524,35 +639,54 @@ github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go. github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/c-kzg-4844 v1.0.2 h1:8tV84BCEiPeOkiVgW9mpYBeBUir2bkCNVqxPwwVeO+s= github.com/ethereum/c-kzg-4844 v1.0.2/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0= +github.com/ethereum/go-ethereum v1.4.0/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= +github.com/ethereum/go-ethereum v1.9.21/go.mod h1:RXAVzbGrSGmDkDnHymruTAIEjUR3E4TX0EOpaj702sI= +github.com/ethereum/go-ethereum v1.9.23/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= +github.com/ethereum/go-ethereum v1.10.16/go.mod h1:Anj6cxczl+AHy63o4X9O8yWNHuN5wMpfb8MAnHkWn7Y= github.com/ethereum/go-ethereum v1.14.7 h1:EHpv3dE8evQmpVEQ/Ne2ahB06n2mQptdwqaMNhAT29g= github.com/ethereum/go-ethereum v1.14.7/go.mod h1:Mq0biU2jbdmKSZoqOj29017ygFrMnB5/Rifwp980W4o= github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 h1:KrE8I4reeVvf7C1tm8elRjj4BdscTYzz/WAbYyf/JI4= github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0/go.mod h1:D9AJLVXSyZQXJQVk8oh1EwjISE+sJTn2duYIZC0dy3w= github.com/evalphobia/logrus_fluent v0.5.4 h1:G4BSBTm7+L+oanWfFtA/A5Y3pvL2OMxviczyZPYO5xc= github.com/evalphobia/logrus_fluent v0.5.4/go.mod h1:hasyj+CXm3BDP1YhFk/rnTcjlegyqvkokV9A25cQsaA= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.0-20180929194037-2a09253e352a/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.2 h1:27txuSD9or+NZlnOWdKUxeBzTAUkWCVh+4Gf2dWFOzA= github.com/fjl/memsize v0.0.2/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fluent/fluent-logger-golang v1.4.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= github.com/fluent/fluent-logger-golang v1.9.0 h1:zUdY44CHX2oIUc7VTNZc+4m+ORuO/mldQDA7czhWXEg= github.com/fluent/fluent-logger-golang v1.9.0/go.mod h1:2/HCT/jTy78yGyeNGQLGQsjF3zzzAuy6Xlk6FCMV5eU= +github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/garslo/gogen v0.0.0-20170307003452-d6ebae628c7c/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= +github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays= github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= +github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -561,6 +695,13 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= +github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= +github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= +github.com/go-critic/go-critic v0.3.5-0.20190904082202-d79a9f0c64db/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA= +github.com/go-critic/go-critic v0.4.0/go.mod h1:7/14rZGnZbY6E38VEGk2kVhoq6itzc1E68facVDK23g= +github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -575,6 +716,7 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= @@ -586,25 +728,46 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= +github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= +github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg= +github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= +github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= +github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk= +github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI= +github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks= +github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= +github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= @@ -618,8 +781,12 @@ github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MG github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -630,15 +797,20 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/gddo v0.0.0-20200831202555-721e228c7686/go.mod h1:sam69Hju0uq+5uvLJUMDlsKlQ21Vrs1Kd/1YFPNYdOU= +github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -669,15 +841,38 @@ github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= +github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk= +github.com/golangci/errcheck v0.0.0-20181223084120-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0= +github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= +github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o= +github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU= +github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= +github.com/golangci/golangci-lint v1.21.0/go.mod h1:phxpHK52q7SE+5KpPnti4oZTdFCEsn/tKN+nFvCKXfk= +github.com/golangci/golangci-lint v1.22.2/go.mod h1:2Bj42k6hPQFTRxkDb7S3TQ+EsnumZXOmIYNqlQrp0FI= +github.com/golangci/ineffassign v0.0.0-20190609212857-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU= +github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= +github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= +github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= +github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= +github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI= +github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4= +github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= +github.com/google/addlicense v0.0.0-20200827091314-d1655b921368/go.mod h1:EMjYTRimagHs1FwlIqKyX3wAM0u3rA+McvlIIWmSamA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -697,8 +892,11 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= +github.com/google/gopacket v1.1.18/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= @@ -708,6 +906,7 @@ github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9 github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20181127221834-b4f47329b966/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -728,7 +927,9 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -737,6 +938,7 @@ github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -755,24 +957,46 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= +github.com/gosuri/uitable v0.0.0-20160404203958-36ee7e946282/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= +github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= +github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/haltingstate/secp256k1-go v0.0.0-20151224084235-572209b26df6/go.mod h1:73mKQiY8bLnscfGakn57WAJZTzT0eSUAy3qgMQNR/DI= +github.com/harmony-ek/gencodec v0.0.0-20190215044613-e6740dbdd846/go.mod h1:YZcPnufUw70msUSudLvxcQOSpnZJgaMS9WIU8IGEtBg= +github.com/harmony-one/abool v1.0.1/go.mod h1:9sq0PJzb1SqRpKrpEV4Ttvm9WV5uud8sfrsPw3AIBJA= +github.com/harmony-one/bls v0.0.6/go.mod h1:ML9osB/z3hR9WAYZVj7qH+IP6oaPRPmshDbxrQyia7g= +github.com/harmony-one/harmony v1.10.2/go.mod h1:QsUfRGisvY6k1KvpzVeBI3VBdHhYLlpVQTEbzrMmw1U= +github.com/harmony-one/taggedrlp v0.1.4/go.mod h1:osO5TRXLKdgCP+oj2J9qfqhywMOOA+4nP5q+o8nDSYA= +github.com/harmony-one/vdf v0.0.0-20190924175951-620379da8849/go.mod h1:EgNU7X5HLNBBho+OqCm1A1NrpD6xb1SHfi9pMCYaKKw= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE= @@ -792,6 +1016,7 @@ github.com/hashicorp/go-metrics v0.5.3 h1:M5uADWMOGCTUNU1YuC4hfknOeHNaX54LDm4oYS github.com/hashicorp/go-metrics v0.5.3/go.mod h1:KEjodfebIOuBYSAe/bHTm+HChmKSxAOXPBieMLYozDE= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-plugin v1.5.2 h1:aWv8eimFqWlsEiMrYZdPYl+FdHaBJSN4AWwGWfT1G2Y= github.com/hashicorp/go-plugin v1.5.2/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= @@ -810,10 +1035,13 @@ github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09 github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -828,6 +1056,8 @@ github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4 h1:X4egAf/gcS1zATw6w github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4/go.mod h1:5GuXa7vkL8u9FkFuWdVvfR5ix8hRB7DbOAaYULamFpc= github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.3.0 h1:4wdcm/tnd0xXdu7iS3ruNvxkWwrb4aeBQv19ayYn8F4= github.com/holiman/uint256 v1.3.0/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -836,27 +1066,96 @@ github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0Jr github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw= github.com/huandu/skiplist v1.2.0/go.mod h1:7v3iFjLcSAzO4fN5B8dvebvo/qsfumiLiDXMrPiHF9w= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/hugobyte/keygen v0.1.0/go.mod h1:9xV3yxKUwIy54jw2IRtFikoEhTUurO8ZSEiS7IC5aLA= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goupnp v1.3.0 h1:UvLUlWDNpoUdYzb2TCn+MuTWtcjXKSza2n6CBdQ0xXc= github.com/huin/goupnp v1.3.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFckNX8= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/icon-project/goloop v1.2.11/go.mod h1:P7mwPMmoAWFXdt0KmlrsQkRV9Qw1JswoCKqfTBpXYCw= github.com/icon-project/goloop v1.3.11 h1:Lry7rCM9QeZudiAqi7n7CqmoOsg7qNDwrw6O12j7vuo= github.com/icon-project/goloop v1.3.11/go.mod h1:9PoWRb5kowidc9jYy0RLuLpay1zT5FXgEKijx7rDQjE= +github.com/icon-project/icon-bridge v0.0.11 h1:1qUYq6YmzUQR+zCDJGnXQxXKs81NmkxATtOr8KEx4Wc= +github.com/icon-project/icon-bridge v0.0.11/go.mod h1:7GcN+biPaXdsYLvsiwC1Y/5ro6ENPinhUqm2MZL4tgQ= github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= +github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= +github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= +github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= +github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= +github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= +github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= +github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= +github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= +github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM= +github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M= +github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog= +github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I= +github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE= +github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw= +github.com/ipfs/go-datastore v0.4.0/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.1/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.4/go.mod h1:SX/xMIKoCszPqp+z9JhPYCmoOoXTvaa13XEbGtsFUhA= +github.com/ipfs/go-datastore v0.4.5/go.mod h1:eXTcaaiN6uOlVCLS9GjJUJtlvJfM3xk23w3fyfrmmJs= +github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps= +github.com/ipfs/go-ds-badger v0.0.2/go.mod h1:Y3QpeSFWQf6MopLTiZD+VT6IC1yZqaGmjvRcKeSGij8= +github.com/ipfs/go-ds-badger v0.0.5/go.mod h1:g5AuuCGmr7efyzQhLL8MzwqcauPojGPUaHzfGTzuE3s= +github.com/ipfs/go-ds-badger v0.0.7/go.mod h1:qt0/fWzZDoPW6jpQeqUjR5kBfhDNB65jd9YlmAvpQBk= +github.com/ipfs/go-ds-badger v0.2.1/go.mod h1:Tx7l3aTph3FMFrRS838dcSJh+jjA7cX9DrGVwx/NOwE= +github.com/ipfs/go-ds-badger v0.2.3/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-badger v0.2.4/go.mod h1:pEYw0rgg3FIrywKKnL+Snr+w/LjJZVMTBRn4FS6UHUk= +github.com/ipfs/go-ds-leveldb v0.0.1/go.mod h1:feO8V3kubwsEF22n0YRQCffeb79OOYIykR4L04tMOYc= +github.com/ipfs/go-ds-leveldb v0.1.0/go.mod h1:hqAW8y4bwX5LWcCtku2rFNX3vjDZCy5LZCg+cSZvYb8= +github.com/ipfs/go-ds-leveldb v0.4.1/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= +github.com/ipfs/go-ds-leveldb v0.4.2/go.mod h1:jpbku/YqBSsBc1qgME8BkWS4AxzF2cEu1Ii2r79Hh9s= +github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw= +github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc= +github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ= +github.com/ipfs/go-ipns v0.0.2/go.mod h1:WChil4e0/m9cIINWLxZe1Jtf77oz5L05rO2ei/uKJ5U= +github.com/ipfs/go-log v0.0.1/go.mod h1:kL1d2/hzSpI0thNYjiKfjanbVNU+IIGA/WnNESY9leM= +github.com/ipfs/go-log v1.0.2/go.mod h1:1MNjMxe0u6xvJZgeqbJ8vdo2TKaGwZ1a0Bpza+sr2Sk= +github.com/ipfs/go-log v1.0.3/go.mod h1:OsLySYkwIbiSUR/yBTdv1qPtcE4FW3WPWk/ewz9Ru+A= +github.com/ipfs/go-log v1.0.4/go.mod h1:oDCg2FkjogeFOhqqb+N39l2RpTNPL6F/StPkB3kPgcs= +github.com/ipfs/go-log/v2 v2.0.2/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.3/go.mod h1:O7P1lJt27vWHhOwQmcFEvlmo49ry2VY2+JfBWFaa9+0= +github.com/ipfs/go-log/v2 v2.0.5/go.mod h1:eZs4Xt4ZUJQFM3DlanGhy7TkwwawCZcSByscwkWG+dw= +github.com/ipfs/go-log/v2 v2.1.1/go.mod h1:2v2nsGfZsvvAJz13SyFzf9ObaqwHiHxsPLEHntrv9KM= +github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= +github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus= github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs= +github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA= +github.com/jbenet/go-temp-err-catcher v0.0.0-20150120210811-aac704a3f4f2/go.mod h1:8GXXJV31xl8whumTzdZsTt3RnUIiPqzkyf7mxToRCMs= +github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk= +github.com/jbenet/goprocess v0.0.0-20160826012719-b497e2f366b8/go.mod h1:Ly/wlsjFq/qrU3Rar62tu1gASgGw6chQbSh/XgIIXCY= +github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls= github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= @@ -866,6 +1165,7 @@ github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/jroimartin/gocui v0.4.0/go.mod h1:7i7bbj99OgFHzo7kB2zPb8pXLqMBSQegY7azfqXMkyY= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -876,63 +1176,273 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= github.com/jsternberg/zap-logfmt v1.3.0 h1:z1n1AOHVVydOOVuyphbOKyR4NICDQFiJMn1IK5hVQ5Y= github.com/jsternberg/zap-logfmt v1.3.0/go.mod h1:N3DENp9WNmCZxvkBD/eReWwz1149BK6jEN9cQ4fNwZE= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +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/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= 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/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM= github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= +github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= +github.com/labstack/echo/v4 v4.6.1/go.mod h1:RnjgMWNDB9g/HucVWhQYNQP9PvbYf6adqftqryo7s9k= +github.com/labstack/echo/v4 v4.9.0/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks= github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM= github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk= github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= +github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ= +github.com/libp2p/go-addr-util v0.0.2/go.mod h1:Ecd6Fb3yIuLzq4bD7VcywcVSBtefcAwnUISBM3WG15E= +github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic= +github.com/libp2p/go-conn-security-multistream v0.1.0/go.mod h1:aw6eD7LOsHEX7+2hJkDxw1MteijaVcI+/eP2/x3J1xc= +github.com/libp2p/go-conn-security-multistream v0.2.0/go.mod h1:hZN4MjlNetKD3Rq5Jb/P5ohUnFLNzEAR4DLSzpn2QLU= +github.com/libp2p/go-eventbus v0.1.0/go.mod h1:vROgu5cs5T7cv7POWlWxBaVLxfSegC5UGQf8A2eEmx4= +github.com/libp2p/go-eventbus v0.2.1/go.mod h1:jc2S4SoEVPP48H9Wpzm5aiGwUCBMfGhVhhBjyhhCJs8= +github.com/libp2p/go-flow-metrics v0.0.1/go.mod h1:Iv1GH0sG8DtYN3SVJ2eG221wMiNpZxBdp967ls1g+k8= +github.com/libp2p/go-flow-metrics v0.0.2/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-flow-metrics v0.0.3/go.mod h1:HeoSNUrOJVK1jEpDqVEiUOIXqhbnS27omG0uWU5slZs= +github.com/libp2p/go-libp2p v0.6.1/go.mod h1:CTFnWXogryAHjXAKEbOf1OWY+VeAP3lDMZkfEI5sT54= +github.com/libp2p/go-libp2p v0.7.0/go.mod h1:hZJf8txWeCduQRDC/WSqBGMxaTHCOYHt2xSU1ivxn0k= +github.com/libp2p/go-libp2p v0.7.4/go.mod h1:oXsBlTLF1q7pxr+9w6lqzS1ILpyHsaBPniVO7zIHGMw= +github.com/libp2p/go-libp2p v0.8.1/go.mod h1:QRNH9pwdbEBpx5DTJYg+qxcVaDMAz3Ee/qDKwXujH5o= +github.com/libp2p/go-libp2p v0.12.0/go.mod h1:FpHZrfC1q7nA8jitvdjKBDF31hguaC676g/nT9PgQM0= +github.com/libp2p/go-libp2p v0.13.0/go.mod h1:pM0beYdACRfHO1WcJlp65WXyG2A6NqYM+t2DTVAJxMo= +github.com/libp2p/go-libp2p-asn-util v0.0.0-20200825225859-85005c6cf052/go.mod h1:nRMRTab+kZuk0LnKZpxhOVH/ndsdr2Nr//Zltc/vwgo= +github.com/libp2p/go-libp2p-autonat v0.1.1/go.mod h1:OXqkeGOY2xJVWKAGV2inNF5aKN/djNA3fdpCWloIudE= +github.com/libp2p/go-libp2p-autonat v0.2.0/go.mod h1:DX+9teU4pEEoZUqR1PiMlqliONQdNbfzE1C718tcViI= +github.com/libp2p/go-libp2p-autonat v0.2.1/go.mod h1:MWtAhV5Ko1l6QBsHQNSuM6b1sRkXrpk0/LqCr+vCVxI= +github.com/libp2p/go-libp2p-autonat v0.2.2/go.mod h1:HsM62HkqZmHR2k1xgX34WuWDzk/nBwNHoeyyT4IWV6A= +github.com/libp2p/go-libp2p-autonat v0.4.0/go.mod h1:YxaJlpr81FhdOv3W3BTconZPfhaYivRdf53g+S2wobk= +github.com/libp2p/go-libp2p-blankhost v0.1.1/go.mod h1:pf2fvdLJPsC1FsVrNP3DUUvMzUts2dsLLBEpo1vW1ro= +github.com/libp2p/go-libp2p-blankhost v0.1.4/go.mod h1:oJF0saYsAXQCSfDq254GMNmLNz6ZTHTOvtF4ZydUvwU= +github.com/libp2p/go-libp2p-blankhost v0.2.0/go.mod h1:eduNKXGTioTuQAUcZ5epXi9vMl+t4d8ugUBRQ4SqaNQ= +github.com/libp2p/go-libp2p-circuit v0.1.4/go.mod h1:CY67BrEjKNDhdTk8UgBX1Y/H5c3xkAcs3gnksxY7osU= +github.com/libp2p/go-libp2p-circuit v0.2.1/go.mod h1:BXPwYDN5A8z4OEY9sOfr2DUQMLQvKt/6oku45YUmjIo= +github.com/libp2p/go-libp2p-circuit v0.4.0/go.mod h1:t/ktoFIUzM6uLQ+o1G6NuBl2ANhBKN9Bc8jRIk31MoA= +github.com/libp2p/go-libp2p-connmgr v0.2.4/go.mod h1:YV0b/RIm8NGPnnNWM7hG9Q38OeQiQfKhHCCs1++ufn0= +github.com/libp2p/go-libp2p-core v0.0.1/go.mod h1:g/VxnTZ/1ygHxH3dKok7Vno1VfpvGcGip57wjTU4fco= +github.com/libp2p/go-libp2p-core v0.0.4/go.mod h1:jyuCQP356gzfCFtRKyvAbNkyeuxb7OlyhWZ3nls5d2I= +github.com/libp2p/go-libp2p-core v0.2.0/go.mod h1:X0eyB0Gy93v0DZtSYbEM7RnMChm9Uv3j7yRXjO77xSI= +github.com/libp2p/go-libp2p-core v0.2.2/go.mod h1:8fcwTbsG2B+lTgRJ1ICZtiM5GWCWZVoVrLaDRvIRng0= +github.com/libp2p/go-libp2p-core v0.2.4/go.mod h1:STh4fdfa5vDYr0/SzYYeqnt+E6KfEV5VxfIrm0bcI0g= +github.com/libp2p/go-libp2p-core v0.2.5/go.mod h1:6+5zJmKhsf7yHn1RbmYDu08qDUpIUxGdqHuEZckmZOA= +github.com/libp2p/go-libp2p-core v0.3.0/go.mod h1:ACp3DmS3/N64c2jDzcV429ukDpicbL6+TrrxANBjPGw= +github.com/libp2p/go-libp2p-core v0.3.1/go.mod h1:thvWy0hvaSBhnVBaW37BvzgVV68OUhgJJLAa6almrII= +github.com/libp2p/go-libp2p-core v0.4.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.0/go.mod h1:49XGI+kc38oGVwqSBhDEwytaAxgZasHhFfQKibzTls0= +github.com/libp2p/go-libp2p-core v0.5.1/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.3/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.4/go.mod h1:uN7L2D4EvPCvzSH5SrhR72UWbnSGpt5/a35Sm4upn4Y= +github.com/libp2p/go-libp2p-core v0.5.5/go.mod h1:vj3awlOr9+GMZJFH9s4mpt9RHHgGqeHCopzbYKZdRjM= +github.com/libp2p/go-libp2p-core v0.5.6/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.5.7/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.0/go.mod h1:txwbVEhHEXikXn9gfC7/UDDw7rkxuX0bJvM49Ykaswo= +github.com/libp2p/go-libp2p-core v0.6.1/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.7.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-core v0.8.0/go.mod h1:FfewUH/YpvWbEB+ZY9AQRQ4TAD8sJBt/G1rVvhz5XT8= +github.com/libp2p/go-libp2p-crypto v0.1.0/go.mod h1:sPUokVISZiy+nNuTTH/TY+leRSxnFj/2GLjtOTW90hI= +github.com/libp2p/go-libp2p-discovery v0.2.0/go.mod h1:s4VGaxYMbw4+4+tsoQTqh7wfxg97AEdo4GYBt6BadWg= +github.com/libp2p/go-libp2p-discovery v0.3.0/go.mod h1:o03drFnz9BVAZdzC/QUQ+NeQOu38Fu7LJGEOK2gQltw= +github.com/libp2p/go-libp2p-discovery v0.5.0/go.mod h1:+srtPIU9gDaBNu//UHvcdliKBIcr4SfDcm0/PfPJLug= +github.com/libp2p/go-libp2p-kad-dht v0.11.1/go.mod h1:5ojtR2acDPqh/jXf5orWy8YGb8bHQDS+qeDcoscL/PI= +github.com/libp2p/go-libp2p-kbucket v0.4.7/go.mod h1:XyVo99AfQH0foSf176k4jY1xUJ2+jUJIZCSDm7r2YKk= +github.com/libp2p/go-libp2p-loggables v0.1.0/go.mod h1:EyumB2Y6PrYjr55Q3/tiJ/o3xoDasoRYM7nOzEpoa90= +github.com/libp2p/go-libp2p-mplex v0.2.0/go.mod h1:Ejl9IyjvXJ0T9iqUTE1jpYATQ9NM3g+OtR+EMMODbKo= +github.com/libp2p/go-libp2p-mplex v0.2.1/go.mod h1:SC99Rxs8Vuzrf/6WhmH41kNn13TiYdAWNYHrwImKLnE= +github.com/libp2p/go-libp2p-mplex v0.2.2/go.mod h1:74S9eum0tVQdAfFiKxAyKzNdSuLqw5oadDq7+L/FELo= +github.com/libp2p/go-libp2p-mplex v0.2.3/go.mod h1:CK3p2+9qH9x+7ER/gWWDYJ3QW5ZxWDkm+dVvjfuG3ek= +github.com/libp2p/go-libp2p-mplex v0.3.0/go.mod h1:l9QWxRbbb5/hQMECEb908GbS9Sm2UAR2KFZKUJEynEs= +github.com/libp2p/go-libp2p-mplex v0.4.0/go.mod h1:yCyWJE2sc6TBTnFpjvLuEJgTSw/u+MamvzILKdX7asw= +github.com/libp2p/go-libp2p-mplex v0.4.1/go.mod h1:cmy+3GfqfM1PceHTLL7zQzAAYaryDu6iPSC+CIb094g= +github.com/libp2p/go-libp2p-nat v0.0.5/go.mod h1:1qubaE5bTZMJE+E/uu2URroMbzdubFz1ChgiN79yKPE= +github.com/libp2p/go-libp2p-nat v0.0.6/go.mod h1:iV59LVhB3IkFvS6S6sauVTSOrNEANnINbI/fkaLimiw= +github.com/libp2p/go-libp2p-netutil v0.1.0/go.mod h1:3Qv/aDqtMLTUyQeundkKsA+YCThNdbQD54k3TqjpbFU= +github.com/libp2p/go-libp2p-noise v0.1.1/go.mod h1:QDFLdKX7nluB7DEnlVPbz7xlLHdwHFA9HiohJRr3vwM= +github.com/libp2p/go-libp2p-peer v0.2.0/go.mod h1:RCffaCvUyW2CJmG2gAWVqwePwW7JMgxjsHm7+J5kjWY= +github.com/libp2p/go-libp2p-peerstore v0.1.0/go.mod h1:2CeHkQsr8svp4fZ+Oi9ykN1HBb6u0MOvdJ7YIsmcwtY= +github.com/libp2p/go-libp2p-peerstore v0.1.3/go.mod h1:BJ9sHlm59/80oSkpWgr1MyY1ciXAXV397W6h1GH/uKI= +github.com/libp2p/go-libp2p-peerstore v0.1.4/go.mod h1:+4BDbDiiKf4PzpANZDAT+knVdLxvqh7hXOujessqdzs= +github.com/libp2p/go-libp2p-peerstore v0.2.0/go.mod h1:N2l3eVIeAitSg3Pi2ipSrJYnqhVnMNQZo9nkSCuAbnQ= +github.com/libp2p/go-libp2p-peerstore v0.2.1/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.2/go.mod h1:NQxhNjWxf1d4w6PihR8btWIRjwRLBr4TYKfNgrUkOPA= +github.com/libp2p/go-libp2p-peerstore v0.2.6/go.mod h1:ss/TWTgHZTMpsU/oKVVPQCGuDHItOpf2W8RxAi50P2s= +github.com/libp2p/go-libp2p-pnet v0.2.0/go.mod h1:Qqvq6JH/oMZGwqs3N1Fqhv8NVhrdYcO0BW4wssv21LA= +github.com/libp2p/go-libp2p-pubsub v0.4.0/go.mod h1:izkeMLvz6Ht8yAISXjx60XUQZMq9ZMe5h2ih4dLIBIQ= +github.com/libp2p/go-libp2p-record v0.1.2/go.mod h1:pal0eNcT5nqZaTV7UGhqeGqxFgGdsU/9W//C8dqjQDk= +github.com/libp2p/go-libp2p-record v0.1.3/go.mod h1:yNUff/adKIfPnYQXgp6FQmNu3gLJ6EMg7+/vv2+9pY4= +github.com/libp2p/go-libp2p-routing-helpers v0.2.3/go.mod h1:795bh+9YeoFl99rMASoiVgHdi5bjack0N1+AFAdbvBw= +github.com/libp2p/go-libp2p-secio v0.1.0/go.mod h1:tMJo2w7h3+wN4pgU2LSYeiKPrfqBgkOsdiKK77hE7c8= +github.com/libp2p/go-libp2p-secio v0.2.0/go.mod h1:2JdZepB8J5V9mBp79BmwsaPQhRPNN2NrnB2lKQcdy6g= +github.com/libp2p/go-libp2p-secio v0.2.1/go.mod h1:cWtZpILJqkqrSkiYcDBh5lA3wbT2Q+hz3rJQq3iftD8= +github.com/libp2p/go-libp2p-secio v0.2.2/go.mod h1:wP3bS+m5AUnFA+OFO7Er03uO1mncHG0uVwGrwvjYlNY= +github.com/libp2p/go-libp2p-swarm v0.1.0/go.mod h1:wQVsCdjsuZoc730CgOvh5ox6K8evllckjebkdiY5ta4= +github.com/libp2p/go-libp2p-swarm v0.2.2/go.mod h1:fvmtQ0T1nErXym1/aa1uJEyN7JzaTNyBcHImCxRpPKU= +github.com/libp2p/go-libp2p-swarm v0.2.3/go.mod h1:P2VO/EpxRyDxtChXz/VPVXyTnszHvokHKRhfkEgFKNM= +github.com/libp2p/go-libp2p-swarm v0.2.8/go.mod h1:JQKMGSth4SMqonruY0a8yjlPVIkb0mdNSwckW7OYziM= +github.com/libp2p/go-libp2p-swarm v0.3.0/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.3.1/go.mod h1:hdv95GWCTmzkgeJpP+GK/9D9puJegb7H57B5hWQR5Kk= +github.com/libp2p/go-libp2p-swarm v0.4.0/go.mod h1:XVFcO52VoLoo0eitSxNQWYq4D6sydGOweTOAjJNraCw= +github.com/libp2p/go-libp2p-testing v0.0.2/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.3/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.0.4/go.mod h1:gvchhf3FQOtBdr+eFUABet5a4MBLK8jM3V4Zghvmi+E= +github.com/libp2p/go-libp2p-testing v0.1.0/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.1/go.mod h1:xaZWMJrPUM5GlDBxCeGUi7kI4eqnjVyavGroI2nxEM0= +github.com/libp2p/go-libp2p-testing v0.1.2-0.20200422005655-8775583591d8/go.mod h1:Qy8sAncLKpwXtS2dSnDOP8ktexIAHKu+J+pnZOFZLTc= +github.com/libp2p/go-libp2p-testing v0.3.0/go.mod h1:efZkql4UZ7OVsEfaxNHZPzIehtsBXMrXnCfJIgDti5g= +github.com/libp2p/go-libp2p-testing v0.4.0/go.mod h1:Q+PFXYoiYFN5CAEG2w3gLPEzotlKsNSbKQ/lImlOWF0= +github.com/libp2p/go-libp2p-tls v0.1.3/go.mod h1:wZfuewxOndz5RTnCAxFliGjvYSDA40sKitV4c50uI1M= +github.com/libp2p/go-libp2p-transport-upgrader v0.1.1/go.mod h1:IEtA6or8JUbsV07qPW4r01GnTenLW4oi3lOPbUMGJJA= +github.com/libp2p/go-libp2p-transport-upgrader v0.2.0/go.mod h1:mQcrHj4asu6ArfSoMuyojOdjx73Q47cYD7s5+gZOlns= +github.com/libp2p/go-libp2p-transport-upgrader v0.3.0/go.mod h1:i+SKzbRnvXdVbU3D1dwydnTmKRPXiAR/fyvi1dXuL4o= +github.com/libp2p/go-libp2p-transport-upgrader v0.4.0/go.mod h1:J4ko0ObtZSmgn5BX5AmegP+dK3CSnU2lMCKsSq/EY0s= +github.com/libp2p/go-libp2p-yamux v0.2.0/go.mod h1:Db2gU+XfLpm6E4rG5uGCFX6uXA8MEXOxFcRoXUODaK8= +github.com/libp2p/go-libp2p-yamux v0.2.2/go.mod h1:lIohaR0pT6mOt0AZ0L2dFze9hds9Req3OfS+B+dv4qw= +github.com/libp2p/go-libp2p-yamux v0.2.5/go.mod h1:Zpgj6arbyQrmZ3wxSZxfBmbdnWtbZ48OpsfmQVTErwA= +github.com/libp2p/go-libp2p-yamux v0.2.7/go.mod h1:X28ENrBMU/nm4I3Nx4sZ4dgjZ6VhLEn0XhIoZ5viCwU= +github.com/libp2p/go-libp2p-yamux v0.2.8/go.mod h1:/t6tDqeuZf0INZMTgd0WxIRbtK2EzI2h7HbFm9eAKI4= +github.com/libp2p/go-libp2p-yamux v0.4.0/go.mod h1:+DWDjtFMzoAwYLVkNZftoucn7PelNoy5nm3tZ3/Zw30= +github.com/libp2p/go-libp2p-yamux v0.5.0/go.mod h1:AyR8k5EzyM2QN9Bbdg6X1SkVVuqLwTGf0L4DFq9g6po= +github.com/libp2p/go-libp2p-yamux v0.5.1/go.mod h1:dowuvDu8CRWmr0iqySMiSxK+W0iL5cMVO9S94Y6gkv4= +github.com/libp2p/go-maddr-filter v0.0.4/go.mod h1:6eT12kSQMA9x2pvFQa+xesMKUBlj9VImZbj3B9FBH/Q= +github.com/libp2p/go-maddr-filter v0.0.5/go.mod h1:Jk+36PMfIqCJhAnaASRH83bdAvfDRp/w6ENFaC9bG+M= +github.com/libp2p/go-maddr-filter v0.1.0/go.mod h1:VzZhTXkMucEGGEOSKddrwGiOv0tUhgnKqNEmIAz/bPU= +github.com/libp2p/go-mplex v0.0.3/go.mod h1:pK5yMLmOoBR1pNCqDlA2GQrdAVTMkqFalaTWe7l4Yd0= +github.com/libp2p/go-mplex v0.1.0/go.mod h1:SXgmdki2kwCUlCCbfGLEgHjC4pFqhTp0ZoV6aiKgxDU= +github.com/libp2p/go-mplex v0.1.1/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= +github.com/libp2p/go-mplex v0.1.2/go.mod h1:Xgz2RDCi3co0LeZfgjm4OgUF15+sVR8SRcu3SFXI1lk= +github.com/libp2p/go-mplex v0.2.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-mplex v0.3.0/go.mod h1:0Oy/A9PQlwBytDRp4wSkFnzHYDKcpLot35JQ6msjvYQ= +github.com/libp2p/go-msgio v0.0.2/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.4/go.mod h1:63lBBgOTDKQL6EWazRMCwXsEeEeK9O2Cd+0+6OOuipQ= +github.com/libp2p/go-msgio v0.0.6/go.mod h1:4ecVB6d9f4BDSL5fqvPiC4A3KivjWn+Venn/1ALLMWA= +github.com/libp2p/go-nat v0.0.4/go.mod h1:Nmw50VAvKuk38jUBcmNh6p9lUJLoODbJRvYAa/+KSDo= +github.com/libp2p/go-nat v0.0.5/go.mod h1:B7NxsVNPZmRLvMOwiEO1scOSyjA56zxYAGv1yQgRkEU= +github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-netroute v0.1.3/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk= +github.com/libp2p/go-openssl v0.0.2/go.mod h1:v8Zw2ijCSWBQi8Pq5GAixw6DbFfa9u6VIYDXnvOXkc0= +github.com/libp2p/go-openssl v0.0.3/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.4/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.5/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-openssl v0.0.7/go.mod h1:unDrJpgy3oFr+rqXsarWifmJuNnJR4chtO1HmaZjggc= +github.com/libp2p/go-reuseport v0.0.1/go.mod h1:jn6RmB1ufnQwl0Q1f+YxAj8isJgDCQzaaxIFYDhcYEA= +github.com/libp2p/go-reuseport v0.0.2/go.mod h1:SPD+5RwGC7rcnzngoYC86GjPzjSywuQyMVAheVBD9nQ= +github.com/libp2p/go-reuseport-transport v0.0.2/go.mod h1:YkbSDrvjUVDL6b8XqriyA20obEtsW9BLkuOUyQAOCbs= +github.com/libp2p/go-reuseport-transport v0.0.3/go.mod h1:Spv+MPft1exxARzP2Sruj2Wb5JSyHNncjf1Oi2dEbzM= +github.com/libp2p/go-reuseport-transport v0.0.4/go.mod h1:trPa7r/7TJK/d+0hdBLOCGvpQQVOU74OXbNCIMkufGw= +github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k= +github.com/libp2p/go-stream-muxer v0.0.1/go.mod h1:bAo8x7YkSpadMTbtTaxGVHWUQsR/l5MEaHbKaliuT14= +github.com/libp2p/go-stream-muxer-multistream v0.2.0/go.mod h1:j9eyPol/LLRqT+GPLSxvimPhNph4sfYfMoDPd7HkzIc= +github.com/libp2p/go-stream-muxer-multistream v0.3.0/go.mod h1:yDh8abSIzmZtqtOt64gFJUXEryejzNb0lisTt+fAMJA= +github.com/libp2p/go-tcp-transport v0.1.0/go.mod h1:oJ8I5VXryj493DEJ7OsBieu8fcg2nHGctwtInJVpipc= +github.com/libp2p/go-tcp-transport v0.1.1/go.mod h1:3HzGvLbx6etZjnFlERyakbaYPdfjg2pWP97dFZworkY= +github.com/libp2p/go-tcp-transport v0.2.0/go.mod h1:vX2U0CnWimU4h0SGSEsg++AzvBcroCGYw28kh94oLe0= +github.com/libp2p/go-tcp-transport v0.2.1/go.mod h1:zskiJ70MEfWz2MKxvFB/Pv+tPIB1PpPUrHIWQ8aFw7M= +github.com/libp2p/go-ws-transport v0.2.0/go.mod h1:9BHJz/4Q5A9ludYWKoGCFC5gUElzlHoKzu0yY9p/klM= +github.com/libp2p/go-ws-transport v0.3.0/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= +github.com/libp2p/go-ws-transport v0.3.1/go.mod h1:bpgTJmRZAvVHrgHybCVyqoBmyLQ1fiZuEaBYusP5zsk= +github.com/libp2p/go-ws-transport v0.4.0/go.mod h1:EcIEKqf/7GDjth6ksuS/6p7R49V4CBY6/E7R/iyhYUA= +github.com/libp2p/go-yamux v1.2.2/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.0/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow= +github.com/libp2p/go-yamux v1.3.7/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux v1.4.0/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux v1.4.1/go.mod h1:fr7aVgmdNGJK+N1g+b6DW6VxzbRCjCOejR/hkmpooHE= +github.com/libp2p/go-yamux/v2 v2.0.0/go.mod h1:NVWira5+sVUIU6tu1JWvaRn1dRnG+cawOJiflsAM+7U= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/linxGnu/grocksdb v1.8.14 h1:HTgyYalNwBSG/1qCQUIott44wU5b2Y9Kr3z7SK5OfGQ= github.com/linxGnu/grocksdb v1.8.14/go.mod h1:QYiYypR2d4v63Wj1adOOfzglnoII0gLj3PNh4fZkcFA= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -940,25 +1450,43 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= +github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.28/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= +github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.0.0-20190328051042-05b4dd3047e5/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.0/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U= +github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= +github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A= @@ -973,14 +1501,65 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mozilla/tls-observatory v0.0.0-20190404164649-a3c1b6cfecfd/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk= +github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.1/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8= +github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= +github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA= +github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM= +github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.0/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44= +github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= +github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= +github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE= +github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y= +github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI= +github.com/multiformats/go-multiaddr v0.3.1/go.mod h1:uPbspcUPd5AfaP6ql3ujFY+QWzmBD8uLLL4bXW0XfGc= +github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q= +github.com/multiformats/go-multiaddr-dns v0.2.0/go.mod h1:TJ5pr5bBO7Y1B18djPuRsVkduhQH2YqYSbxWJzYGdK0= +github.com/multiformats/go-multiaddr-fmt v0.0.1/go.mod h1:aBYjqL4T/7j4Qx+R73XSv/8JsgnRFlf0w2KGLCmXl3Q= +github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo= +github.com/multiformats/go-multiaddr-net v0.0.1/go.mod h1:nw6HSxNmCIQH27XPGBuX+d1tnvM7ihcFwHMSstNAVUU= +github.com/multiformats/go-multiaddr-net v0.1.0/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.1/go.mod h1:5JNbcfBOP4dnhoZOv10JJVkJO0pCCEf8mTnipAo2UZQ= +github.com/multiformats/go-multiaddr-net v0.1.2/go.mod h1:QsWt3XK/3hwvNxZJp92iMQKME1qHfpYmyIjFVsSOY6Y= +github.com/multiformats/go-multiaddr-net v0.1.3/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.1.4/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysjCu4PVONlrBZpHIrw/qQuA= +github.com/multiformats/go-multiaddr-net v0.2.0/go.mod h1:gGdH3UXny6U3cKKYCvpXI5rnK7YaOIEOPVDI9tsJbEA= +github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs= +github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc= +github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U= +github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po= +github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew= +github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc= +github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg= +github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38= +github.com/multiformats/go-multistream v0.2.0/go.mod h1:5GZPQZbkWOLOn3J2y4Y99vVW7vOfsAflxARk3x14o6k= +github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= +github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE= github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8= github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= @@ -988,7 +1567,10 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/near/borsh-go v0.3.1/go.mod h1:NeMochZp7jN/pYFuxLkrZtmLqbADmnp/y1+/dL+AsyQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nsf/termbox-go v0.0.0-20190325093121-288510b9734e/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -998,11 +1580,18 @@ github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtb github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= @@ -1011,7 +1600,10 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042 github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= @@ -1027,7 +1619,9 @@ github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJ github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= @@ -1038,14 +1632,20 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67 h1:jik8PHtAIsPlCRJjJzl4udgEf7hawInF9texMeO2jrU= github.com/petermattis/goid v0.0.0-20231207134359-e60b3f734c67/go.mod h1:pxMtw7cyUw6B2bRH0ZBANSPg+AoSud1I1iyJHI69jH4= +github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= @@ -1058,16 +1658,20 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= @@ -1082,11 +1686,16 @@ github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= @@ -1095,10 +1704,13 @@ github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJ github.com/prometheus/common v0.52.2 h1:LW8Vk7BccEdONfrJBDffQGRtpSzi5CQaRZGtboOO2ck= github.com/prometheus/common v0.52.2/go.mod h1:lrWtQx+iDfn2mbH5GUzlH9TSHyfZpHkSiG1W7y3sF2Q= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= @@ -1108,26 +1720,39 @@ github.com/prometheus/procfs v0.13.0/go.mod h1:cd4PFCR54QLnGKPaKGA6l+cfuNXtht43Z github.com/prometheus/statsd_exporter v0.22.7/go.mod h1:N/TevpjkIh9ccs6nuzY3jQn9dFqnUakOjnEuMPJJJnI= github.com/prometheus/statsd_exporter v0.26.0 h1:SQl3M6suC6NWQYEzOvIv+EF6dAMYEqIuZy+o4H9F5Ig= github.com/prometheus/statsd_exporter v0.26.0/go.mod h1:GXFLADOmBTVDrHc7b04nX8ooq3azG61pnECNqT7O5DM= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/reactivex/rxgo/v2 v2.5.0/go.mod h1:bs4fVZxcb5ZckLIOeIeVH942yunJLWDABWGbrHAW+qU= github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.6.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo= github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I= github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= @@ -1144,10 +1769,23 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0 github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/securego/gosec v0.0.0-20191002120514-e680875ea14d/go.mod h1:w5+eXa0mYznDkHaMCXA4XYffjlH+cy1oyKbfzJXa2Do= +github.com/segmentio/golines v0.0.0-20200824192126-7f30d3046793/go.mod h1:bQSh5qdVR67XiCKbaVvYO41s50c5hQo+3cY/1CQQ3xQ= +github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shamaton/msgpack/v2 v2.2.0 h1:IP1m01pHwCrMa6ZccP9B3bqxEMKMSmMVAVKk54g3L/Y= github.com/shamaton/msgpack/v2 v2.2.0/go.mod h1:6khjYnkx73f7VQU7wjcFS9DFjs+59naVWJv1TB7qdOI= +github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= +github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -1157,42 +1795,61 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE= +github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0= +github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -1208,27 +1865,49 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stvp/go-udp-testing v0.0.0-20201019212854-469649b16807/go.mod h1:7jxmlfBCDBXRzr0eAQJ48XC1hBu1np4CS5+cHEYfwpc= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/supranational/blst v0.3.12 h1:Vfas2U2CFHhniv2QkUm2OVa1+pGTdqtpqm9NnhUUbZ8= github.com/supranational/blst v0.3.12/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= +github.com/teivah/onecontext v0.0.0-20200513185103-40f981bfd775/go.mod h1:XUZ4x3oGhWfiOnUvTslnKKs39AWUct3g3yJvXTQSJOQ= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tidwall/btree v1.7.0 h1:L1fkJH/AuEh5zBnnBbmTwQ5Lt+bRJ5A8EWecslvo9iI= github.com/tidwall/btree v1.7.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= +github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls= +github.com/tidwall/gjson v1.6.1/go.mod h1:BaHyNc5bjzYkPqgLq7mdVzeiRtULKULXLgZFKsxEHI0= +github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.1/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.1.1/go.mod h1:yvVuSnpEQv5cYIrO+AT6kw4QVfd5SDZoGIS7/5+fZFs= +github.com/timakin/bodyclose v0.0.0-20190930140734-f7f2e9bca95e/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= +github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= +github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU= github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k= +github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= +github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tommy-muehle/go-mnd v1.1.1/go.mod h1:dSUh0FtTP8VhvkL1S+gUR1OKd9ZnSaozuI6r3m6wOig= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= @@ -1237,21 +1916,44 @@ github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.12 h1:37Nm15o69RwBkXM0J6A5OlE67RZTfzUxTj8fB3dfcsc= github.com/ulikunitz/xz v0.5.12/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= +github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/uudashr/gocognit v0.0.0-20190926065955-1655d0de0517/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= +github.com/uudashr/gocognit v1.0.1/go.mod h1:j44Ayx2KW4+oB6SWMv8KsmHzZrOInQav7D3cQMJ5JUM= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4= +github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/vmihailenco/msgpack/v4 v4.3.11/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v4 v4.3.13 h1:A2wsiTbvp63ilDaWmsk2wjx6xZdxQOvpiNlKBGKKXKI= github.com/vmihailenco/msgpack/v4 v4.3.13/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/msgpack/v5 v5.0.0-beta.1/go.mod h1:xlngVLeyQ/Qi05oQxhQ+oTuqa03RjMwMfk/7/TCs+QI= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmihailenco/tagparser v0.1.2 h1:gnjoVuB/kljJ5wICEEOpx98oXMWPLj22G67Vbd1qPqc= github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/whyrusleeping/go-keyspace v0.0.0-20160322163242-5b898ac5add1/go.mod h1:8UvriyWtv5Q5EOgjHaSseUEdkQfvwFv1I/In/O2M9gc= +github.com/whyrusleeping/go-logging v0.0.0-20170515211332-0457bb6b88fc/go.mod h1:bopw91TMyo8J3tvftk8xmU2kPmlrt4nScJQZU2hE5EM= +github.com/whyrusleeping/go-logging v0.0.1/go.mod h1:lDPYj54zutzG1XYfHAhcc7oNXEburHQBn+Iqd4yS4vE= +github.com/whyrusleeping/mafmt v1.2.8/go.mod h1:faQJFPbLSxzD9xpA02ttW/tS9vZykNvXwGvqIpk20FA= +github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4= +github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI= +github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg= +github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= @@ -1263,10 +1965,12 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= @@ -1275,6 +1979,7 @@ go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1298,39 +2003,68 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/arch v0.0.0-20180920145803-b19384d3c130/go.mod h1:cYlCBUl1MsqxdiKgmc4uh7TxZfWSFLOGSRR090WDxt8= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200423211502-4bdfaf469ed5/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/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-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= @@ -1341,6 +2075,7 @@ golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMk golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1357,10 +2092,12 @@ golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPI golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -1371,6 +2108,8 @@ golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73r 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= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1378,16 +2117,19 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1405,11 +2147,13 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -1417,6 +2161,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210913180222-943fd674d43e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1432,6 +2178,7 @@ golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfS golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1459,6 +2206,7 @@ golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1477,8 +2225,10 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1486,26 +2236,37 @@ golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190219092855-153ac476189d/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190526052359-791d8a0f4d09/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191024172528-b4ff53e7a1cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1525,8 +2286,12 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1536,8 +2301,11 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1548,10 +2316,13 @@ golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1581,6 +2352,7 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.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= @@ -1599,40 +2371,66 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181127232545-e782529d0ddd/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181130052023-1c3d964395ce/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190221204921-83362c3779f5/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190719005602-e377ae9d6386/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190924052046-3ac2a5bbd98a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190930201159-7c411dea38b0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191024220359-3d91e92cde03/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113232020-e2727e816f5a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1649,7 +2447,10 @@ golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729181040-64cdafbe085c/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200731060945-b5fad4ed8dd6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= @@ -1666,6 +2467,7 @@ 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/gopls v0.4.4/go.mod h1:zhyGzA+CAtREUwwq/btQxEx2FHnGzDwJvGs5YqdVCbE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1676,6 +2478,13 @@ golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNq golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= +gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1737,6 +2546,7 @@ google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= +google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -1744,6 +2554,7 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1751,6 +2562,7 @@ google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= @@ -1850,6 +2662,7 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1: google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= +google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -1864,6 +2677,7 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= @@ -1925,15 +2739,24 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v9 v9.28.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= +gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= +gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1941,6 +2764,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= @@ -1949,6 +2773,7 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1959,13 +2784,22 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +mvdan.cc/gofumpt v0.0.0-20200709182408-4fd085cb6d5f/go.mod h1:9VQ397fNXEnF84t90W4r4TRCQK+pg9f8ugVfyj+S26w= +mvdan.cc/gofumpt v0.0.0-20200802201014-ab5a8192947d/go.mod h1:bzrjFmaD6+xqohD3KYP0H2FEuxknnBmyyOxdhLdaIws= +mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc= +mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4= +mvdan.cc/unparam v0.0.0-20190720180237-d51796306d8f/go.mod h1:4G1h5nDURzA3bwVMZIVpwbkw+04kSxk3rAtzlimaUJw= +mvdan.cc/xurls/v2 v2.2.0/go.mod h1:EV1RMtya9D6G5DMYPGD8zTQzaHet6Jh8gFlRgGRJeO8= nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= @@ -1974,3 +2808,4 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index 602c4552..63564c7b 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -3,14 +3,11 @@ package bitcoin import ( "encoding/hex" "fmt" - "github.com/ethereum/go-ethereum/common" - "github.com/icon-project/centralized-relay/utils/multisig" "log" "os" "testing" "github.com/icon-project/icon-bridge/common/codec" - "github.com/stretchr/testify/assert" ) func TestDecode(t *testing.T) { @@ -64,40 +61,3 @@ func TestGetRuneBalanceAtIndex(t *testing.T) { fmt.Printf("%+v", res) } - -func TestEncodeToXcallMessage(t *testing.T) { - // - test1 := multisig.RadFiProvideLiquidityMsg{ - Detail: &multisig.RadFiProvideLiquidityDetail{ - Fee: 30, - UpperTick: -173940, - LowerTick: -178320, - Min0: 0, - Min1: 0, - }, - } - - protocols := []string{ - "0x932e088453515720B8eD50c1999C4Bc7bc11991F", - "0x526C5Bcd376FAD738780e099E9723A62044D0319", - } - - res, err := ToXCallMessage( - test1, - "0x3.BTC/bc1qvqkshkdj67uwvlwschyq8wja6df4juhewkg5fg", - "0x2a68F967bFA230780a385175d0c86AE4048d3096", - 2, - protocols, - common.HexToAddress("0x000013938B55EDFBF3380656CC321770cCF470E1"), - common.HexToAddress("0x66f2A9220C8479d73eE84df0932f38C496e8E9e3"), - common.HexToAddress("0x7a4a1aF7B59c5FF522D5F11336d5b20d5116c7cb"), - ) - if err != nil { - log.Fatal(err.Error()) - } - - resReadable := hex.EncodeToString(res) - fmt.Printf("%+v", resReadable) - - assert.Equal(t, resReadable, "f902a201b9029ef9029bb23078332e4254432f6263317176716b73686b646a36377577766c77736368797138776a61366466346a756865776b67356667aa3078326136384639363762464132333037383061333835313735643063383641453430343864333039360200b901e0000000000000000000000000000013938b55edfbf3380656cc321770ccf470e1000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001648831645600000000000000000000000066f2a9220c8479d73ee84df0932f38c496e8e9e30000000000000000000000007a4a1af7b59c5ff522d5f11336d5b20d5116c7cb0000000000000000000000000000000000000000000000000000000000000bb8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd4770fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd588c0000000000000000000000000000000000000000000fb768105935a2f1a5b649000000000000000000000000000000000000000000000000077cf984c325302e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a68f967bfa230780a385175d0c86ae4048d3096000000000000000000000000000000000000000000000000000000003b9aca0000000000000000000000000000000000000000000000000000000000f856aa307839333265303838343533353135373230423865443530633139393943344263376263313139393146aa307835323643354263643337364641443733383738306530393945393732334136323034344430333139") -} diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index ea3f41f3..f766620e 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -7,13 +7,7 @@ import ( "math/big" "net/http" "strconv" - "strings" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - - bitcoinABI "github.com/icon-project/centralized-relay/relayer/chains/bitcoin/abi" - "github.com/icon-project/centralized-relay/utils/multisig" "github.com/icon-project/icon-bridge/common/codec" ) @@ -52,77 +46,6 @@ func GetRuneTxIndex(endpoint, method, bearToken, txId string, index int) (*RuneT return resp, nil } -func ToXCallMessage(data interface{}, from, to string, sn uint, protocols []string, requester, token0, token1 common.Address) ([]byte, error) { - var res []byte - - //bitcoinStateAbi, _ := abi.JSON(strings.NewReader(bitcoinABI.BitcoinStateMetaData.ABI)) - nonfungibleABI, _ := abi.JSON(strings.NewReader(bitcoinABI.InonfungibleTokenMetaData.ABI)) - addressTy, _ := abi.NewType("address", "", nil) - bytes, _ := abi.NewType("bytes", "", nil) - - arguments := abi.Arguments{ - { - Type: addressTy, - }, - { - Type: bytes, - }, - } - - amount0, _ := big.NewInt(0).SetString("18999999999999999977305673", 10) - - switch data.(type) { - case multisig.RadFiProvideLiquidityMsg: - dataMint := data.(multisig.RadFiProvideLiquidityMsg) - mintParams := bitcoinABI.INonfungiblePositionManagerMintParams{ - Token0: token0, - Token1: token1, - Fee: big.NewInt(int64(dataMint.Detail.Fee) * 100), - TickLower: big.NewInt(int64(dataMint.Detail.LowerTick)), - TickUpper: big.NewInt(int64(dataMint.Detail.UpperTick)), - Amount0Desired: amount0, - Amount1Desired: big.NewInt(539580403982610478), - Recipient: common.HexToAddress(to), - Deadline: big.NewInt(1000000000), - } - - mintParams.Amount0Min = mulDiv(mintParams.Amount0Desired, big.NewInt(int64(dataMint.Detail.Min0)), big.NewInt(1e4)) - mintParams.Amount1Min = mulDiv(mintParams.Amount1Desired, big.NewInt(int64(dataMint.Detail.Min1)), big.NewInt(1e4)) - - // encode - // todo: for init pool - //initPoolCalldata, err := bitcoinStateAbi.Pack("initPool", mintParams, "btc", "rad", 1e0) - //if err != nil { - // return nil, err - //} - - provideLiquidity, err := nonfungibleABI.Pack("mint", mintParams) - if err != nil { - return nil, err - } - - // encode with requester - provideLiquidity, err = arguments.Pack(requester, provideLiquidity) - if err != nil { - return nil, err - } - - //from := "0x3.BTC/bc1qvqkshkdj67uwvlwschyq8wja6df4juhewkg5fg" - // todo: s, extract message type from OP_RETURN DATA - // encode to xcall format - res, err = XcallFormat(provideLiquidity, from, to, sn, protocols, uint8(CALL_MESSAGE_TYPE)) - if err != nil { - return nil, err - } - - case multisig.RadFiWithdrawLiquidityMsg: - - default: - return nil, fmt.Errorf("not supported") - } - return res, nil -} - func XcallFormat(callData []byte, from, to string, sn uint, protocols []string, messType uint8) ([]byte, error) { // csV2 := CSMessageRequestV2{ diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 6643086f..0a356b74 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -11,11 +11,11 @@ import ( "runtime" "slices" "sort" - "strconv" "strings" "sync" "time" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" @@ -45,7 +45,7 @@ var ( MasterMode = "master" SlaveMode = "slave" BtcDB = "btc.db" - MinSatsRequired uint64 = 1000 + MinSatsRequired int64 = 1000 WitnessSize = 385 ) @@ -314,7 +314,7 @@ func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { return withdrawInfo, withdrawInfoWrapperV2.Data, nil } -func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, error) { +func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, timeout uint, addressPkScript []byte) ([]*multisig.Input, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired @@ -322,8 +322,8 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired uint64 if err != nil { return nil, fmt.Errorf("failed to query bitcoin UTXOs from unisat: %v", err) } - outputs := []*multisig.UTXO{} - var totalAmount uint64 + inputs := []*multisig.Input{} + var totalAmount int64 utxos := resp.Data.Utxo // sort utxos by amount in descending order @@ -335,20 +335,20 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired uint64 if totalAmount >= amountRequired { break } - outputAmount := utxo.Satoshi.Uint64() - outputs = append(outputs, &multisig.UTXO{ - IsRelayersMultisig: true, + outputAmount := utxo.Satoshi.Int64() + inputs = append(inputs, &multisig.Input{ TxHash: utxo.TxId, OutputIdx: uint32(utxo.Vout), OutputAmount: outputAmount, + PkScript: addressPkScript, }) totalAmount += outputAmount } - return outputs, nil + return inputs, nil } -func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout uint) ([]*multisig.UTXO, error) { +func GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, timeout uint, addressPkScript []byte) ([]*multisig.Input, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired @@ -363,107 +363,129 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint64, timeout return utxos[i].Satoshi.Cmp(utxos[j].Satoshi) == 1 }) - inputs := []*multisig.UTXO{} - var totalAmount uint64 + inputs := []*multisig.Input{} + var totalAmount uint128.Uint128 for _, utxo := range utxos { - if totalAmount >= amountRequired { + if totalAmount.Cmp(amountRequired) >= 0 { break } - inputs = append(inputs, &multisig.UTXO{ - IsRelayersMultisig: true, + inputs = append(inputs, &multisig.Input{ TxHash: utxo.TxId, OutputIdx: uint32(utxo.Vout), - OutputAmount: utxo.Satoshi.Uint64(), + OutputAmount: utxo.Satoshi.Int64(), + PkScript: addressPkScript, }) if len(utxo.Runes) != 1 { return nil, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) } - runeAmount, _ := strconv.ParseUint(utxo.Runes[0].Amount, 10, 64) - totalAmount += runeAmount + runeAmount, _ := uint128.FromString(utxo.Runes[0].Amount) + totalAmount = totalAmount.Add(runeAmount) } return inputs, nil } func (p *Provider) CreateBitcoinMultisigTx( - outputData []*multisig.OutputTx, - - feeRate uint64, + outputData []*wire.TxOut, + feeRate int64, decodedData *MessageDecoded, msWallet *multisig.MultisigWallet, -) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { +) ([]*multisig.Input, *wire.MsgTx, error) { + // build receiver Pk Script + receiverAddr, err := btcutil.DecodeAddress(decodedData.To, p.chainParam) + if err != nil { + return nil, nil, err + } + receiverPkScript, err := txscript.PayToAddrScript(receiverAddr) + if err != nil { + return nil, nil, err + } // ----- BUILD OUTPUTS ----- - outputs := []*multisig.OutputTx{} - outputs = append(outputs, outputData...) - var bitcoinAmountRequired uint64 - var runeAmountRequired uint64 + var outputs []*wire.TxOut + var bitcoinAmountRequired int64 + var runeAmountRequired uint128.Uint128 rlMsAddress, err := multisig.AddressOnChain(p.chainParam, msWallet) if err != nil { - return nil, nil, "", nil, err + return nil, nil, err } msAddressStr := rlMsAddress.String() // add withdraw output - amount, _ := strconv.ParseUint(string(decodedData.Amount), 10, 64) + amount := new(big.Int).SetBytes(decodedData.Amount) if decodedData.Action == MethodWithdrawTo || decodedData.Action == MethodDeposit { if decodedData.TokenAddress == BTCToken { // transfer btc - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: decodedData.To, - Amount: amount, - }) - - bitcoinAmountRequired = amount + bitcoinAmountRequired = amount.Int64() + outputs = []*wire.TxOut{ + // bitcoin send to receiver + { + Value: bitcoinAmountRequired, + PkScript: receiverPkScript, + }, + } } else { // transfer rune - runeRequired, _ := runestone.RuneIdFromString(decodedData.TokenAddress) - changeOutputId := uint32(len(outputs) + 2) + runeAmountRequired = uint128.FromBig(amount) + runeRequired, err := runestone.RuneIdFromString(decodedData.TokenAddress) + if err != nil { + return nil, nil, err + } + changeOutputId := uint32(1) runeOutput := &runestone.Runestone{ Edicts: []runestone.Edict{ { ID: *runeRequired, - Amount: uint128.FromBytes(decodedData.Amount), - Output: uint32(len(outputs) + 1), + Amount: uint128.FromBig(amount), + Output: 0, }, }, Pointer: &changeOutputId, } - runeScript, _ := runeOutput.Encipher() - // add runestone OP_RETURN - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: runeScript, - }) - // add receiver output - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: decodedData.To, - Amount: MinSatsRequired, - }) - // add change output - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: msAddressStr, - Amount: MinSatsRequired, - }) - runeAmountRequired = amount + runeScript, err := runeOutput.Encipher() + if err != nil { + return nil, nil, err + } + + outputs = []*wire.TxOut{ + // rune send to receiver + { + Value: MinSatsRequired, + PkScript: receiverPkScript, + }, + // rune change output + { + Value: MinSatsRequired, + PkScript: msWallet.PKScript, + }, + // rune OP_RETURN + { + Value: 0, + PkScript: runeScript, + }, + } + bitcoinAmountRequired = MinSatsRequired * 2 } } + outputs = append(outputs, outputData...) // ----- BUILD INPUTS ----- inputs, estFee, err := p.computeTx(feeRate, bitcoinAmountRequired, runeAmountRequired, decodedData.TokenAddress, msAddressStr, outputs, msWallet) if err != nil { - return nil, nil, "", nil, err + return nil, nil, err } // create raw tx - msgTx, hexRawTx, txSigHashes, err := multisig.CreateMultisigTx(inputs, outputs, estFee, msWallet, nil, p.chainParam, msAddressStr, 0) + msgTx, err := multisig.CreateTx(inputs, outputs, msWallet.PKScript, estFee, 0) + // msgTx, hexRawTx, txSigHashes, err := multisig.CreateMultisigTx(inputs, outputs, estFee, msWallet, nil, p.chainParam, msAddressStr, 0) - return inputs, msgTx, hexRawTx, txSigHashes, err + return inputs, msgTx, err } // calculateTxSize calculates the size of a transaction given the inputs, outputs, estimated fee, change address, chain parameters, and multisig wallet. // It returns the size of the transaction in bytes and an error if any occurs during the process. -func (p *Provider) calculateTxSize(inputs []*multisig.UTXO, outputs []*multisig.OutputTx, estFee uint64, changeAddress string, msWallet *multisig.MultisigWallet) (int, error) { - msgTx, _, _, err := multisig.CreateMultisigTx(inputs, outputs, estFee, msWallet, msWallet, p.chainParam, changeAddress, 0) +func (p *Provider) calculateTxSize(inputs []*multisig.Input, outputs []*wire.TxOut, estFee int64, msWallet *multisig.MultisigWallet) (int, error) { + msgTx, err := multisig.CreateTx(inputs, outputs, msWallet.PKScript, estFee, 0) if err != nil { return 0, err } @@ -472,52 +494,52 @@ func (p *Provider) calculateTxSize(inputs []*multisig.UTXO, outputs []*multisig. if err != nil { return 0, err } - txSize := len(rawTxBytes.Bytes()) + WitnessSize + txSize := len(rawTxBytes.Bytes()) + len(inputs)*WitnessSize return txSize, nil } -func (p *Provider) computeTx(feeRate, satsToSend, runeToSend uint64, runeId, changeAddress string, outputs []*multisig.OutputTx, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, uint64, error) { +func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128.Uint128, runeId, address string, outputs []*wire.TxOut, msWallet *multisig.MultisigWallet) ([]*multisig.Input, int64, error) { - outputsCopy := make([]*multisig.OutputTx, len(outputs)) + outputsCopy := make([]*wire.TxOut, len(outputs)) copy(outputsCopy, outputs) - inputs, err := p.selectUnspentUTXOs(satsToSend, runeToSend, runeId, outputsCopy, changeAddress) - sumSelectedOutputs := multisig.SumInputsSat(inputs) + inputs, err := p.selectUnspentUTXOs(satsToSend, runeToSend, runeId, address, msWallet.PKScript) + sumSelectedInputs := multisig.SumInputsSat(inputs) if err != nil { return nil, 0, err } - txSize, err := p.calculateTxSize(inputs, outputsCopy, 0, changeAddress, msWallet) + txSize, err := p.calculateTxSize(inputs, outputsCopy, 0, msWallet) if err != nil { return nil, 0, err } - estFee := uint64(txSize) * feeRate + estFee := int64(txSize) * feeRate count := 0 loopEntered := false - var iterationOutputs []*multisig.OutputTx + var iterationOutputs []*wire.TxOut - for sumSelectedOutputs < satsToSend+estFee { + for sumSelectedInputs < satsToSend+estFee { loopEntered = true // Create a fresh copy of outputs for each iteration - iterationOutputs := make([]*multisig.OutputTx, len(outputs)) + iterationOutputs := make([]*wire.TxOut, len(outputs)) copy(iterationOutputs, outputs) newSatsToSend := satsToSend + estFee var err error - selectedUnspentOutputs, err := p.selectUnspentUTXOs(newSatsToSend, runeToSend, runeId, iterationOutputs, changeAddress) + selectedUnspentInputs, err := p.selectUnspentUTXOs(newSatsToSend, runeToSend, runeId, address, msWallet.PKScript) if err != nil { return nil, 0, err } - sumSelectedOutputs = multisig.SumInputsSat(selectedUnspentOutputs) + sumSelectedInputs = multisig.SumInputsSat(selectedUnspentInputs) - txSize, err := p.calculateTxSize(selectedUnspentOutputs, iterationOutputs, estFee, changeAddress, msWallet) + txSize, err := p.calculateTxSize(selectedUnspentInputs, iterationOutputs, estFee, msWallet) if err != nil { return nil, 0, err } - estFee = feeRate * uint64(txSize) + estFee = feeRate * int64(txSize) count += 1 if count > 500 { @@ -533,12 +555,12 @@ func (p *Provider) computeTx(feeRate, satsToSend, runeToSend uint64, runeId, cha return inputs, estFee, nil } -func (p *Provider) selectUnspentUTXOs(satToSend uint64, runeToSend uint64, runeId string, outputs []*multisig.OutputTx, changeAddress string) ([]*multisig.UTXO, error) { +func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint128, runeId string, address string, addressPkScript []byte) ([]*multisig.Input, error) { // add tx fee the the required bitcoin amount - inputs := []*multisig.UTXO{} - if runeToSend != 0 { + inputs := []*multisig.Input{} + if !runeToSend.IsZero() { // query rune UTXOs from unisat - runeInputs, err := GetRuneUTXOs(p.cfg.UniSatURL, changeAddress, runeId, runeToSend, 3) + runeInputs, err := GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, 3, addressPkScript) if err != nil { return nil, err } @@ -547,7 +569,7 @@ func (p *Provider) selectUnspentUTXOs(satToSend uint64, runeToSend uint64, runeI // TODO: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo // query bitcoin UTXOs from unisat - bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, changeAddress, satToSend, 3) + bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, address, satToSend, 3, addressPkScript) if err != nil { return nil, err } @@ -578,21 +600,7 @@ func (p *Provider) buildMultisigWallet() (*multisig.MultisigWallet, error) { return msWallet, nil } -func (p *Provider) partSignTx(msgTx *wire.MsgTx, inputs []*multisig.UTXO, msWallet *multisig.MultisigWallet, txSigHashes *txscript.TxSigHashes) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: msWallet.PKScript, - RelayersTapLeaf: msWallet.TapLeaves[0], - UserPKScript: []byte{}, - UserTapLeaf: txscript.TapLeaf{}, - } - // relayer sign tx - relayerSigs, err := multisig.PartSignOnRawExternalTx(p.cfg.RelayerPrivKey, msgTx, inputs, tapSigParams, p.chainParam, false) - - return inputs, msWallet, msgTx, relayerSigs, err -} - -func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.UTXO, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { +func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.Input, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { msWallet, err := p.buildMultisigWallet() if err != nil { return nil, nil, nil, nil, err @@ -602,12 +610,16 @@ func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multi p.logger.Error("failed to get recommended fee from mempool", zap.Error(err)) feeRate = 0 } - inputs, msgTx, _, txSigHashes, err := p.buildTxMessage(message, feeRate, msWallet) + inputs, msgTx, err := p.buildTxMessage(message, int64(feeRate), msWallet) if err != nil { p.logger.Error("failed to build tx message: %v", zap.Error(err)) return nil, nil, nil, nil, err } - inputs, msWallet, msgTx, relayerSigs, err := p.partSignTx(msgTx, inputs, msWallet, txSigHashes) + relayerSigs, err := multisig.SignTapMultisig(p.cfg.RelayerPrivKey, msgTx, inputs, msWallet, 0) + if err != nil { + p.logger.Error("failed to sign tx message: %v", zap.Error(err)) + return nil, nil, nil, nil, err + } return inputs, msWallet, msgTx, relayerSigs, err } @@ -646,7 +658,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) totalSigs = append(totalSigs, slaveSigs...) // combine sigs - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, msWallet, 0, msWallet, 0, totalSigs) + signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) if err != nil { p.logger.Error("err combine tx: ", zap.Error(err)) @@ -702,8 +714,8 @@ func (p *Provider) decodeMessage(message *relayTypes.Message) (CSMessageResult, return messageDecoded, nil } -func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, msWallet *multisig.MultisigWallet) ([]*multisig.UTXO, *wire.MsgTx, string, *txscript.TxSigHashes, error) { - outputs := []*multisig.OutputTx{} +func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, msWallet *multisig.MultisigWallet) ([]*multisig.Input, *wire.MsgTx, error) { + outputs := []*wire.TxOut{} decodedData := &MessageDecoded{} switch message.EventType { @@ -718,12 +730,12 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, m // Process RollbackMessage data, err := p.db.Get([]byte("RB"+messageDecoded.Sn.String()), nil) if err != nil { - return nil, nil, "", nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) + return nil, nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) } var storedData StoredMessageData err = json.Unmarshal(data, &storedData) if err != nil { - return nil, nil, "", nil, fmt.Errorf("failed to unmarshal stored rollback message data: %v", err) + return nil, nil, fmt.Errorf("failed to unmarshal stored rollback message data: %v", err) } decodedData = &MessageDecoded{ Action: storedData.ActionMethod, @@ -740,21 +752,22 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate uint64, m decodedData = data if err != nil { p.logger.Error("failed to decode message: %v", zap.Error(err)) - return nil, nil, "", nil, err + return nil, nil, err } - scripts, _ := multisig.CreateBridgeMessageScripts(opreturnData, 76) + scripts, _ := multisig.EncodePayloadToScripts(opreturnData) for _, script := range scripts { - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, + outputs = append(outputs, &wire.TxOut{ + Value: 0, + PkScript: script, }) } } default: - return nil, nil, "", nil, fmt.Errorf("unknown event type: %s", message.EventType) + return nil, nil, fmt.Errorf("unknown event type: %s", message.EventType) } - inputs, msgTx, hexRawTx, txSigHashes, err := p.CreateBitcoinMultisigTx(outputs, feeRate, decodedData, msWallet) - return inputs, msgTx, hexRawTx, txSigHashes, err + inputs, msgTx, err := p.CreateBitcoinMultisigTx(outputs, feeRate, decodedData, msWallet) + return inputs, msgTx, err } // call the smart contract to send the message diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index fa9574f9..7bc06eaf 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -12,7 +12,6 @@ import ( "path/filepath" "testing" - "github.com/btcsuite/btcd/btcec/v2/schnorr" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" @@ -24,7 +23,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/syndtr/goleveldb/leveldb" "go.uber.org/zap" - "lukechampine.com/uint128" +) + +const ( + TX_FEE = 10000 + RELAYER_MULTISIG_ADDRESS = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" + USER_MULTISIG_ADDRESS = "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" ) func TestDecodeWithdrawToMessage(t *testing.T) { @@ -102,21 +106,15 @@ func TestProvider_Route(t *testing.T) { func TestDepositBitcoinToIcon(t *testing.T) { chainParam := &chaincfg.TestNet3Params + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - inputs := []*multisig.UTXO{ - { - IsRelayersMultisig: false, - TxHash: "e57c10e27f75dbf0856163ca5f825b5af7ffbb3874f606b31330464ddd9df9a1", - OutputIdx: 4, - OutputAmount: 2974000, - }, - } - - outputs := []*multisig.OutputTx{} - - // Add Bridge Message - payload, _ := multisig.CreateBridgePayload( - &multisig.XCallMessage{ + bridgeMsg := multisig.BridgeDecodedMsg { + Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", TokenAddress: "0:1", @@ -125,51 +123,41 @@ func TestDepositBitcoinToIcon(t *testing.T) { Amount: new(big.Int).SetUint64(100000).Bytes(), Data: []byte(""), }, - 1, - "cxfc86ee7687e1bf681b5548b2667844485c0e7192", - []string{ + ChainId: 1, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, - ) - scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, - }) } - // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - Amount: 100000, - }) - - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - rlMsAddress, _ := multisig.AddressOnChain(chainParam, userMultisigWallet) - - msAddressStr := rlMsAddress.String() - fmt.Printf(msAddressStr) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 100000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + inputs := []*multisig.Input{ + { + TxHash: "e57c10e27f75dbf0856163ca5f825b5af7ffbb3874f606b31330464ddd9df9a1", + OutputIdx: 4, + OutputAmount: 2974000, + PkScript: userMultisigWallet.PKScript, + }, } + // create tx + msgTx, err := multisig.CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -185,21 +173,24 @@ func TestDepositBitcoinToIcon(t *testing.T) { func TestDepositBitcoinToIconFail1(t *testing.T) { chainParam := &chaincfg.TestNet3Params + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - inputs := []*multisig.UTXO{ + inputs := []*multisig.Input{ { - IsRelayersMultisig: false, TxHash: "eeb8c9f79ecfe7c084b2af95bf82acebd130185a0d188283d78abb58d85eddff", OutputIdx: 4, OutputAmount: 2999000, + PkScript: userMultisigWallet.PKScript, }, } - outputs := []*multisig.OutputTx{} + outputs := []*wire.TxOut{} // Add Bridge Message - payload, _ := multisig.CreateBridgePayload( - &multisig.XCallMessage{ + scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ Action: "Deposit", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", @@ -207,47 +198,31 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { Amount: new(big.Int).SetUint64(1000000).Bytes(), Data: []byte(""), }, - 1, - "cx8b52dfea0aa1e548288102df15ad7159f7266106", - []string{ + ChainId: 1, + Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", + Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, - ) - scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, + }) + for _, script := range scripts { + outputs = append(outputs, &wire.TxOut{ + Value: 0, + PkScript: script, }) } - // Add transfering bitcoin to relayer multisig - // outputs = append(outputs, &multisig.OutputTx{ - // ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - // Amount: 1000000, - // }) - - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - + msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + fmt.Println("err: ", err) + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -263,21 +238,27 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { func TestDepositBitcoinToIconFail2(t *testing.T) { chainParam := &chaincfg.TestNet3Params + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - inputs := []*multisig.UTXO{ + inputs := []*multisig.Input{ { - IsRelayersMultisig: false, TxHash: "0416795b227e1a6a64eeb7bf7542d15964d18ac4c4732675d3189cda8d38bed7", OutputIdx: 3, OutputAmount: 2998000, + PkScript: userMultisigWallet.PKScript, }, } - outputs := []*multisig.OutputTx{} + outputs := []*wire.TxOut{} // Add Bridge Message - payload, _ := multisig.CreateBridgePayload( - &multisig.XCallMessage{ + scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ Action: "Deposit", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", @@ -285,47 +266,37 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { Amount: new(big.Int).SetUint64(1000000).Bytes(), Data: []byte(""), }, - 1, - "cx8b52dfea0aa1e548288102df15ad7159f7266106", - []string{ + ChainId: 1, + Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", + Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, - ) - scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, + }) + for _, script := range scripts { + outputs = append(outputs, &wire.TxOut{ + Value: 0, + PkScript: script, }) } // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - Amount: 1000, + outputs = append(outputs, &wire.TxOut{ + Value: 1000, + PkScript: relayerPkScript, }) - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - + msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + fmt.Println("err: ", err) + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -341,21 +312,27 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { func TestDepositBitcoinToIconFail3(t *testing.T) { chainParam := &chaincfg.TestNet3Params + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - inputs := []*multisig.UTXO{ + inputs := []*multisig.Input{ { - IsRelayersMultisig: false, TxHash: "dc21f89436d9fbda2cc521ed9b8988c7cbf84cdc67d728b2b2709a5efe7e775a", OutputIdx: 4, OutputAmount: 2996000, + PkScript: userMultisigWallet.PKScript, }, } - outputs := []*multisig.OutputTx{} + outputs := []*wire.TxOut{} // Add Bridge Message - payload, _ := multisig.CreateBridgePayload( - &multisig.XCallMessage{ + scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ Action: "Deposit", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", @@ -363,47 +340,37 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), }, - 1, - "cx8b52dfea0aa1e548288102df15ad7159f7266106", - []string{ + ChainId: 1, + Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", + Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, - ) - scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, + }) + for _, script := range scripts { + outputs = append(outputs, &wire.TxOut{ + Value: 0, + PkScript: script, }) } // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - Amount: 10000, + outputs = append(outputs, &wire.TxOut{ + Value: 10000, + PkScript: relayerPkScript, }) - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - + msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + fmt.Println("err: ", err) + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -419,21 +386,27 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { func TestDepositBitcoinToIconFail4(t *testing.T) { chainParam := &chaincfg.TestNet3Params + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - inputs := []*multisig.UTXO{ + inputs := []*multisig.Input{ { - IsRelayersMultisig: false, TxHash: "1e29fa62942f92dd4cf688e219641b54229fbc2ec2dc74cc9c1c7f247c7172b2", OutputIdx: 4, OutputAmount: 2985000, + PkScript: userMultisigWallet.PKScript, }, } - outputs := []*multisig.OutputTx{} + outputs := []*wire.TxOut{} // Add Bridge Message - payload, _ := multisig.CreateBridgePayload( - &multisig.XCallMessage{ + scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ Action: "Withdraw", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", @@ -441,47 +414,37 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), }, - 1, - "cx8b52dfea0aa1e548288102df15ad7159f7266106", - []string{ + ChainId: 1, + Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", + Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, - ) - scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, + }) + for _, script := range scripts { + outputs = append(outputs, &wire.TxOut{ + Value: 0, + PkScript: script, }) } // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - Amount: 10000, + outputs = append(outputs, &wire.TxOut{ + Value: 10000, + PkScript: relayerPkScript, }) - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - + msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + fmt.Println("err: ", err) + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -559,100 +522,66 @@ func TestDecodeBitcoinTransaction(t *testing.T) { func TestDepositRuneToIcon(t *testing.T) { chainParam := &chaincfg.TestNet3Params + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - inputs := []*multisig.UTXO{ + bridgeMsg := multisig.BridgeDecodedMsg { + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "840000:3", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Connectors: []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + } + + inputs := []*multisig.Input{ // user rune UTXOs to spend { - IsRelayersMultisig: false, TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", OutputIdx: 0, OutputAmount: 1000, + PkScript: userMultisigWallet.PKScript, }, // user bitcoin UTXOs to pay tx fee { - IsRelayersMultisig: false, TxHash: "4933e04e3d9320df6e9f046ff83cfc3e9f884d8811df0539af7aaca0218189aa", OutputIdx: 0, OutputAmount: 4000000, + PkScript: userMultisigWallet.PKScript, }, } - outputs := []*multisig.OutputTx{} - - // Add Bridge Message - payload, _ := multisig.CreateBridgePayload( - &multisig.XCallMessage{ - Action: "Deposit", - TokenAddress: "840000:3", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), - Data: []byte(""), - }, - 1, - "cx8b52dfea0aa1e548288102df15ad7159f7266106", - []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, + // create tx + msgTx, err := multisig.CreateBridgeTxSendRune( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + TX_FEE, ) - scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, - }) - } - - // Add transfering rune to relayer multisig - runeId, _ := runestone.NewRuneId(840000, 3) - changeReceiver := uint32(len(outputs) + 2) - runeStone := &runestone.Runestone{ - Edicts: []runestone.Edict{ - { - ID: *runeId, - Amount: uint128.From64(1000000000), - Output: uint32(len(outputs) + 1), - }, - }, - Pointer: &changeReceiver, - } - runeScript, _ := runeStone.Encipher() - // Runestone OP_RETURN - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: runeScript, - }) - // Rune UTXO send to relayer multisig - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - Amount: 1000, - }) - // Rune change UTXO send back to user - changeReceiverAddress := "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: changeReceiverAddress, - Amount: 1000, - }) - - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - msgTx, _, txSigHashes, _ := multisig.CreateMultisigTx(inputs, outputs, 1000, &multisig.MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := multisig.TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - + fmt.Println("err: ", err) + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := multisig.PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS - signedMsgTx, err := multisig.CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -672,99 +601,6 @@ func TestDepositRuneToIcon(t *testing.T) { } a, _ := json.Marshal(artifact) fmt.Printf("Artifact: %s\n", string(a)) - // TODO: test the signedMsgTx -} - -func TestCreateAndSignBitcoinTransaction(t *testing.T) { - // Set up the network parameters (use TestNet3 for testing) - chainParam := &chaincfg.TestNet3Params - wif, _ := btcutil.DecodeWIF("your_private_key") - // Get the private key from WIF - privateKey := wif.PrivKey - // Create a Taproot address - internalKey := privateKey.PubKey() - taprootKey := txscript.ComputeTaprootOutputKey(internalKey, nil) - taprootAddress, err := btcutil.NewAddressTaproot(schnorr.SerializePubKey(taprootKey), chainParam) - assert.NoError(t, err) - - // Create the output script (witness program) - pkScript, err := txscript.PayToAddrScript(taprootAddress) - assert.NoError(t, err) - prevOutputAmount := uint64(99800000) - sendingAmount := uint64(100000) - fees := uint64(200000) - - inputs := []*multisig.UTXO{ - { - IsRelayersMultisig: false, - TxHash: "9dbd6f6f976f9f31895214c6c3034c80c567a38e1e816b8eb6bed972df0fdad9", - OutputIdx: 4, - OutputAmount: prevOutputAmount, - }, - } - - outputs := []*multisig.OutputTx{} - - // Add Bridge Message - payload, _ := multisig.CreateBridgePayload( - &multisig.XCallMessage{MessageType: 1, - Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1peg65qks0qum848kq8udf3n3psvkpkaxsr7wq60ukr7w2symtt83qwd7cmx", - Amount: new(big.Int).SetUint64(sendingAmount).Bytes(), - Data: []byte(""), - }, - 1, - "cx8b52dfea0aa1e548288102df15ad7159f7266106", - []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, - ) - scripts, _ := multisig.CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &multisig.OutputTx{ - OpReturnScript: script, - }) - } - // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &multisig.OutputTx{ - ReceiverAddress: "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk", - Amount: sendingAmount, - }) - - changeReceiverAddress := "tb1peg65qks0qum848kq8udf3n3psvkpkaxsr7wq60ukr7w2symtt83qwd7cmx" - msgTx, _, _, _ := multisig.CreateMultisigTx(inputs, outputs, fees, &multisig.MultisigWallet{}, &multisig.MultisigWallet{}, chainParam, changeReceiverAddress, 1) - - // Sign the transaction using Taproot - for i, txIn := range msgTx.TxIn { - // Create the signing hash - prevOutputFetcher := txscript.NewCannedPrevOutputFetcher(pkScript, int64(prevOutputAmount)) - sigHashes := txscript.NewTxSigHashes(msgTx, prevOutputFetcher) - - // Create the Taproot signature - witness, err := txscript.TaprootWitnessSignature( - msgTx, - sigHashes, - i, - int64(prevOutputAmount), - pkScript, - txscript.SigHashDefault, - privateKey, - ) - assert.NoError(t, err) - - // Set the witness data - txIn.Witness = witness - } - - // Serialize the transaction - var signedTx bytes.Buffer - err = msgTx.Serialize(&signedTx) - assert.NoError(t, err) - - // Print the hex-encoded transaction - fmt.Printf("Signed Taproot transaction: %x\n", signedTx.Bytes()) + // TODO: test the signedMsgTx } diff --git a/utils/multisig/bridge_script.go b/utils/multisig/bridge_script.go new file mode 100644 index 00000000..bf2c9e3d --- /dev/null +++ b/utils/multisig/bridge_script.go @@ -0,0 +1,198 @@ +package multisig + +import ( + "encoding/hex" + "fmt" + + "github.com/btcsuite/btcd/txscript" + "github.com/btcsuite/btcd/wire" + "github.com/icon-project/goloop/common/codec" +) + +const ( + OP_BRIDGE_IDENT = txscript.OP_14 +) + +type XCallMessage struct { + MessageType uint8 + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte +} + +type BridgeDecodedMsg struct { + Message *XCallMessage + ChainId uint8 + Receiver string + Connectors []string +} + +func AddressToPayload(address string) ([]byte, error) { + prefix := address[0:2] + var prefixType uint8 // max number of supported type is 7 + switch prefix { + case "0x": + prefixType = 1 + case "hx": + prefixType = 2 + case "cx": + prefixType = 3 + default: + return nil, fmt.Errorf("address type not supported") + } + addressBytes, err := hex.DecodeString(address[2:]) + if err != nil { + return nil, fmt.Errorf("could decode string address - Error %v", err) + } + + addressBytesLen := uint8(len(addressBytes)) + if addressBytesLen > 32 { + return nil, fmt.Errorf("address length not supported") + } + prefixByte := byte((prefixType << 5) ^ (addressBytesLen - 1)) + + return append([]byte{prefixByte}, addressBytes...), nil +} + +func PayloadToAddress(payload []byte) (string, []byte, error) { + prefixByte := payload[0] + prefixType := uint8(prefixByte >> 5) + var prefix string + switch prefixType { + case 1: + prefix = "0x" + case 2: + prefix = "hx" + case 3: + prefix = "cx" + default: + return "", nil, fmt.Errorf("prefix type not supported") + } + addressBytesLen := uint8((prefixByte << 3 >> 3) + 1) + address := prefix + hex.EncodeToString(payload[1:addressBytesLen+1]) + remainPayload := payload[addressBytesLen+1:] + + return address, remainPayload, nil +} + +func CreateBridgePayload(msg *BridgeDecodedMsg) ([]byte, error) { + payload, err := codec.RLP.MarshalToBytes(msg.Message) + if err != nil { + return nil, fmt.Errorf("could not marshal message - Error %v", err) + } + + payload = append(payload, msg.ChainId) + + receiverBytes, err := AddressToPayload(msg.Receiver) + if err != nil { + return nil, err + } + payload = append(payload, receiverBytes...) + + for _, connector := range msg.Connectors { + connectorBytes, err := AddressToPayload(connector) + if err != nil { + return nil, err + } + payload = append(payload, connectorBytes...) + } + + return payload, nil +} + +func EncodePayloadToScripts(payload []byte) ([][]byte, error) { + // divide []byte payload to parts + var chunk []byte + chunks := make([][]byte, 0, len(payload)/PART_LIMIT+1) + for len(payload) >= PART_LIMIT { + chunk, payload = payload[:PART_LIMIT], payload[PART_LIMIT:] + chunks = append(chunks, chunk) + } + if len(payload) > 0 { + chunks = append(chunks, payload) + } + // turn parts to OP_RETURN script + scripts := [][]byte{} + for _, part := range chunks { + builder := txscript.NewScriptBuilder() + + builder.AddOp(txscript.OP_RETURN) + builder.AddOp(OP_BRIDGE_IDENT) + builder.AddData(part) + + script, err := builder.Script() + if err != nil { + return nil, fmt.Errorf("could not build script - Error %v", err) + } + + scripts = append(scripts, script) + } + + return scripts, nil +} + +func CreateBridgeMessageScripts(msg *BridgeDecodedMsg) ([][]byte, error) { + payload, err := CreateBridgePayload(msg) + if err != nil { + return nil, err + } + + return EncodePayloadToScripts(payload) +} + +func ReadBridgeMessage(transaction *wire.MsgTx) (*BridgeDecodedMsg, error) { + payload := []byte{} + for _, output := range transaction.TxOut { + tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) + if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != txscript.OP_RETURN { + // Check for OP_RETURN + continue + } + if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != OP_BRIDGE_IDENT { + // Check to ignore non Bridge protocol identifier (Rune or RadFi) + continue + } + + // Construct the payload by concatenating remaining data pushes + for tokenizer.Next() { + if tokenizer.Err() != nil { + return nil, tokenizer.Err() + } + payload = append(payload, tokenizer.Data()...) + } + } + + if len(payload) == 0 { + return nil, fmt.Errorf("no Bridge message found") + } + + var message XCallMessage + remainData, err := codec.RLP.UnmarshalFromBytes(payload, &message) + if err != nil { + return nil, fmt.Errorf("could not unmarshal message - Error %v", err) + } + chainId := uint8(remainData[0]) + receiver, remainData, err := PayloadToAddress(remainData[1:]) + if err != nil { + return nil, err + } + connectors := []string{} + var connector string + for len(remainData) > 0 { + connector, remainData, err = PayloadToAddress(remainData) + if err != nil { + return nil, err + } + connectors = append(connectors, connector) + } + + return &BridgeDecodedMsg{ + Message: &message, + ChainId: chainId, + Receiver: receiver, + Connectors: connectors, + }, nil +} diff --git a/utils/multisig/bridge_tx.go b/utils/multisig/bridge_tx.go new file mode 100644 index 00000000..7b070f0d --- /dev/null +++ b/utils/multisig/bridge_tx.go @@ -0,0 +1,99 @@ +package multisig + +import ( + "math/big" + + "github.com/btcsuite/btcd/wire" + "github.com/bxelab/runestone" + "lukechampine.com/uint128" +) + +func CreateBridgeTxSendBitcoin( + msg *BridgeDecodedMsg, + inputs []*Input, + senderPkScript []byte, + receiverPkScript []byte, + txFee int64, +) (*wire.MsgTx, error) { + // TODO: verify msg content + + outputs := []*wire.TxOut{ + // bitcoin send to receiver + { + Value: new(big.Int).SetBytes(msg.Message.Amount).Int64(), + PkScript: receiverPkScript, + }, + } + + bridgeScripts, err := CreateBridgeMessageScripts(msg) + if err != nil { + return nil, err + } + for _, script := range bridgeScripts { + outputs = append(outputs, &wire.TxOut{ + Value: 0, + PkScript: script, + }) + } + + return CreateTx(inputs, outputs, senderPkScript, txFee, 0) +} + +func CreateBridgeTxSendRune( + msg *BridgeDecodedMsg, + inputs []*Input, + senderPkScript []byte, + receiverPkScript []byte, + txFee int64, +) (*wire.MsgTx, error) { + // TODO: verify msg content + + // create runestone OP_RETURN + runeId, err := runestone.RuneIdFromString(msg.Message.TokenAddress) + if err != nil { + return nil, err + } + relayerChangeOutput := uint32(1) + runeOutput := &runestone.Runestone{ + Edicts: []runestone.Edict{ + { + ID: *runeId, + Amount: uint128.FromBig(new(big.Int).SetBytes(msg.Message.Amount)), + Output: 0, + }, + }, + Pointer: &relayerChangeOutput, + } + runeScript, _ := runeOutput.Encipher() + + outputs := []*wire.TxOut{ + // rune send to receiver + { + Value: DUST_UTXO_AMOUNT, + PkScript: receiverPkScript, + }, + // rune change output + { + Value: DUST_UTXO_AMOUNT, + PkScript: senderPkScript, + }, + // rune OP_RETURN + { + Value: 0, + PkScript: runeScript, + }, + } + + bridgeScripts, err := CreateBridgeMessageScripts(msg) + if err != nil { + return nil, err + } + for _, script := range bridgeScripts { + outputs = append(outputs, &wire.TxOut{ + Value: 0, + PkScript: script, + }) + } + + return CreateTx(inputs, outputs, senderPkScript, txFee, 0) +} diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 7c17d056..5fb1a920 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,4 +1,9 @@ package multisig -const MIN_SAT = 100 -const SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" \ No newline at end of file +const( + MIN_SAT = 100 + SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" + DUST_UTXO_AMOUNT int64 = 1000 + + PART_LIMIT = 76 +) \ No newline at end of file diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 7df01948..021a4832 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -11,10 +11,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" "github.com/bxelab/runestone" - "github.com/holiman/uint256" ) const ( @@ -73,169 +70,6 @@ func TestBuildMultisigTapScript(t *testing.T) { fmt.Println("userMultisigAddress, err : ", userMultisigAddress, err) } -func TestMultisigUserClaimLiquidity(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: true, - TxHash: "9ed822adb7c3623fcc6776bc93dadb030bf3b887e36975521d540c2a49510e27", - OutputIdx: 1, - OutputAmount: 3901, - }, - } - - outputs := []*OutputTx{ - { - ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", - Amount: 1000, - }, - } - - relayerPrivKeys, relayersMultisigInfo := RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) - relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) - - changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, relayersMultisigWallet, &MultisigWallet{}, chainParam, changeReceiverAddress, 0) - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - UserPKScript: []byte{}, - UserTapLeaf: txscript.TapLeaf{}, - } - - totalSigs := [][][]byte{} - // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) - if err != nil { - fmt.Println("err sign: ", err) - } - totalSigs = append(totalSigs, sigs) - - router := SetUpRouter() - // create post body using an instance of the requestSignInput struct - rsi := requestSignInput{ - MsgTx: hexRawTx, - UTXOs: inputs, - TapSigInfo: tapSigParams, - } - requestJson, _ := json.Marshal(rsi) - - // SLAVE RELAYER 1 SIGN TX - sigs1 := requestSign("/requestSign1", requestJson, router) - fmt.Println("resp: ", sigs1) - totalSigs = append(totalSigs, sigs1) - - // SLAVE RELAYER 2 SIGN TX - sigs2 := requestSign("/requestSign2", requestJson, router) - fmt.Println("resp: ", sigs2) - totalSigs = append(totalSigs, sigs2) - - // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, relayersMultisigWallet, 0, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) -} - -func TestMultisigUserSwap(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: false, - TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", - OutputIdx: 0, - OutputAmount: 1501, - }, - { - IsRelayersMultisig: true, - TxHash: "374702601b446e0a5c247d15bc6ea049a1266c29ef119ab03801d490ad223bd2", - OutputIdx: 1, - OutputAmount: 4234, - }, - } - - outputs := []*OutputTx{ - { - ReceiverAddress: "tb1pfhttx6vvskhgv6h0w9rss3k63r0zy8vnmwrap0jvraqm5wme6vtsglfta8", - Amount: 1834, - }, - } - - relayerPrivKeys, relayersMultisigInfo := RandomMultisigInfo(3, 3, chainParam, []int{0, 1, 2}, 0, 1) - relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := "tb1py04eh93ae0e6dpps2ufxt58wjnvesj0ffzddcckmru3tyrhzsslsxyhwtd" - msgTx, hexRawTx, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, relayersMultisigWallet, userMultisigWallet, chainParam, changeReceiverAddress, 0) - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: relayersMultisigWallet.PKScript, - RelayersTapLeaf: relayersMultisigWallet.TapLeaves[0], - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[0], - } - - totalSigs := [][][]byte{} - // MATSTER RELAYER SIGN TX - sigs, err := PartSignOnRawExternalTx(relayerPrivKeys[0], msgTx, inputs, tapSigParams, chainParam, true) - if err != nil { - fmt.Println("err sign: ", err) - } - totalSigs = append(totalSigs, sigs) - - router := SetUpRouter() - // create post body using an instance of the requestSignInput struct - rsi := requestSignInput{ - MsgTx: hexRawTx, - UTXOs: inputs, - TapSigInfo: tapSigParams, - } - requestJson, _ := json.Marshal(rsi) - - // SLAVE RELAYER 1 SIGN TX - sigs1 := requestSign("/requestSign1", requestJson, router) - fmt.Println("resp: ", sigs1) - totalSigs = append(totalSigs, sigs1) - - // SLAVE RELAYER 2 SIGN TX - sigs2 := requestSign("/requestSign2", requestJson, router) - fmt.Println("resp: ", sigs2) - totalSigs = append(totalSigs, sigs2) - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - - // add user sign to total sigs - for i := range msgTx.TxIn { - if !inputs[i].IsRelayersMultisig { - totalSigs[1][i] = userSigs[i] - } - } - fmt.Println("--------totalSig: ", totalSigs) - - // MATSTER RELAYER COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, relayersMultisigWallet, 0, userMultisigWallet, 0, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) -} - func TestGenSharedInternalPubKey(t *testing.T) { b := make([]byte, 32) rand.Read(b) @@ -262,151 +96,23 @@ func TestParseTx(t *testing.T) { } } -func TestUserRecoveryTimeLock(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: false, - TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", - OutputIdx: 4, - OutputAmount: 1929000, - }, - } - - outputs := []*OutputTx{ - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000000, - }, - } - - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - - totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) -} - -func TestTransferRune(t *testing.T) { +func TestTransferBitcoinWithBridgeMessage(t *testing.T) { chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: false, - TxHash: "ae9f43a77d861d5076ebdb1af0d76af033843b784766a1d07a78a68fe845c012", - OutputIdx: 1, - OutputAmount: 3808, - }, - } - - outputs := []*OutputTx{ - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - } - + // relayer multisig + _, relayersMultisigInfo := RandomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) + // user key userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - // Add Rune transfering - // rune id 840000:3, amount 10000 (5 decimals), to output id 0 - script1, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 0) - msgTx.AddTxOut(wire.NewTxOut(0, script1)) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - - totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // Decipher runestone - r := &runestone.Runestone{} - artifact, err := r.Decipher(signedMsgTx) - if err != nil { - fmt.Println(err) - return - } - a, _ := json.Marshal(artifact) - fmt.Printf("Artifact: %s\n", string(a)) -} - -func TestTransferBitcoinWithBridgeMessage(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: false, - TxHash: "88cce50b4c9ff0d1c3f58f769fdb8b2e2bfbd3a637664c78b1a38c0f1e492b8f", - OutputIdx: 0, - OutputAmount: 2000000, - }, - } - - outputs := []*OutputTx{ - { - ReceiverAddress: USER_MULTISIG_ADDRESS, - Amount: 10000, - }, - } - - // Add Bridge Message - payload, _ := CreateBridgePayload( + bridgeMsg := BridgeDecodedMsg { &XCallMessage{ MessageType: 1, Action: "Deposit", TokenAddress: "0:0", // bitcoin address To: "0x2.icon/hx39eddef484f6bb08072c59cc0a206e6713fc6d7d", //(receiver) From: USER_MULTISIG_ADDRESS, //user - Amount: new(big.Int).SetUint64(1000).Bytes(), + Amount: new(big.Int).SetUint64(10000).Bytes(), Data: []byte(""), }, 1, @@ -416,37 +122,37 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { "hx0000000000000000000000000000000000000002", "hx0000000000000000000000000000000000000003", }, - ) - scripts, _ := CreateBridgeMessageScripts(payload, 76) - for i, script := range scripts { - fmt.Println("OP_RETURN ", i, " script ", script) - outputs = append(outputs, &OutputTx{ - OpReturnScript: script, - }) } - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + inputs := []*Input{ + // user bitcoin UTXO to transfer and pay tx fee + { + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, + PkScript: userMultisigWallet.PKScript, + }, } + // create tx + msgTx, err := CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayersMultisigWallet.PKScript, + TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -473,517 +179,67 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { fmt.Println("Connectors: ", decodedMessage.Connectors) } -func TestRadFiInitPool(t *testing.T) { +func TestTransferRuneWithBridgeMessage(t *testing.T) { chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: false, - TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", - OutputIdx: 4, - OutputAmount: 1929000, - }, - } - - // OP_RETURN RadFi Init pool Message - radfiMsg := RadFiProvideLiquidityMsg{ - Detail: &RadFiProvideLiquidityDetail{ - Fee: 30, - UpperTick: 12345, - LowerTick: -12345, - Min0: 0, - Min1: 10000, - }, - InitPrice: uint256.MustFromDecimal("123456789"), - } - script, _ := CreateProvideLiquidityScript(&radfiMsg) - - outputs := []*OutputTx{ - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - OpReturnScript: script, - }, - } - + // relayer multisig + _, relayersMultisigInfo := RandomMultisigInfo(3, 2, chainParam, []int{0, 1, 2}, 0, 1) + relayersMultisigWallet, _ := BuildMultisigWallet(relayersMultisigInfo) + // user key userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGN - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // Decode Radfi message - decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) - fmt.Println("err decode: ", err) - fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - Fee : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Fee) - fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.UpperTick) - fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.LowerTick) - fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min0) - fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min1) - fmt.Println("decoded message - InitPrice: ", decodedRadFiMessage.ProvideLiquidityMsg.InitPrice) -} - -func TestRadFiProvideLiquidity(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: true, - TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", - OutputIdx: 0, - OutputAmount: 1000, - }, - { - IsRelayersMultisig: false, - TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", - OutputIdx: 2, - OutputAmount: 1918000, - }, - { - IsRelayersMultisig: false, - TxHash: "96f43d22e98f9abf78422b27bd31412912b7c5e3a2b3f706d61148fc8d0f6550", - OutputIdx: 0, - OutputAmount: 1000, + bridgeMsg := BridgeDecodedMsg { + &XCallMessage{ + Action: "Deposit", + TokenAddress: "840000:3", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(1000000).Bytes(), + Data: []byte(""), }, - } - - // OP_RETURN RadFi Provive Liquidity Message - radfiMsg := RadFiProvideLiquidityMsg{ - Detail: &RadFiProvideLiquidityDetail{ - Fee: 30, - UpperTick: 12345, - LowerTick: -12345, - Min0: 0, - Min1: 10000, + 1, + "cx8b52dfea0aa1e548288102df15ad7159f7266106", + []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, } - script1, _ := CreateProvideLiquidityScript(&radfiMsg) - // OP_RETURN Rune transfering - // rune id 840000:3, amount 10000 (5 decimals), to output id 4 - script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(1000000000), 4) - outputs := []*OutputTx{ + inputs := []*Input{ + // userrune UTXO used to transfer { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, + TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", + OutputIdx: 0, + OutputAmount: DUST_UTXO_AMOUNT, + PkScript: userMultisigWallet.PKScript, }, + // user bitcoin UTXO to pay tx fee { - OpReturnScript: script1, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, + PkScript: userMultisigWallet.PKScript, }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 20000, - }, - { - OpReturnScript: script2, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - } - - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], } - totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // Decode Radfi message - decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) - fmt.Println("err decode: ", err) - fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - Fee : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Fee) - fmt.Println("decoded message - UpperTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.UpperTick) - fmt.Println("decoded message - LowerTick: ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.LowerTick) - fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min0) - fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.ProvideLiquidityMsg.Detail.Min1) - fmt.Println("decoded message - InitPrice: ", decodedRadFiMessage.ProvideLiquidityMsg.InitPrice) - - // get list of Relayer bitcoin an rune UTXOs - relayerScriptAddress := signedMsgTx.TxOut[0].PkScript - sequenceNumberUTXO, bitcoinUTXOs, runeUTXOs, err := GetRelayerReceivedUTXO(signedMsgTx, 0, relayerScriptAddress) - fmt.Println("-------------GetRelayerReceivedUTXO:") - fmt.Println("relayerScriptAddress: ", relayerScriptAddress) + // create tx + msgTx, err := CreateBridgeTxSendRune( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayersMultisigWallet.PKScript, + TX_FEE, + ) fmt.Println("err: ", err) - fmt.Println("sequenceNumberUTXO: ", sequenceNumberUTXO.IsRelayersMultisig, sequenceNumberUTXO.OutputIdx, sequenceNumberUTXO.OutputAmount, sequenceNumberUTXO.TxHash) - fmt.Println("bitcoinUTXOs: ") - for _, utxo := range bitcoinUTXOs { - fmt.Println("bitcoinUTXO: ", utxo.IsRelayersMultisig, utxo.OutputIdx, utxo.OutputAmount, utxo.TxHash) - } - fmt.Println("runeUTXOs: ") - for _, utxo := range runeUTXOs { - fmt.Println("runeUTXO: ", utxo.edict, utxo.edictUTXO.IsRelayersMultisig, utxo.edictUTXO.OutputIdx, utxo.edictUTXO.OutputAmount, utxo.edictUTXO.TxHash) - } -} - -func TestRadFiSwap(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: true, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 0, - OutputAmount: 1000, - }, - { - IsRelayersMultisig: false, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 5, - OutputAmount: 1888000, - }, - { - IsRelayersMultisig: false, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 4, - OutputAmount: 1000, - }, - } - - // OP_RETURN RadFi Swap Message - radfiMsg := RadFiSwapMsg{ - IsExactInOut: true, - TokenOutIndex: 2, - } - script1, _ := CreateSwapScript(&radfiMsg) - // OP_RETURN Rune transfering - // rune id 840000:3, amount 4000 (5 decimals), to output id 3 - script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(400000000), 3) - // rune id 840000:3, amount 6000 (5 decimals), to output id 6 - script3, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(600000000), 6) - - outputs := []*OutputTx{ - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - OpReturnScript: script1, - }, - { - OpReturnScript: script2, - }, - { - ReceiverAddress: USER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 10000, - }, - { - OpReturnScript: script3, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - } - - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // Decode Radfi message - decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) - - fmt.Println("err decode: ", err) - fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - IsExactInOut : ", decodedRadFiMessage.SwapMsg.IsExactInOut) - fmt.Println("decoded message - TokenOutIndex : ", decodedRadFiMessage.SwapMsg.TokenOutIndex) -} - -func TestRadFiWithdrawLiquidity(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: true, - TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", - OutputIdx: 0, - OutputAmount: 1000, - }, - { - IsRelayersMultisig: true, - TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", - OutputIdx: 4, - OutputAmount: 10000, - }, - { - IsRelayersMultisig: true, - TxHash: "3aa9c4b9a71fe19560c467cdddce932eae8a10e28123a09acb27701123f2a8f7", - OutputIdx: 6, - OutputAmount: 1000, - }, - { - IsRelayersMultisig: false, - TxHash: "4e2b225d732b4123443e8d737e292921ea4a891ddf3a5c9842a4409f2c82805d", - OutputIdx: 5, - OutputAmount: 1867000, - }, - } - - // OP_RETURN RadFi Withdraw Liquidity Message - radfiMsg := RadFiWithdrawLiquidityMsg{ - RecipientIndex: 2, - LiquidityValue: uint256.MustFromDecimal("123456"), - NftId: uint256.MustFromDecimal("123456789"), - } - script1, _ := CreateWithdrawLiquidityScript(&radfiMsg) - // OP_RETURN Rune transfering - // rune id 840000:3, amount 2500 (5 decimals), to output id 3 - script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(250000000), 4) - // rune id 840000:3, amount 3500 (5 decimals), to output id 7 - script3, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(350000000), 7) - - outputs := []*OutputTx{ - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - OpReturnScript: script1, - }, - { - ReceiverAddress: USER_MULTISIG_ADDRESS, - Amount: 5000, - }, - { - OpReturnScript: script2, - }, - { - ReceiverAddress: USER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 5000, - }, - { - OpReturnScript: script3, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - } - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } - totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // Decode Radfi message - decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) - - fmt.Println("err decode: ", err) - fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - RecipientIndex : ", decodedRadFiMessage.WithdrawLiquidityMsg.RecipientIndex) - fmt.Println("decoded message - LiquidityValue : ", decodedRadFiMessage.WithdrawLiquidityMsg.LiquidityValue) - fmt.Println("decoded message - NftId : ", decodedRadFiMessage.WithdrawLiquidityMsg.NftId) -} - -func TestRadFiCollectFees(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: true, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 0, - OutputAmount: 1000, - }, - { - IsRelayersMultisig: true, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 5, - OutputAmount: 5000, - }, - { - IsRelayersMultisig: true, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 7, - OutputAmount: 1000, - }, - { - IsRelayersMultisig: false, - TxHash: "b508b193dd9712406c8d712af00e6d3e34b8d2ad52809b72c63f6463c1555703", - OutputIdx: 8, - OutputAmount: 1856000, - }, - } - - // OP_RETURN RadFi Collect Fees - radfiMsg := RadFiCollectFeesMsg{ - RecipientIndex: 2, - NftId: uint256.MustFromDecimal("123456789"), - } - script1, _ := CreateCollectFeesScript(&radfiMsg) - // OP_RETURN Rune transfering - // rune id 840000:3, amount 500 (5 decimals), to output id 4 - script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(50000000), 4) - // rune id 840000:3, amount 3000 (5 decimals), to output id 7 - script3, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(300000000), 7) - - outputs := []*OutputTx{ - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - OpReturnScript: script1, - }, - { - ReceiverAddress: USER_MULTISIG_ADDRESS, - Amount: 2000, - }, - { - OpReturnScript: script2, - }, - { - ReceiverAddress: USER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 3000, - }, - { - OpReturnScript: script3, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - } - - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], - } + // sign tx totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) + // user key 1 sign tx + userSigs1, _ := SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) @@ -994,108 +250,28 @@ func TestRadFiCollectFees(t *testing.T) { fmt.Println("signedMsgTxID: ", signedMsgTxID) fmt.Println("err sign: ", err) - // Decode Radfi message - decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) - - fmt.Println("err decode: ", err) - fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - RecipientIndex : ", decodedRadFiMessage.CollectFeesMsg.RecipientIndex) - fmt.Println("decoded message - NftId : ", decodedRadFiMessage.CollectFeesMsg.NftId) -} - -func TestRadFiIncreaseLiquidity(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - - inputs := []*UTXO{ - { - IsRelayersMultisig: true, - TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", - OutputIdx: 0, - OutputAmount: 1000, - }, - { - IsRelayersMultisig: false, - TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", - OutputIdx: 8, - OutputAmount: 1845000, - }, - { - IsRelayersMultisig: false, - TxHash: "546fd5aa7336a82ec31dda54de0ec0e81c9285e42f75768f5de058b390126e51", - OutputIdx: 0, - OutputAmount: 1000, - }, - } - - // OP_RETURN RadFi Increase Liquidity Message - radfiMsg := RadFiIncreaseLiquidityMsg{ - Min0: 0, - Min1: 10000, - NftId: uint256.MustFromDecimal("123456789"), - } - script1, _ := CreateIncreaseLiquidityScript(&radfiMsg) - // OP_RETURN Rune transfering - // rune id 840000:3, amount 500 (5 decimals), to output id 4 - script2, _ := CreateRuneTransferScript(Rune{BlockNumber: 840000, TxIndex: 3}, big.NewInt(50000000), 4) - - outputs := []*OutputTx{ - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - { - OpReturnScript: script1, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 20000, - }, - { - OpReturnScript: script2, - }, - { - ReceiverAddress: RELAYER_MULTISIG_ADDRESS, - Amount: 1000, - }, - } - - userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - - changeReceiverAddress := USER_MULTISIG_ADDRESS - msgTx, _, txSigHashes, _ := CreateMultisigTx(inputs, outputs, TX_FEE, &MultisigWallet{}, userMultisigWallet, chainParam, changeReceiverAddress, 1) - - tapSigParams := TapSigParams{ - TxSigHashes: txSigHashes, - RelayersPKScript: []byte{}, - RelayersTapLeaf: txscript.TapLeaf{}, - UserPKScript: userMultisigWallet.PKScript, - UserTapLeaf: userMultisigWallet.TapLeaves[1], + // Decipher runestone + r := &runestone.Runestone{} + artifact, err := r.Decipher(signedMsgTx) + if err != nil { + fmt.Println(err) + return } - totalSigs := [][][]byte{} - - // USER SIGN TX - userSigs, _ := PartSignOnRawExternalTx(userPrivKeys[1], msgTx, inputs, tapSigParams, chainParam, true) - totalSigs = append(totalSigs, userSigs) - - // COMBINE SIGNS - signedMsgTx, err := CombineMultisigSigs(msgTx, inputs, userMultisigWallet, 0, userMultisigWallet, 1, totalSigs) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // Decode Radfi message - decodedRadFiMessage, err := ReadRadFiMessage(signedMsgTx) + a, _ := json.Marshal(artifact) + fmt.Printf("Artifact: %s\n", string(a)) + // Decode bridge message + decodedMessage, err := ReadBridgeMessage(signedMsgTx) fmt.Println("err decode: ", err) - fmt.Println("decoded message - Flag : ", decodedRadFiMessage.Flag) - fmt.Println("decoded message - Min0 : ", decodedRadFiMessage.IncreaseLiquidityMsg.Min0) - fmt.Println("decoded message - Min1 : ", decodedRadFiMessage.IncreaseLiquidityMsg.Min1) - fmt.Println("decoded message - NftId : ", decodedRadFiMessage.IncreaseLiquidityMsg.NftId) + fmt.Println("-----------decodedMessage---------- ") + fmt.Println("Message.MessageType: ", decodedMessage.Message.MessageType) + fmt.Println("Message.Action: ", decodedMessage.Message.Action) + fmt.Println("Message.TokenAddress: ", decodedMessage.Message.TokenAddress) + fmt.Println("Message.From: ", decodedMessage.Message.From) + fmt.Println("Message.To: ", decodedMessage.Message.To) + fmt.Println("Message.Amount: ", decodedMessage.Message.Amount) + fmt.Println("Message.Data: ", decodedMessage.Message.Data) + fmt.Println("ChainId: ", decodedMessage.ChainId) + fmt.Println("Address: ", decodedMessage.Receiver) + fmt.Println("Connectors: ", decodedMessage.Connectors) } diff --git a/utils/multisig/op_message.go b/utils/multisig/op_message.go deleted file mode 100644 index bb30dc83..00000000 --- a/utils/multisig/op_message.go +++ /dev/null @@ -1,492 +0,0 @@ -package multisig - -import ( - "bytes" - "encoding/binary" - "encoding/hex" - "fmt" - - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - "github.com/holiman/uint256" - "github.com/icon-project/goloop/common/codec" -) - -const ( - OP_RADFI_IDENT = txscript.OP_12 - OP_RUNE_IDENT = txscript.OP_13 - OP_BRIDGE_IDENT = txscript.OP_14 - - OP_RADFI_PROVIDE_LIQUIDITY = txscript.OP_1 - OP_RADFI_SWAP = txscript.OP_2 - OP_RADFI_WITHDRAW_LIQUIDITY = txscript.OP_3 - OP_RADFI_COLLECT_FEES = txscript.OP_4 - OP_RADFI_INCREASE_LIQUIDITY = txscript.OP_5 -) - -type XCallMessage struct { - MessageType uint8 - Action string - TokenAddress string - From string - To string - Amount []byte - Data []byte -} - -type RadFiProvideLiquidityDetail struct { - Fee uint8 - UpperTick int32 - LowerTick int32 - Min0 uint16 - Min1 uint16 -} - -type RadFiProvideLiquidityMsg struct { - Detail *RadFiProvideLiquidityDetail - InitPrice *uint256.Int -} - -type RadFiSwapMsg struct { - IsExactInOut bool - TokenOutIndex uint32 - // TokenOutId *Rune - // TokenOutAmount *uint256.Int -} - -type RadFiWithdrawLiquidityMsg struct { - RecipientIndex uint32 - LiquidityValue *uint256.Int - NftId *uint256.Int -} - -type RadFiCollectFeesMsg struct { - RecipientIndex uint32 - NftId *uint256.Int -} - -type RadFiIncreaseLiquidityMsg struct { - Min0 uint16 - Min1 uint16 - NftId *uint256.Int -} - -type BridgeDecodedMsg struct { - Message *XCallMessage - ChainId uint8 - Receiver string - Connectors []string -} - -type RadFiDecodedMsg struct { - Flag byte - ProvideLiquidityMsg *RadFiProvideLiquidityMsg - SwapMsg *RadFiSwapMsg - WithdrawLiquidityMsg *RadFiWithdrawLiquidityMsg - CollectFeesMsg *RadFiCollectFeesMsg - IncreaseLiquidityMsg *RadFiIncreaseLiquidityMsg -} - -func AddressToPayload(address string) ([]byte, error) { - prefix := address[0:2] - var prefixType uint8 // max number of supported type is 7 - switch prefix { - case "0x": - prefixType = 1 - case "hx": - prefixType = 2 - case "cx": - prefixType = 3 - default: - return nil, fmt.Errorf("address type not supported") - } - addressBytes, err := hex.DecodeString(address[2:]) - if err != nil { - return nil, fmt.Errorf("could decode string address - Error %v", err) - } - - addressBytesLen := uint8(len(addressBytes)) - if addressBytesLen > 32 { - return nil, fmt.Errorf("address length not supported") - } - prefixByte := byte((prefixType << 5) ^ (addressBytesLen - 1)) - - return append([]byte{prefixByte}, addressBytes...), nil -} - -func PayloadToAddress(payload []byte) (string, []byte, error) { - prefixByte := payload[0] - prefixType := uint8(prefixByte >> 5) - var prefix string - switch prefixType { - case 1: - prefix = "0x" - case 2: - prefix = "hx" - case 3: - prefix = "cx" - default: - return "", nil, fmt.Errorf("prefix type not supported") - } - addressBytesLen := uint8((prefixByte << 3 >> 3) + 1) - address := prefix + hex.EncodeToString(payload[1:addressBytesLen+1]) - remainPayload := payload[addressBytesLen+1:] - - return address, remainPayload, nil -} - -func CreateBridgePayload(message *XCallMessage, chainId uint8, receiver string, connectors []string) ([]byte, error) { - payload, err := codec.RLP.MarshalToBytes(message) - if err != nil { - return nil, fmt.Errorf("could not marshal message - Error %v", err) - } - - payload = append(payload, chainId) - - receiverBytes, err := AddressToPayload(receiver) - if err != nil { - return nil, err - } - payload = append(payload, receiverBytes...) - - for _, connector := range connectors { - connectorBytes, err := AddressToPayload(connector) - if err != nil { - return nil, err - } - payload = append(payload, connectorBytes...) - } - - return payload, nil -} - -func CreateBridgeMessageScripts(payload []byte, partLimit int) ([][]byte, error) { - var chunk []byte - chunks := make([][]byte, 0, len(payload)/partLimit+1) - for len(payload) >= partLimit { - chunk, payload = payload[:partLimit], payload[partLimit:] - chunks = append(chunks, chunk) - } - if len(payload) > 0 { - chunks = append(chunks, payload) - } - - scripts := [][]byte{} - for _, part := range chunks { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(OP_BRIDGE_IDENT) - builder.AddData(part) - - script, err := builder.Script() - if err != nil { - return nil, fmt.Errorf("could not build script - Error %v", err) - } - scripts = append(scripts, script) - } - - return scripts, nil -} - -func CreateProvideLiquidityScript(msg *RadFiProvideLiquidityMsg) ([]byte, error) { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(OP_RADFI_IDENT) - builder.AddOp(OP_RADFI_PROVIDE_LIQUIDITY) - // encode message content - buf := new(bytes.Buffer) - var data = []any{msg.Detail.Fee, msg.Detail.UpperTick, msg.Detail.LowerTick, msg.Detail.Min0, msg.Detail.Min1} - for _, v := range data { - err := binary.Write(buf, binary.BigEndian, v) - if err != nil { - return nil, fmt.Errorf("could encode data - Error %v", err) - } - } - - if msg.InitPrice != nil { - return builder.AddData(append(buf.Bytes(), msg.InitPrice.Bytes()...)).Script() - } - - return builder.AddData(buf.Bytes()).Script() -} - -func CreateSwapScript(msg *RadFiSwapMsg) ([]byte, error) { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(OP_RADFI_IDENT) - builder.AddOp(OP_RADFI_SWAP) - // encode message content - var isExactInOutUint8 uint8 - if msg.IsExactInOut { - isExactInOutUint8 = 1 - } - - // tokenOutIdBlockNumberByte := make([]byte, 8) - // binary.BigEndian.PutUint64(tokenOutIdBlockNumberByte, msg.TokenOutId.BlockNumber) - // tokenOutIdBlockNumberLen := uint8(bits.Len64(msg.TokenOutId.BlockNumber)) - - // tokenOutIdTxIndexByte := make([]byte, 4) - // binary.BigEndian.PutUint32(tokenOutIdTxIndexByte, msg.TokenOutId.TxIndex) - // tokenOutIdTxIndexLen := uint8(bits.Len32(msg.TokenOutId.TxIndex)) - - // fmt.Println("tokenOutIdBlockNumberLen: ", tokenOutIdBlockNumberLen) - // singleByte := byte((isExactInOutUint8 << 7) ^ (tokenOutIdBlockNumberLen << 3) ^ tokenOutIdTxIndexLen) - // fmt.Println("singleByte: ", singleByte) - // data := append([]byte{singleByte}, tokenOutIdBlockNumberByte[8-tokenOutIdBlockNumberLen:]...) - // data = append(data, tokenOutIdTxIndexByte[4-tokenOutIdTxIndexLen:]...) - // data = append(data, msg.TokenOutAmount.Bytes()...) - - TokenOutIndexByte := make([]byte, 4) - binary.BigEndian.PutUint32(TokenOutIndexByte, msg.TokenOutIndex) - data := append([]byte{isExactInOutUint8}, TokenOutIndexByte...) - - return builder.AddData(data).Script() -} - -func CreateWithdrawLiquidityScript(msg *RadFiWithdrawLiquidityMsg) ([]byte, error) { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(OP_RADFI_IDENT) - builder.AddOp(OP_RADFI_WITHDRAW_LIQUIDITY) - // encode message content - recipientIndexByte := make([]byte, 4) - binary.BigEndian.PutUint32(recipientIndexByte, msg.RecipientIndex) - // recipientIndexLen := uint8(bits.Len32(msg.RecipientIndex)) - liquidityValueBytes := msg.LiquidityValue.Bytes() - liquidityValueBytesLen := uint8(len(liquidityValueBytes)) - // singleByte := byte((recipientIndexLen << 5) ^ liquidityValueBytesLen) - singleByte := byte(liquidityValueBytesLen) - // data := append([]byte{singleByte}, recipientIndexByte[4-recipientIndexLen:]...) - data := append([]byte{singleByte}, recipientIndexByte...) - data = append(data, liquidityValueBytes...) - data = append(data, msg.NftId.Bytes()...) - // fmt.Println("data: ", data) - // fmt.Println("singleByte: ", singleByte) - // fmt.Println("recipientIndexByte: ", recipientIndexByte) - // fmt.Println("liquidityValueBytes: ", liquidityValueBytes) - return builder.AddData(data).Script() -} - -func CreateCollectFeesScript(msg *RadFiCollectFeesMsg) ([]byte, error) { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(OP_RADFI_IDENT) - builder.AddOp(OP_RADFI_COLLECT_FEES) - // encode message content - recipientIndexByte := make([]byte, 4) - binary.BigEndian.PutUint32(recipientIndexByte, msg.RecipientIndex) - data := append(recipientIndexByte, msg.NftId.Bytes()...) - - return builder.AddData(data).Script() -} - -func CreateIncreaseLiquidityScript(msg *RadFiIncreaseLiquidityMsg) ([]byte, error) { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(OP_RADFI_IDENT) - builder.AddOp(OP_RADFI_INCREASE_LIQUIDITY) - // encode message content - buf := new(bytes.Buffer) - var data = []any{msg.Min0, msg.Min1} - for _, v := range data { - err := binary.Write(buf, binary.BigEndian, v) - if err != nil { - return nil, fmt.Errorf("could encode data - Error %v", err) - } - } - - return builder.AddData(append(buf.Bytes(), msg.NftId.Bytes()...)).Script() -} - -func ReadBridgeMessage(transaction *wire.MsgTx) (*BridgeDecodedMsg, error) { - payload := []byte{} - for _, output := range transaction.TxOut { - tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) - if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != txscript.OP_RETURN { - // Check for OP_RETURN - continue - } - if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != OP_BRIDGE_IDENT { - // Check to ignore non Bridge protocol identifier (Rune or RadFi) - continue - } - - // Construct the payload by concatenating remaining data pushes - for tokenizer.Next() { - if tokenizer.Err() != nil { - return nil, tokenizer.Err() - } - payload = append(payload, tokenizer.Data()...) - } - } - - if len(payload) == 0 { - return nil, fmt.Errorf("no Bridge message found") - } - - var message XCallMessage - remainData, err := codec.RLP.UnmarshalFromBytes(payload, &message) - if err != nil { - return nil, fmt.Errorf("could not unmarshal message - Error %v", err) - } - chainId := uint8(remainData[0]) - receiver, remainData, err := PayloadToAddress(remainData[1:]) - if err != nil { - return nil, err - } - connectors := []string{} - var connector string - for len(remainData) > 0 { - connector, remainData, err = PayloadToAddress(remainData) - if err != nil { - return nil, err - } - connectors = append(connectors, connector) - } - - return &BridgeDecodedMsg{ - Message: &message, - ChainId: chainId, - Receiver: receiver, - Connectors: connectors, - }, nil -} - -func ReadRadFiMessage(transaction *wire.MsgTx) (*RadFiDecodedMsg, error) { - var flag byte - var payload []byte - for _, output := range transaction.TxOut { - tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) - if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != txscript.OP_RETURN { - // Check for OP_RETURN - continue - } - if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != OP_RADFI_IDENT { - // Check to ignore non RadFi protocol identifier (Rune or Bridge) - continue - } - - if tokenizer.Next() && tokenizer.Err() == nil { - flag = tokenizer.Opcode() - } - - // Construct the payload by concatenating remaining data pushes - for tokenizer.Next() { - if tokenizer.Err() != nil { - return nil, tokenizer.Err() - } - payload = append(payload, tokenizer.Data()...) - } - - // only read 1 OP_RETURN output for RadFi protocol - break - } - - // Decode RadFi message - switch flag { - case OP_RADFI_PROVIDE_LIQUIDITY: - r := bytes.NewReader(payload[:13]) - var provideLiquidityDetail RadFiProvideLiquidityDetail - if err := binary.Read(r, binary.BigEndian, &provideLiquidityDetail); err != nil { - return nil, fmt.Errorf("ReadRadFiMessage - OP_RADFI_PROVIDE_LIQUIDITY Read failed") - } - - if len(payload) > 13 { - return &RadFiDecodedMsg{ - Flag: flag, - ProvideLiquidityMsg: &RadFiProvideLiquidityMsg{ - Detail: &provideLiquidityDetail, - InitPrice: new(uint256.Int).SetBytes(payload[13:]), - }, - }, nil - } - - return &RadFiDecodedMsg{ - Flag: flag, - ProvideLiquidityMsg: &RadFiProvideLiquidityMsg{ - Detail: &provideLiquidityDetail, - }, - }, nil - - case OP_RADFI_SWAP: - // singleByte := uint8(payload[0]) - // isExactInOut := (singleByte >> 7) != 0 - // tokenOutIdBlockNumberLen := singleByte << 1 >> 4 - // tokenOutIdTxIndexLen := singleByte << 5 >> 5 - - // payload = payload[1:] - // tokenOutIdBlockNumber := binary.BigEndian.Uint64(payload[:tokenOutIdBlockNumberLen]) - - // payload = payload[tokenOutIdBlockNumberLen:] - // tokenOutIdTxIndex := binary.BigEndian.Uint32(payload[:tokenOutIdTxIndexLen]) - - // TokenOutAmount := new(uint256.Int).SetBytes(payload[tokenOutIdTxIndexLen:]) - - return &RadFiDecodedMsg{ - Flag: flag, - SwapMsg: &RadFiSwapMsg{ - IsExactInOut: payload[0] != 0, - TokenOutIndex: binary.BigEndian.Uint32(payload[1:]), - // TokenOutId : &Rune{ - // BlockNumber : tokenOutIdBlockNumber, - // TxIndex : tokenOutIdTxIndex, - // }, - // TokenOutAmount : TokenOutAmount, - }, - }, nil - - case OP_RADFI_WITHDRAW_LIQUIDITY: - // singleByte := uint8(payload[0]) - // recipientIndexLen := singleByte >> 5 - // fmt.Println("recipientIndexLen", recipientIndexLen) - // liquidityValueBytesLen := singleByte << 3 >> 3 - liquidityValueBytesLen := uint8(payload[0]) - // fmt.Println("liquidityValueBytesLen", liquidityValueBytesLen) - payload = payload[1:] - recipientIndex := binary.BigEndian.Uint32(payload[:4]) - payload = payload[4:] - liquidityValue := new(uint256.Int).SetBytes(payload[:liquidityValueBytesLen]) - nftId := new(uint256.Int).SetBytes(payload[liquidityValueBytesLen:]) - // fmt.Println("OP_RADFI_WITHDRAW_LIQUIDITY", recipientIndex, liquidityValue, NftId) - - return &RadFiDecodedMsg{ - Flag: flag, - WithdrawLiquidityMsg: &RadFiWithdrawLiquidityMsg{ - RecipientIndex: recipientIndex, - LiquidityValue: liquidityValue, - NftId: nftId, - }, - }, nil - - case OP_RADFI_COLLECT_FEES: - recipientIndex := binary.BigEndian.Uint32(payload[:4]) - nftId := new(uint256.Int).SetBytes(payload[4:]) - - return &RadFiDecodedMsg{ - Flag: flag, - CollectFeesMsg: &RadFiCollectFeesMsg{ - RecipientIndex: recipientIndex, - NftId: nftId, - }, - }, nil - - case OP_RADFI_INCREASE_LIQUIDITY: - return &RadFiDecodedMsg{ - Flag: flag, - IncreaseLiquidityMsg: &RadFiIncreaseLiquidityMsg{ - Min0: binary.BigEndian.Uint16(payload[:2]), - Min1: binary.BigEndian.Uint16(payload[2:4]), - NftId: new(uint256.Int).SetBytes(payload[4:]), - }, - }, nil - - default: - return nil, fmt.Errorf("ReadRadFiMessage - invalid flag") - } -} diff --git a/utils/multisig/structure.go b/utils/multisig/structure.go index 656994a7..0758b266 100644 --- a/utils/multisig/structure.go +++ b/utils/multisig/structure.go @@ -22,28 +22,11 @@ type MultisigWallet struct { SharedPublicKey *btcec.PublicKey } -type OutputTx struct { - OpReturnScript []byte - ReceiverAddress string - Amount uint64 -} - -type UTXO struct { - IsRelayersMultisig bool `bson:"is_relayers_multisig" json:"isRelayersMultisig"` - TxHash string `bson:"tx_hash" json:"txHash"` - OutputIdx uint32 `bson:"output_idx" json:"outputIdx"` - OutputAmount uint64 `bson:"output_amount" json:"outputAmount"` -} - -type RuneUTXO struct { - edict runestone.Edict - edictUTXO *UTXO -} - -type TapSigParams struct { - TxSigHashes *txscript.TxSigHashes `bson:"tx_sig_hashes" json:"txSigHashes"` - RelayersPKScript []byte `bson:"relayers_PK_script" json:"relayersPKScript"` - RelayersTapLeaf txscript.TapLeaf `bson:"relayers_tap_leaf" json:"relayersTapLeaf"` - UserPKScript []byte `bson:"user_PK_script" json:"userPKScript"` - UserTapLeaf txscript.TapLeaf `bson:"user_tap_leaf" json:"userTapLeaf"` +type Input struct { + TxHash string + OutputIdx uint32 + OutputAmount int64 + PkScript []byte + Sigs [][]byte + Runes []*runestone.Edict } diff --git a/utils/multisig/test_utils.go b/utils/multisig/test_utils.go deleted file mode 100644 index bb453723..00000000 --- a/utils/multisig/test_utils.go +++ /dev/null @@ -1,79 +0,0 @@ -package multisig - -import ( - "bytes" - "encoding/json" - "fmt" - "io" - "net/http" - "net/http/httptest" - - "github.com/btcsuite/btcd/chaincfg" - "github.com/gin-gonic/gin" -) - -func SetUpRouter() *gin.Engine{ - router := gin.Default() - router.POST("/requestSign1", postRequestSignSlaveRelayer1) - router.POST("/requestSign2", postRequestSignSlaveRelayer2) - - return router -} - -func requestSign(url string, requestJson []byte, router *gin.Engine) [][]byte{ - req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestJson)) - w := httptest.NewRecorder() - router.ServeHTTP(w, req) - - responseData, _ := io.ReadAll(w.Body) - - sigs := [][]byte{} - err := json.Unmarshal(responseData, &sigs) - if err != nil { - fmt.Println("err Unmarshal: ", err) - } - - return sigs -} - -type requestSignInput struct { - MsgTx string `json:"msgTx"` - UTXOs []*UTXO `json:"UTXOs"` - TapSigInfo TapSigParams `json:"tapSigInfo"` -} - -func postRequestSignSlaveRelayer1(c *gin.Context) { - var input requestSignInput - - if err := c.ShouldBindJSON(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), - }) - return - } - - chainParam := &chaincfg.SigNetParams - privKeys, _, _ := randomKeys(1, chainParam, []int{1}) - msgTx, _ := ParseTx(input.MsgTx) - sigs, _ := PartSignOnRawExternalTx(privKeys[0], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) - - c.IndentedJSON(http.StatusOK, sigs) -} - -func postRequestSignSlaveRelayer2(c *gin.Context) { - var input requestSignInput - - if err := c.ShouldBindJSON(&input); err != nil { - c.JSON(http.StatusBadRequest, gin.H{ - "error": err.Error(), - }) - return - } - - chainParam := &chaincfg.SigNetParams - privKeys, _, _ := randomKeys(1, chainParam, []int{2}) - msgTx, _ := ParseTx(input.MsgTx) - sigs, _ := PartSignOnRawExternalTx(privKeys[0], msgTx, input.UTXOs, input.TapSigInfo, chainParam, false) - - c.IndentedJSON(http.StatusOK, sigs) -} diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index c4c9c060..3e0916b1 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -6,160 +6,127 @@ import ( "fmt" "strings" - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/bxelab/runestone" + "github.com/btcsuite/btcd/btcutil" ) -// create unsigned multisig transaction -// input: UTXOs, output, tx fee, chain config, change receiver, PK scripts -// output: unsigned tx message -func CreateMultisigTx( - inputs []*UTXO, - outputs []*OutputTx, - txFee uint64, - relayersMultisigWallet *MultisigWallet, - userMultisigWallet *MultisigWallet, - chainParam *chaincfg.Params, - changeReceiverAddress string, +func TransposeSigs(sigs [][][]byte) [][][]byte { + xl := len(sigs[0]) + yl := len(sigs) + result := make([][][]byte, xl) + + for i := range result { + result[i] = make([][]byte, yl) + } + for i := 0; i < xl; i++ { + for j := 0; j < yl; j++ { + result[i][j] = sigs[j][i] + } + } + + return result +} + +func ParseTx(data string) (*wire.MsgTx, error) { + fmt.Printf("ParseTx data: %v\n", string(data)) + dataBytes, err := hex.DecodeString(data) + if err != nil { + return nil, err + } + fmt.Printf("ParseTx dataBytes: %v\n", string(dataBytes)) + tx := &wire.MsgTx{} + err = tx.Deserialize(strings.NewReader(string(dataBytes))) + if err != nil { + return nil, err + } + return tx, nil +} + +func CreateTx( + inputs []*Input, + outputs []*wire.TxOut, + changePkScript []byte, + txFee int64, lockTime uint32, -) (*wire.MsgTx, string, *txscript.TxSigHashes, error) { +) (*wire.MsgTx, error) { msgTx := wire.NewMsgTx(2) - // if lockTime > 0 { - // msgTx.LockTime = lockTime - // } - // add TxIns into raw tx - // totalInputAmount in external unit - totalInputAmount := uint64(0) - prevOuts := txscript.NewMultiPrevOutFetcher(nil) - for _, in := range inputs { - utxoHash, err := chainhash.NewHashFromStr(in.TxHash) + totalInputAmount := int64(0) + for _, input := range inputs { + utxoHash, err := chainhash.NewHashFromStr(input.TxHash) if err != nil { - return nil, "", nil, err + return nil, err } - outPoint := wire.NewOutPoint(utxoHash, in.OutputIdx) + outPoint := wire.NewOutPoint(utxoHash, input.OutputIdx) txIn := wire.NewTxIn(outPoint, nil, nil) txIn.Sequence = lockTime msgTx.AddTxIn(txIn) - totalInputAmount += in.OutputAmount - - var pkScript []byte - if in.IsRelayersMultisig { - pkScript = relayersMultisigWallet.PKScript - } else { - pkScript = userMultisigWallet.PKScript - } - - prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ - Value: int64(in.OutputAmount), - PkScript: pkScript, - }) + totalInputAmount += input.OutputAmount } - // add TxOuts into raw tx - // totalOutputAmount in external unit totalOutputAmount := txFee - for _, out := range outputs { - if len(out.OpReturnScript) > 0 { - msgTx.AddTxOut(wire.NewTxOut(0, out.OpReturnScript)) - } else { - // adding the output to tx - decodedAddr, err := btcutil.DecodeAddress(out.ReceiverAddress, chainParam) - if err != nil { - return nil, "", nil, fmt.Errorf("CreateMultisigTx - Error when decoding receiver address: %v - %v", err, out.ReceiverAddress) - } - destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) - if err != nil { - return nil, "", nil, err - } + for _, output := range outputs { + msgTx.AddTxOut(output) - // adding the destination address and the amount to the transaction - if out.Amount < MIN_SAT { - return nil, "", nil, fmt.Errorf("CreateMultisigTx - Output amount %v must greater than minimum UTXO value %v", out.Amount, MIN_SAT) - } - redeemTxOut := wire.NewTxOut(int64(out.Amount), destinationAddrByte) - - msgTx.AddTxOut(redeemTxOut) - totalOutputAmount += out.Amount - } + totalOutputAmount += output.Value } - // check amount of input coins and output coins if totalInputAmount < totalOutputAmount { - return nil, "", nil, fmt.Errorf("CreateMultisigTx - Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) + return nil, fmt.Errorf("CreateMultisigTx - Total input amount %v is less than total output amount %v", totalInputAmount, totalOutputAmount) } - // calculate the change output if totalInputAmount > totalOutputAmount { changeAmt := totalInputAmount - totalOutputAmount if changeAmt >= MIN_SAT { - // adding the output to tx - decodedAddr, err := btcutil.DecodeAddress(changeReceiverAddress, chainParam) - if err != nil { - return nil, "", nil, err - } - destinationAddrByte, err := txscript.PayToAddrScript(decodedAddr) - if err != nil { - return nil, "", nil, err - } - // adding the destination address and the amount to the transaction - redeemTxOut := wire.NewTxOut(int64(changeAmt), destinationAddrByte) + redeemTxOut := wire.NewTxOut(changeAmt, changePkScript) msgTx.AddTxOut(redeemTxOut) } } - var rawTxBytes bytes.Buffer - err := msgTx.Serialize(&rawTxBytes) - if err != nil { - return nil, "", nil, err - } - hexRawTx := hex.EncodeToString(rawTxBytes.Bytes()) - txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) - - return msgTx, hexRawTx, txSigHashes, nil + return msgTx, nil } -// sign the tx with 1 relayer multisig key -// input: private key, unsigned tx message, UTXOs, PK scripts, tap leave, chain config, relayer type -// output: signatures -func PartSignOnRawExternalTx( +func SignTapMultisig( privKey string, msgTx *wire.MsgTx, - inputs []*UTXO, - tapSigParams TapSigParams, - chainParam *chaincfg.Params, - isMasterRelayer bool, + inputs []*Input, + multisigWallet *MultisigWallet, + indexTapLeaf int, ) ([][]byte, error) { + if len(inputs) != len(msgTx.TxIn) { + return nil, fmt.Errorf("len of inputs %v and TxIn %v mismatch", len(inputs), len(msgTx.TxIn)) + } + prevOuts := txscript.NewMultiPrevOutFetcher(nil) + for _, input := range inputs { + utxoHash, err := chainhash.NewHashFromStr(input.TxHash) + if err != nil { + return nil, err + } + outPoint := wire.NewOutPoint(utxoHash, input.OutputIdx) + + prevOuts.AddPrevOut(*outPoint, &wire.TxOut{ + Value: input.OutputAmount, + PkScript: input.PkScript, + }) + } + txSigHashes := txscript.NewTxSigHashes(msgTx, prevOuts) + wif, err := btcutil.DecodeWIF(privKey) if err != nil { return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when generate btc private key from seed: %v", err) } - // sign on each TxIn - if len(inputs) != len(msgTx.TxIn) { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Len of Public seeds %v and len of TxIn %v are not correct", len(inputs), len(msgTx.TxIn)) - } - + tapLeaf := multisigWallet.TapLeaves[indexTapLeaf] sigs := [][]byte{} - for i := range msgTx.TxIn { - if inputs[i].IsRelayersMultisig { + for i, input := range inputs { + if bytes.Equal(input.PkScript, multisigWallet.PKScript) { sig, err := txscript.RawTxInTapscriptSignature( - msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.RelayersPKScript, tapSigParams.RelayersTapLeaf, txscript.SigHashDefault, wif.PrivKey) + msgTx, txSigHashes, i, int64(inputs[i].OutputAmount), multisigWallet.PKScript, tapLeaf, txscript.SigHashDefault, wif.PrivKey) if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when relayers-multisig key signing on raw btc tx: %v", err) - } - - sigs = append(sigs, sig) - } else if isMasterRelayer { - sig, err := txscript.RawTxInTapscriptSignature( - msgTx, tapSigParams.TxSigHashes, i, int64(inputs[i].OutputAmount), tapSigParams.UserPKScript, tapSigParams.UserTapLeaf, txscript.SigHashDefault, wif.PrivKey) - if err != nil { - return nil, fmt.Errorf("[PartSignOnRawExternalTx] Error when user-multisig key signing on raw btc tx: %v", err) + return nil, fmt.Errorf("fail to sign tx: %v", err) } sigs = append(sigs, sig) @@ -171,132 +138,33 @@ func PartSignOnRawExternalTx( return sigs, nil } -func TransposeSigs(sigs [][][]byte) [][][]byte { - xl := len(sigs[0]) - yl := len(sigs) - result := make([][][]byte, xl) - - for i := range result { - result[i] = make([][]byte, yl) - } - for i := 0; i < xl; i++ { - for j := 0; j < yl; j++ { - result[i][j] = sigs[j][i] - } - } - - return result -} - -// combine all the signatures to create the signed tx -// input: tap leave, control blocks, unsigned tx message, UTXOs, signatures collection -// output: signed tx -func CombineMultisigSigs( - msgTx *wire.MsgTx, - inputs []*UTXO, - relayersMultisigWallet *MultisigWallet, - relayersIndexTapLeaf int, - userMultisigWallet *MultisigWallet, - userIndexTapLeaf int, +func CombineTapMultisig( totalSigs [][][]byte, + msgTx *wire.MsgTx, + inputs []*Input, + multisigWallet *MultisigWallet, + indexTapLeaf int, ) (*wire.MsgTx, error) { - relayersMultisigTapLeafScript := relayersMultisigWallet.TapLeaves[relayersIndexTapLeaf].Script - relayersMultisigControlBlock := relayersMultisigWallet.TapScriptTree.LeafMerkleProofs[relayersIndexTapLeaf].ToControlBlock(relayersMultisigWallet.SharedPublicKey) - relayersMultisigControlBlockBytes, _ := relayersMultisigControlBlock.ToBytes() - - userMultisigTapLeafScript := userMultisigWallet.TapLeaves[userIndexTapLeaf].Script - userMultisigControlBlock := userMultisigWallet.TapScriptTree.LeafMerkleProofs[userIndexTapLeaf].ToControlBlock(userMultisigWallet.SharedPublicKey) - userMultisigControlBlockBytes, _ := userMultisigControlBlock.ToBytes() - - transposedSigs := TransposeSigs(totalSigs) - for idxInput, v := range transposedSigs { - reverseV := [][]byte{} - for i := len(v) - 1; i >= 0; i-- { - if len(v[i]) != 0 { - reverseV = append(reverseV, v[i]) - } - } - - witness := append([][]byte{}, reverseV...) - if inputs[idxInput].IsRelayersMultisig { - witness = append(witness, relayersMultisigTapLeafScript, relayersMultisigControlBlockBytes) - } else { - witness = append(witness, userMultisigTapLeafScript, userMultisigControlBlockBytes) - } - - msgTx.TxIn[idxInput].Witness = witness - } - - return msgTx, nil -} - -func ParseTx(data string) (*wire.MsgTx, error) { - fmt.Printf("ParseTx data: %v\n", string(data)) - dataBytes, err := hex.DecodeString(data) + tapLeafScript := multisigWallet.TapLeaves[indexTapLeaf].Script + multisigControlBlock := multisigWallet.TapScriptTree.LeafMerkleProofs[indexTapLeaf].ToControlBlock(multisigWallet.SharedPublicKey) + multisigControlBlockBytes, err := multisigControlBlock.ToBytes() if err != nil { return nil, err } - fmt.Printf("ParseTx dataBytes: %v\n", string(dataBytes)) - tx := &wire.MsgTx{} - err = tx.Deserialize(strings.NewReader(string(dataBytes))) - if err != nil { - return nil, err - } - return tx, nil -} -// filter the relayer UTXO from tx -// input: tx, id of sequence number in output (0 is default, -1 if not existed), relayer script address -// output: sequence number UTXO, bitcoin UTXOs, rune UTXOs -func GetRelayerReceivedUTXO( - msgTx *wire.MsgTx, - sequenceNumberIdx int, - relayerScriptAddress []byte, -) (*UTXO, []*UTXO, []*RuneUTXO, error) { - // Decipher runestone - r := &runestone.Runestone{} - artifact, err := r.Decipher(msgTx) - if err != nil { - return nil, nil, nil, err - } - edictOutputs := []uint32{} - for _, edict := range artifact.Runestone.Edicts { - edictOutputs = append(edictOutputs, edict.Output) - } - - var sequenceNumberUTXO *UTXO - bitcoinUTXOs := []*UTXO{} - runeUTXOs := []*RuneUTXO{} -Exit: - for idx, output := range msgTx.TxOut { - // Skip non-relayer received UTXO - if !bytes.Equal(output.PkScript, relayerScriptAddress) { - continue - } - currentUTXO := &UTXO{ - IsRelayersMultisig: true, - TxHash: msgTx.TxHash().String(), - OutputIdx: uint32(idx), - OutputAmount: uint64(output.Value), - } - // check if is sequenceNumber UTXO - if idx == sequenceNumberIdx { - sequenceNumberUTXO = currentUTXO - continue - } - // check if is rune UTXO - for edictIdx, edictOutput := range edictOutputs { - if idx == int(edictOutput) { - runeUTXOs = append(runeUTXOs, &RuneUTXO{ - edict: artifact.Runestone.Edicts[edictIdx], - edictUTXO: currentUTXO, - }) - continue Exit + transposedSigs := TransposeSigs(totalSigs) + for idx, v := range transposedSigs { + if bytes.Equal(inputs[idx].PkScript, multisigWallet.PKScript) { + reverseV := [][]byte{} + for i := len(v) - 1; i >= 0; i-- { + if (len(v[i]) != 0) { + reverseV = append(reverseV, v[i]) + } } + + msgTx.TxIn[idx].Witness = append(reverseV, tapLeafScript, multisigControlBlockBytes) } - // or else it will be bitcoin UTXO - bitcoinUTXOs = append(bitcoinUTXOs, currentUTXO) } - return sequenceNumberUTXO, bitcoinUTXOs, runeUTXOs, nil + return msgTx, nil } diff --git a/utils/multisig/utils.go b/utils/multisig/utils.go index 813cc214..35da481a 100644 --- a/utils/multisig/utils.go +++ b/utils/multisig/utils.go @@ -56,8 +56,8 @@ func RandomMultisigInfo(n int, k int, chainParam *chaincfg.Params, seeds []int, return privKeys, &vaultInfo } -func SumInputsSat(inputs []*UTXO) uint64 { - total := uint64(0) +func SumInputsSat(inputs []*Input) int64 { + total := int64(0) for _, in := range inputs { total += in.OutputAmount } From 3d6493f061a35d4ecb9327b05bc56cdd93c37e53 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 8 Oct 2024 09:58:13 +0700 Subject: [PATCH 077/113] remove redundant code --- utils/multisig/rune.go | 45 ------------------------------------------ 1 file changed, 45 deletions(-) delete mode 100644 utils/multisig/rune.go diff --git a/utils/multisig/rune.go b/utils/multisig/rune.go deleted file mode 100644 index 9cd276db..00000000 --- a/utils/multisig/rune.go +++ /dev/null @@ -1,45 +0,0 @@ -package multisig - -import ( - "math/big" - - "github.com/btcsuite/btcd/txscript" - "github.com/multiformats/go-varint" -) - -type Rune struct { - BlockNumber uint64 - TxIndex uint32 -} - -// Varint encoder, ported from -// https://github.com/ordinals/ord/blob/1e6cb641faf3b1eb0aba501a7a2822d7a3dc8643/crates/ordinals/src/varint.rs#L3-L39 -// Using big.Int since go doesn't support u128 -func encodeToSlice(n *big.Int) []byte { - var result []byte - var oneTwentyEight = big.NewInt(128) - - for n.Cmp(oneTwentyEight) >= 0 { - temp := new(big.Int).Mod(n, oneTwentyEight) - tempByte := byte(temp.Uint64()) | 0x80 - result = append(result, tempByte) - n.Div(n, oneTwentyEight) - } - result = append(result, byte(n.Uint64())) - return result -} - -func CreateRuneTransferScript(rune Rune, amount *big.Int, output uint64) ([]byte, error) { - builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) - builder.AddOp(txscript.OP_13) - - data := varint.ToUvarint(0) - data = append(data, encodeToSlice(big.NewInt(int64(rune.BlockNumber)))...) - data = append(data, encodeToSlice(big.NewInt(int64(rune.TxIndex)))...) - data = append(data, encodeToSlice(amount)...) - data = append(data, encodeToSlice(big.NewInt(int64(output)))...) - - return builder.AddData(data).Script() -} \ No newline at end of file From c4d02377c5989e16642ebee4aa615792a420a6ab Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Thu, 10 Oct 2024 14:44:11 +0700 Subject: [PATCH 078/113] fix: get bridge message in txSearch --- relayer/chains/bitcoin/client.go | 35 ++++---------------- relayer/chains/bitcoin/provider.go | 51 +++++++++++++++--------------- relayer/chains/bitcoin/types.go | 8 +++-- 3 files changed, 36 insertions(+), 58 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index b319e795..d114127f 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -13,6 +13,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" + "github.com/icon-project/centralized-relay/utils/multisig" "go.uber.org/zap" // "github.com/btcsuite/btcd/wire" @@ -122,8 +123,6 @@ func (c *Client) GetFee(ctx context.Context) (uint64, error) { func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearchRes, error) { // res := []*TxSearchRes{} - meetRequirement1 := 0 - meetRequirement2 := 0 for i := param.StartHeight; i <= param.EndHeight; i++ { @@ -138,38 +137,16 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch block, err := c.client.GetBlock(blockHash) if err != nil { + c.log.Error("Failed to get block", zap.Error(err)) return nil, err } // loop thru transactions for j, tx := range block.Transactions { - // loop thru tx output - for _, txOutput := range tx.TxOut { - if len(txOutput.PkScript) > 2 { - - // check OP_RETURN - if txOutput.PkScript[0] == txscript.OP_RETURN && txOutput.PkScript[1] == byte(param.OPReturnPrefix) { - c.log.Info("TxSearch txhash", - zap.String("txhash", tx.TxHash().String()), - ) - meetRequirement1++ - } - - // check EQUAL to multisig script - if bytes.Equal(param.BitcoinScript, txOutput.PkScript) { - meetRequirement2++ - } - - if meetRequirement2*meetRequirement1 != 0 { - c.log.Info("TxSearch found op_return", - zap.Uint64("height", i), - ) - res = append(res, &TxSearchRes{Height: i, Tx: tx, TxIndex: uint64(j)}) - break - } - } + bridgeMessage, err := multisig.ReadBridgeMessage(tx) + if err != nil { + continue } - meetRequirement2 = 0 - meetRequirement1 = 0 + res = append(res, &TxSearchRes{Height: i, Tx: tx, TxIndex: uint64(j), BridgeMessage: bridgeMessage}) } } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 0a356b74..52a18578 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -39,14 +39,14 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) var ( - BTCToken = "0:1" - MethodDeposit = "Deposit" - MethodWithdrawTo = "WithdrawTo" - MasterMode = "master" - SlaveMode = "slave" - BtcDB = "btc.db" - MinSatsRequired int64 = 1000 - WitnessSize = 385 + BTCToken = "0:1" + MethodDeposit = "Deposit" + MethodWithdrawTo = "WithdrawTo" + MasterMode = "master" + SlaveMode = "slave" + BtcDB = "btc.db" + MinSatsRequired int64 = 1000 + WitnessSize = 125 ) var chainIdToName = map[uint8]string{ @@ -266,6 +266,7 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn p.logger.Error("failed to determine start height", zap.Error(err)) return err } + // startHeight := uint64(3082427) pollHeightTicker := time.NewTicker(time.Second * 60) // do scan each 2 mins pollHeightTicker.Stop() @@ -337,10 +338,10 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, } outputAmount := utxo.Satoshi.Int64() inputs = append(inputs, &multisig.Input{ - TxHash: utxo.TxId, - OutputIdx: uint32(utxo.Vout), - OutputAmount: outputAmount, - PkScript: addressPkScript, + TxHash: utxo.TxId, + OutputIdx: uint32(utxo.Vout), + OutputAmount: outputAmount, + PkScript: addressPkScript, }) totalAmount += outputAmount } @@ -370,10 +371,10 @@ func GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128 break } inputs = append(inputs, &multisig.Input{ - TxHash: utxo.TxId, - OutputIdx: uint32(utxo.Vout), - OutputAmount: utxo.Satoshi.Int64(), - PkScript: addressPkScript, + TxHash: utxo.TxId, + OutputIdx: uint32(utxo.Vout), + OutputAmount: utxo.Satoshi.Int64(), + PkScript: addressPkScript, }) if len(utxo.Runes) != 1 { return nil, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) @@ -420,7 +421,7 @@ func (p *Provider) CreateBitcoinMultisigTx( outputs = []*wire.TxOut{ // bitcoin send to receiver { - Value: bitcoinAmountRequired, + Value: bitcoinAmountRequired, PkScript: receiverPkScript, }, } @@ -450,17 +451,17 @@ func (p *Provider) CreateBitcoinMultisigTx( outputs = []*wire.TxOut{ // rune send to receiver { - Value: MinSatsRequired, + Value: MinSatsRequired, PkScript: receiverPkScript, }, // rune change output { - Value: MinSatsRequired, + Value: MinSatsRequired, PkScript: msWallet.PKScript, }, // rune OP_RETURN { - Value: 0, + Value: 0, PkScript: runeScript, }, } @@ -757,7 +758,7 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms scripts, _ := multisig.EncodePayloadToScripts(opreturnData) for _, script := range scripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: 0, PkScript: script, }) } @@ -1017,10 +1018,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err p.logger.Info("parseMessageFromTx", zap.Uint64("height", tx.Height)) - bridgeMessage, err := multisig.ReadBridgeMessage(tx.Tx) - if err != nil { - return nil, err - } + bridgeMessage := tx.BridgeMessage messageInfo := bridgeMessage.Message isValidConnector := false @@ -1139,7 +1137,8 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } p.logger.Info("Stored message for rollback case", zap.Any("storedData", storedData)) - data, err = json.Marshal(storedData) + + data, err := json.Marshal(storedData) if err != nil { return nil, fmt.Errorf("failed to marshal stored rollback message data: %v", err) } diff --git a/relayer/chains/bitcoin/types.go b/relayer/chains/bitcoin/types.go index 63147852..54f42aed 100644 --- a/relayer/chains/bitcoin/types.go +++ b/relayer/chains/bitcoin/types.go @@ -2,6 +2,7 @@ package bitcoin import ( "github.com/btcsuite/btcd/wire" + "github.com/icon-project/centralized-relay/utils/multisig" ) type MessageType int @@ -27,9 +28,10 @@ type TxSearchParam struct { } type TxSearchRes struct { - Tx *wire.MsgTx - Height uint64 - TxIndex uint64 + Tx *wire.MsgTx + Height uint64 + TxIndex uint64 + BridgeMessage *multisig.BridgeDecodedMsg } // HightRange is a struct to represent a range of heights From f11a09f49f4016b27f19264aa11939d769a4e79a Mon Sep 17 00:00:00 2001 From: spiderlipovitan <35133731+spiderlipovitan@users.noreply.github.com> Date: Wed, 16 Oct 2024 22:20:14 +0700 Subject: [PATCH 079/113] fix: correct format when call recvMessage to Icon with messageType (#5) * fix: correct format when call recvMessage to Icon with messageType * fix: correct format when call recvMessage to Icon with messageType --- relayer/chains/bitcoin/decode_test.go | 34 ++++++- relayer/chains/bitcoin/provider.go | 20 +++- relayer/chains/bitcoin/provider_test.go | 125 ++++++++++++++++++++++++ 3 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 relayer/chains/bitcoin/provider_test.go diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index 63564c7b..02f8e3c2 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -4,6 +4,7 @@ import ( "encoding/hex" "fmt" "log" + "math/big" "os" "testing" @@ -11,14 +12,18 @@ import ( ) func TestDecode(t *testing.T) { - data, _ := hex.DecodeString("f90106874465706f736974aa307830303030303030303030303030303030303030303030303030303030303030303030303030303030aa307843393736333336343766363634664645443041613933363937374437353638363664433733433037b33078312e69636f6e2f637832316539346330386330336461656538306332356438656533656132326132303738366563323331890db7148f8c6dd40000b8687b226d6574686f64223a225f73776170222c22706172616d73223a7b2270617468223a5b5d2c227265636569766572223a223078312e69636f6e2f687830343232393361393061303433656136383933653731663565343662663464646366323334633233227d7d") + + // hexString := types.new + data, _ := hex.DecodeString("f884874465706f73697483303a31b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375b33078322e69636f6e2f687830316361383532383764363334323732326665373333633235363637363736623963663966386134823a9880") depositInfo := XCallMessage{} _, err := codec.RLP.UnmarshalFromBytes(data, &depositInfo) if err != nil { log.Fatal(err.Error()) } - fmt.Println(depositInfo) + amount := new(big.Int).SetBytes(depositInfo.Amount) + amountInDecimal := new(big.Float).SetInt(amount) + fmt.Println(amountInDecimal) fmt.Println("\n =============") // test decode 2 @@ -32,7 +37,7 @@ func TestDecode(t *testing.T) { fmt.Println(withdrawInfoWrapper) fmt.Println("\n =============") - // withdraw info data + // // withdraw info data withdrawInfoWrapperV2 := CSMessageRequestV2{} _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapper.Payload, &withdrawInfoWrapperV2) if err != nil { @@ -42,7 +47,7 @@ func TestDecode(t *testing.T) { fmt.Println(withdrawInfoWrapperV2) fmt.Println("\n =============") - // withdraw info + // // withdraw info withdrawInfo := XCallMessage{} _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapperV2.Data, &withdrawInfo) if err != nil { @@ -52,6 +57,27 @@ func TestDecode(t *testing.T) { fmt.Println(withdrawInfo) } +func TestDecodeConnectionContract(t *testing.T) { + data, _ := hex.DecodeString("f9013701b90133f90130b8463078322e6274632f74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375aa63786663383665653736383765316266363831623535343862323636373834343438356330653731393287308a0a0000001501b886f884874465706f73697483303a31b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375b33078322e69636f6e2f687830316361383532383764363334323732326665373333633235363637363736623963663966386134823a9880ebaa637835373766356537353661626438396362636261333861353835303862363061313237353464326635") + csMessage := CSMessage{} + _, err := codec.RLP.UnmarshalFromBytes(data, &csMessage) + if err != nil { + log.Fatal(err.Error()) + } + fmt.Println("csMessage: ", csMessage) + csMessageV2 := CSMessageRequestV2{} + _, err = codec.RLP.UnmarshalFromBytes(csMessage.Payload, &csMessageV2) + if err != nil { + log.Fatal(err.Error()) + } + fmt.Println("csMessageV2 MessageType: ", csMessageV2.MessageType) + fmt.Println("csMessageV2 Data: ", csMessageV2.Data) + fmt.Println("csMessageV2 Protocols: ", csMessageV2.Protocols) + fmt.Println("csMessageV2 From: ", csMessageV2.From) + fmt.Println("csMessageV2 To: ", csMessageV2.To) + fmt.Println("csMessageV2 Sn: ", csMessageV2.Sn) +} + func TestGetRuneBalanceAtIndex(t *testing.T) { // res, err := GetRuneTxIndex("https://open-api.unisat.io/v1/indexer/runes", "GET", os.Getenv("APIToken"), "60fa23d19c8116dbb09441bf3d1ee27067c3d2b3735caf2045db84ea8f76d436", 2) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 52a18578..ff2139cb 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -528,14 +528,14 @@ func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128 newSatsToSend := satsToSend + estFee var err error - selectedUnspentInputs, err := p.selectUnspentUTXOs(newSatsToSend, runeToSend, runeId, address, msWallet.PKScript) + inputs, err = p.selectUnspentUTXOs(newSatsToSend, runeToSend, runeId, address, msWallet.PKScript) if err != nil { return nil, 0, err } - sumSelectedInputs = multisig.SumInputsSat(selectedUnspentInputs) + sumSelectedInputs = multisig.SumInputsSat(inputs) - txSize, err := p.calculateTxSize(selectedUnspentInputs, iterationOutputs, estFee, msWallet) + txSize, err := p.calculateTxSize(inputs, iterationOutputs, estFee, msWallet) if err != nil { return nil, 0, err } @@ -1099,9 +1099,19 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err sn := new(big.Int).SetUint64(tx.Height<<32 + tx.TxIndex) from := p.cfg.NID + "/" + p.cfg.Address - decodeMessage, _ := codec.RLP.MarshalToBytes(messageInfo) - data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(sn.Uint64()), bridgeMessage.Connectors, uint8(CALL_MESSAGE_ROLLBACK_TYPE)) + // Remove messageType from messageInfo before calling MarshalToBytes + xCallMessage := XCallMessage{ + Action: messageInfo.Action, + TokenAddress: messageInfo.TokenAddress, + From: messageInfo.From, + To: messageInfo.To, + Amount: messageInfo.Amount, + Data: messageInfo.Data, + } + decodeMessage, _ := codec.RLP.MarshalToBytes(xCallMessage) + + data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(sn.Uint64()), bridgeMessage.Connectors, uint8(messageInfo.MessageType)) relayMessage := &relayTypes.Message{ Dst: "0x2.icon", // TODO: diff --git a/relayer/chains/bitcoin/provider_test.go b/relayer/chains/bitcoin/provider_test.go new file mode 100644 index 00000000..5784d18d --- /dev/null +++ b/relayer/chains/bitcoin/provider_test.go @@ -0,0 +1,125 @@ +package bitcoin + +import ( + "bytes" + "encoding/hex" + "fmt" + "math/big" + "testing" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/txscript" + "github.com/icon-project/centralized-relay/relayer/chains/icon" + "github.com/icon-project/centralized-relay/relayer/chains/icon/types" + "github.com/icon-project/centralized-relay/utils/multisig" + "go.uber.org/zap" +) + +func TestParseMessageFromTx(t *testing.T) { + // Create a mock Provider + chainParam := &chaincfg.TestNet3Params + logger, _ := zap.NewDevelopment() + provider := &Provider{ + logger: logger, + cfg: &Config{ + Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, + }, + chainParam: &chaincfg.TestNet3Params, + } + provider.cfg.NID = "0x2.btc" + + provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" + msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) + multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) + provider.multisigAddrScript = multisigAddressScript + // Create a mock TxSearchRes + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 0, + Action: "Deposit", + TokenAddress: "0:1", + To: "0x2.icon/hx01ca85287d6342722fe733c25667676b9cf9f8a4", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(15000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Connectors: []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + } + + inputs := []*multisig.Input{ + { + TxHash: "16de7df933dacd95b0d3af7325a5a2e680a1b7dd447a97e7678d8dfa1ac750b4", + OutputIdx: 4, + OutputAmount: 445000, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx + totalSigs := [][][]byte{} + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + bridgeMessage, err := multisig.ReadBridgeMessage(signedMsgTx) + fmt.Println("bridgeMessage: ", bridgeMessage) + fmt.Println("err: ", err) + txSearchRes := &TxSearchRes{ + Tx: signedMsgTx, + Height: 3181070, + TxIndex: 21, + BridgeMessage: bridgeMessage, + } + relayerMessage, err := provider.parseMessageFromTx(txSearchRes) + fmt.Println("relayerMessage Src: ", relayerMessage.Src) + fmt.Println("relayerMessage Sn: ", relayerMessage.Sn) + fmt.Println("relayerMessage Data: ", relayerMessage.Data) + fmt.Println("err: ", err) + + msg := &types.RecvMessage{ + SrcNID: relayerMessage.Src, + ConnSn: types.NewHexInt(relayerMessage.Sn.Int64()), + Msg: types.NewHexBytes(relayerMessage.Data), + } + iconProvider := &icon.Provider{} + + iconMessage := iconProvider.NewIconMessage(iconProvider.GetAddressByEventType(relayerMessage.EventType), msg, icon.MethodRecvMessage) + fmt.Println("iconMessage Method: ", iconMessage.Method) + fmt.Println("iconMessage Params: ", iconMessage.Params) + // iconProvider.SendTransaction(nil, iconMessage) +} From 0fcbbac0ef17fbd77a6f1a0492034dfddad6ddf1 Mon Sep 17 00:00:00 2001 From: zuttodoS Date: Tue, 22 Oct 2024 16:19:26 +0700 Subject: [PATCH 080/113] update new unisat API interface --- relayer/chains/bitcoin/provider.go | 8 +++---- relayer/chains/bitcoin/unisat_api.go | 31 +++++++++++++++++----------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index ff2139cb..2a17c19b 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -319,7 +319,7 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired - resp, err := GetBtcUtxo(ctx, server, p.cfg.UniSatKey, address, 0, 32) + resp, err := GetBtcUtxo(ctx, server, p.cfg.UniSatKey, address, 0, 64) if err != nil { return nil, fmt.Errorf("failed to query bitcoin UTXOs from unisat: %v", err) } @@ -349,11 +349,11 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, return inputs, nil } -func GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, timeout uint, addressPkScript []byte) ([]*multisig.Input, error) { +func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, timeout uint, addressPkScript []byte) ([]*multisig.Input, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) defer cancel() // TODO: loop query until sastified amountRequired - resp, err := GetRuneUtxo(ctx, server, address, runeId) + resp, err := GetRuneUtxo(ctx, server, p.cfg.UniSatKey, address, runeId, 0, 64) if err != nil { return nil, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) } @@ -561,7 +561,7 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 inputs := []*multisig.Input{} if !runeToSend.IsZero() { // query rune UTXOs from unisat - runeInputs, err := GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, 3, addressPkScript) + runeInputs, err := p.GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, 3, addressPkScript) if err != nil { return nil, err } diff --git a/relayer/chains/bitcoin/unisat_api.go b/relayer/chains/bitcoin/unisat_api.go index 76445bb4..14b7d115 100644 --- a/relayer/chains/bitcoin/unisat_api.go +++ b/relayer/chains/bitcoin/unisat_api.go @@ -184,16 +184,21 @@ type RuneDetail struct { } type RuneUTXO struct { - Address string `json:"address"` - Satoshi *big.Int `json:"satoshi"` - ScriptPk string `json:"scriptPk"` - TxId string `json:"txid"` - Vout int `json:"vout"` - Runes []RuneDetail `json:"runes"` + Height int64 `json:"height"` + Confirmations int64 `json:"confirmations"` + Address string `json:"address"` + Satoshi *big.Int `json:"satoshi"` + ScriptPk string `json:"scriptPk"` + TxId string `json:"txid"` + Vout int `json:"vout"` + Runes []RuneDetail `json:"runes"` } type DataRuneUtxoList struct { - Utxo []RuneUTXO `json:"utxo"` + Height int64 `json:"height"` + Start int `json:"start"` + Total int `json:"total"` + Utxo []RuneUTXO `json:"utxo"` } type ResponseRuneUtxo struct { @@ -207,10 +212,11 @@ func BtcUtxoUrl(server, address string, offset, limit int64) string { return fmt.Sprintf("%s/v1/indexer/address/%s/utxo-data?cursor=%d&size=%d", server, address, offset, limit) } -func RuneUtxoUrl(server, address, runeId string) string { - return fmt.Sprintf("%s/v1/indexer/address/%s/runes/%s/utxo", server, address, runeId) +func RuneUtxoUrl(server, address, runeId string, offset, limit int64) string { + return fmt.Sprintf("%s/v1/indexer/address/%s/runes/%s/utxo?start=%d&limit=%d", server, address, runeId, offset, limit) } + func GetWithHeader(ctx context.Context, url string, header map[string]string, response interface{}) error { req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { @@ -247,9 +253,10 @@ func GetBtcUtxo(ctx context.Context, server, bear, address string, offset, limit return resp, err } -func GetRuneUtxo(ctx context.Context, server, address, runeId string) (ResponseRuneUtxo, error) { +func GetRuneUtxo(ctx context.Context, server, bear, address, runeId string, offset, limit int64) (ResponseRuneUtxo, error) { var resp ResponseRuneUtxo - url := RuneUtxoUrl(server, address, runeId) - err := GetWithHeader(ctx, url, make(map[string]string), &resp) + url := RuneUtxoUrl(server, address, runeId, offset, limit) + err := GetWithBear(ctx, url, bear, &resp) + return resp, err } From 012076389d2244e6730756c12072a43a6e6cbbdb Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Mon, 28 Oct 2024 17:16:03 +0700 Subject: [PATCH 081/113] feat: withdraw rune from icon to btc --- relayer/chains/bitcoin/decode_test.go | 13 +- relayer/chains/bitcoin/helper.go | 40 --- relayer/chains/bitcoin/provider.go | 40 ++- relayer/chains/bitcoin/provider_route_test.go | 126 ++++----- relayer/chains/bitcoin/provider_test.go | 244 +++++++++++++++++- relayer/chains/bitcoin/unisat_api.go | 55 ++-- relayer/chains/icon/route.go | 2 +- 7 files changed, 367 insertions(+), 153 deletions(-) diff --git a/relayer/chains/bitcoin/decode_test.go b/relayer/chains/bitcoin/decode_test.go index 02f8e3c2..d5c6b5dc 100644 --- a/relayer/chains/bitcoin/decode_test.go +++ b/relayer/chains/bitcoin/decode_test.go @@ -5,7 +5,6 @@ import ( "fmt" "log" "math/big" - "os" "testing" "github.com/icon-project/icon-bridge/common/codec" @@ -58,7 +57,7 @@ func TestDecode(t *testing.T) { } func TestDecodeConnectionContract(t *testing.T) { - data, _ := hex.DecodeString("f9013701b90133f90130b8463078322e6274632f74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375aa63786663383665653736383765316266363831623535343862323636373834343438356330653731393287308a0a0000001501b886f884874465706f73697483303a31b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375b33078322e69636f6e2f687830316361383532383764363334323732326665373333633235363637363736623963663966386134823a9880ebaa637835373766356537353661626438396362636261333861353835303862363061313237353464326635") + data, _ := hex.DecodeString("f9014101b9013df9013ab8463078322e6274632f746231706630617470743264337a656c36756477733338706b7268326534397671643363356a63756433613832737270686e6d7065353571306563727a6baa63786663383665653736383765316266363831623535343862323636373834343438356330653731393287308a0f0000001501b890f88e874465706f7369748c323930343335343a33313139b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a783573687676377375b33078322e69636f6e2f68783134393337393462613331666133333732626637393033663034303330343937653764313438303083030d4080ebaa637835373766356537353661626438396362636261333861353835303862363061313237353464326635") csMessage := CSMessage{} _, err := codec.RLP.UnmarshalFromBytes(data, &csMessage) if err != nil { @@ -77,13 +76,3 @@ func TestDecodeConnectionContract(t *testing.T) { fmt.Println("csMessageV2 To: ", csMessageV2.To) fmt.Println("csMessageV2 Sn: ", csMessageV2.Sn) } - -func TestGetRuneBalanceAtIndex(t *testing.T) { - // - res, err := GetRuneTxIndex("https://open-api.unisat.io/v1/indexer/runes", "GET", os.Getenv("APIToken"), "60fa23d19c8116dbb09441bf3d1ee27067c3d2b3735caf2045db84ea8f76d436", 2) - if err != nil { - log.Fatal(err.Error()) - } - - fmt.Printf("%+v", res) -} diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index f766620e..b2f7649c 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -1,51 +1,11 @@ package bitcoin import ( - "encoding/json" - "fmt" - "io" "math/big" - "net/http" - "strconv" "github.com/icon-project/icon-bridge/common/codec" ) -func GetRuneTxIndex(endpoint, method, bearToken, txId string, index int) (*RuneTxIndexResponse, error) { - client := &http.Client{} - endpoint = endpoint + "/runes/utxo/" + txId + "/" + strconv.FormatUint(uint64(index), 10) + "/balance" - fmt.Println(endpoint) - req, err := http.NewRequest(method, endpoint, nil) - - if err != nil { - fmt.Println(err) - return nil, err - } - req.Header.Add("Authorization", bearToken) - - res, err := client.Do(req) - if err != nil { - fmt.Println(err) - return nil, err - } - defer res.Body.Close() - - body, err := io.ReadAll(res.Body) - if err != nil { - fmt.Println(err) - return nil, err - } - - var resp *RuneTxIndexResponse - err = json.Unmarshal(body, &resp) - if err != nil { - fmt.Println(err) - return nil, err - } - - return resp, nil -} - func XcallFormat(callData []byte, from, to string, sn uint, protocols []string, messType uint8) ([]byte, error) { // csV2 := CSMessageRequestV2{ diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 2a17c19b..f4d9414d 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -102,6 +102,7 @@ type Provider struct { type Config struct { provider.CommonConfig `json:",inline" yaml:",inline"` OpCode int `json:"op-code" yaml:"op-code"` + RequestTimeout int `json:"request-timeout" yaml:"request-timeout"` // seconds UniSatURL string `json:"unisat-url" yaml:"unisat-url"` UniSatKey string `json:"unisat-key" yaml:"unisat-key"` MempoolURL string `json:"mempool-url" yaml:"mempool-url"` @@ -315,8 +316,8 @@ func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { return withdrawInfo, withdrawInfoWrapperV2.Data, nil } -func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, timeout uint, addressPkScript []byte) ([]*multisig.Input, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) +func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, timeout int64, addressPkScript []byte) ([]*multisig.Input, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*timeout)) defer cancel() // TODO: loop query until sastified amountRequired resp, err := GetBtcUtxo(ctx, server, p.cfg.UniSatKey, address, 0, 64) @@ -349,8 +350,8 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, return inputs, nil } -func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, timeout uint, addressPkScript []byte) ([]*multisig.Input, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*3) +func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, timeout int64, addressPkScript []byte) ([]*multisig.Input, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*timeout)) defer cancel() // TODO: loop query until sastified amountRequired resp, err := GetRuneUtxo(ctx, server, p.cfg.UniSatKey, address, runeId, 0, 64) @@ -386,6 +387,16 @@ func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired u return inputs, nil } +func (p *Provider) GetUTXORuneBalance(server, txId string, index int, timeout int64) (*ResponseUtxoRuneBalance, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*timeout)) + defer cancel() + resp, err := GetUtxoRuneBalance(ctx, server, p.cfg.UniSatKey, txId, index) + if err != nil { + return nil, fmt.Errorf("failed to query rune UTXO balance from unisat: %v", err) + } + return &resp, nil +} + func (p *Provider) CreateBitcoinMultisigTx( outputData []*wire.TxOut, feeRate int64, @@ -561,7 +572,7 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 inputs := []*multisig.Input{} if !runeToSend.IsZero() { // query rune UTXOs from unisat - runeInputs, err := p.GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, 3, addressPkScript) + runeInputs, err := p.GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, int64(p.cfg.RequestTimeout), addressPkScript) if err != nil { return nil, err } @@ -570,7 +581,7 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 // TODO: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo // query bitcoin UTXOs from unisat - bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, address, satToSend, 3, addressPkScript) + bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, address, satToSend, int64(p.cfg.RequestTimeout), addressPkScript) if err != nil { return nil, err } @@ -725,10 +736,18 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms if err != nil { p.logger.Error("failed to decode message: %v", zap.Error(err)) } - // 0 is need to rollback - if messageDecoded.Code == 0 { - p.logger.Info("Detected rollback message", zap.String("sn", messageDecoded.Sn.String())) + + // transaction message decoded successfully + // withdraw message has no messageDecoded.Code + if err == nil { + // 1 is transaction already success, no need to rollback + if messageDecoded.Code == 1 { + return nil, nil, fmt.Errorf("transaction already success") + } + + // message code 0 is need to rollback // Process RollbackMessage + p.logger.Info("Detected rollback message", zap.String("sn", messageDecoded.Sn.String())) data, err := p.db.Get([]byte("RB"+messageDecoded.Sn.String()), nil) if err != nil { return nil, nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) @@ -1058,8 +1077,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err break } } else { - // https://open-api.unisat.io/v1/indexer/runes/utxo - runes, err := GetRuneTxIndex(p.cfg.UniSatURL, "GET", p.bearToken, tx.Tx.TxHash().String(), i) + runes, err := p.GetUTXORuneBalance(p.cfg.UniSatURL, tx.Tx.TxHash().String(), i, int64(p.cfg.RequestTimeout)) if err != nil { return nil, err } diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go index 7bc06eaf..b6c1ca5f 100644 --- a/relayer/chains/bitcoin/provider_route_test.go +++ b/relayer/chains/bitcoin/provider_route_test.go @@ -113,8 +113,8 @@ func TestDepositBitcoinToIcon(t *testing.T) { userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - bridgeMsg := multisig.BridgeDecodedMsg { - Message: &multisig.XCallMessage{ + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", TokenAddress: "0:1", @@ -123,19 +123,19 @@ func TestDepositBitcoinToIcon(t *testing.T) { Amount: new(big.Int).SetUint64(100000).Bytes(), Data: []byte(""), }, - ChainId: 1, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", - Connectors: []string{ + ChainId: 1, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, } inputs := []*multisig.Input{ { - TxHash: "e57c10e27f75dbf0856163ca5f825b5af7ffbb3874f606b31330464ddd9df9a1", - OutputIdx: 4, - OutputAmount: 2974000, - PkScript: userMultisigWallet.PKScript, + TxHash: "e57c10e27f75dbf0856163ca5f825b5af7ffbb3874f606b31330464ddd9df9a1", + OutputIdx: 4, + OutputAmount: 2974000, + PkScript: userMultisigWallet.PKScript, }, } @@ -179,10 +179,10 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { inputs := []*multisig.Input{ { - TxHash: "eeb8c9f79ecfe7c084b2af95bf82acebd130185a0d188283d78abb58d85eddff", - OutputIdx: 4, - OutputAmount: 2999000, - PkScript: userMultisigWallet.PKScript, + TxHash: "eeb8c9f79ecfe7c084b2af95bf82acebd130185a0d188283d78abb58d85eddff", + OutputIdx: 4, + OutputAmount: 2999000, + PkScript: userMultisigWallet.PKScript, }, } @@ -190,7 +190,7 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { // Add Bridge Message scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ + Message: &multisig.XCallMessage{ Action: "Deposit", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", @@ -198,7 +198,7 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { Amount: new(big.Int).SetUint64(1000000).Bytes(), Data: []byte(""), }, - ChainId: 1, + ChainId: 1, Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", @@ -206,12 +206,12 @@ func TestDepositBitcoinToIconFail1(t *testing.T) { }) for _, script := range scripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: 0, PkScript: script, }) } - msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) fmt.Println("err: ", err) // sign tx totalSigs := [][][]byte{} @@ -247,10 +247,10 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { inputs := []*multisig.Input{ { - TxHash: "0416795b227e1a6a64eeb7bf7542d15964d18ac4c4732675d3189cda8d38bed7", - OutputIdx: 3, - OutputAmount: 2998000, - PkScript: userMultisigWallet.PKScript, + TxHash: "0416795b227e1a6a64eeb7bf7542d15964d18ac4c4732675d3189cda8d38bed7", + OutputIdx: 3, + OutputAmount: 2998000, + PkScript: userMultisigWallet.PKScript, }, } @@ -258,15 +258,15 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { // Add Bridge Message scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ + Message: &multisig.XCallMessage{ Action: "Deposit", - TokenAddress: "0:1", + TokenAddress: "0:1", // wrong token address To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), + Amount: new(big.Int).SetUint64(1000000).Bytes(), // Data: []byte(""), }, - ChainId: 1, + ChainId: 1, Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", @@ -274,18 +274,18 @@ func TestDepositBitcoinToIconFail2(t *testing.T) { }) for _, script := range scripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: 0, PkScript: script, }) } // Add transfering bitcoin to relayer multisig outputs = append(outputs, &wire.TxOut{ - Value: 1000, + Value: 1000, PkScript: relayerPkScript, }) - msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) fmt.Println("err: ", err) // sign tx totalSigs := [][][]byte{} @@ -321,10 +321,10 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { inputs := []*multisig.Input{ { - TxHash: "dc21f89436d9fbda2cc521ed9b8988c7cbf84cdc67d728b2b2709a5efe7e775a", - OutputIdx: 4, - OutputAmount: 2996000, - PkScript: userMultisigWallet.PKScript, + TxHash: "dc21f89436d9fbda2cc521ed9b8988c7cbf84cdc67d728b2b2709a5efe7e775a", + OutputIdx: 4, + OutputAmount: 2996000, + PkScript: userMultisigWallet.PKScript, }, } @@ -332,15 +332,15 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { // Add Bridge Message scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ + Message: &multisig.XCallMessage{ Action: "Deposit", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000).Bytes(), + Amount: new(big.Int).SetUint64(1000).Bytes(), // wrong amount Data: []byte(""), }, - ChainId: 1, + ChainId: 1, Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", @@ -348,18 +348,18 @@ func TestDepositBitcoinToIconFail3(t *testing.T) { }) for _, script := range scripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: 0, PkScript: script, }) } // Add transfering bitcoin to relayer multisig outputs = append(outputs, &wire.TxOut{ - Value: 10000, + Value: 10000, PkScript: relayerPkScript, }) - msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) fmt.Println("err: ", err) // sign tx totalSigs := [][][]byte{} @@ -395,10 +395,10 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { inputs := []*multisig.Input{ { - TxHash: "1e29fa62942f92dd4cf688e219641b54229fbc2ec2dc74cc9c1c7f247c7172b2", - OutputIdx: 4, - OutputAmount: 2985000, - PkScript: userMultisigWallet.PKScript, + TxHash: "1e29fa62942f92dd4cf688e219641b54229fbc2ec2dc74cc9c1c7f247c7172b2", + OutputIdx: 4, + OutputAmount: 2985000, + PkScript: userMultisigWallet.PKScript, }, } @@ -406,7 +406,7 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { // Add Bridge Message scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ + Message: &multisig.XCallMessage{ Action: "Withdraw", TokenAddress: "0:1", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", @@ -414,7 +414,7 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), }, - ChainId: 1, + ChainId: 1, Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", @@ -422,18 +422,18 @@ func TestDepositBitcoinToIconFail4(t *testing.T) { }) for _, script := range scripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: 0, PkScript: script, }) } // Add transfering bitcoin to relayer multisig outputs = append(outputs, &wire.TxOut{ - Value: 10000, + Value: 10000, PkScript: relayerPkScript, }) - msgTx, err:= multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) + msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) fmt.Println("err: ", err) // sign tx totalSigs := [][][]byte{} @@ -529,19 +529,19 @@ func TestDepositRuneToIcon(t *testing.T) { userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - bridgeMsg := multisig.BridgeDecodedMsg { - Message: &multisig.XCallMessage{ + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "840000:3", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + TokenAddress: "2904354:3119", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), + Amount: new(big.Int).SetUint64(10000).Bytes(), Data: []byte(""), }, - ChainId: 1, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", - Connectors: []string{ + ChainId: 1, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", }, } @@ -549,17 +549,17 @@ func TestDepositRuneToIcon(t *testing.T) { inputs := []*multisig.Input{ // user rune UTXOs to spend { - TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", - OutputIdx: 0, - OutputAmount: 1000, - PkScript: userMultisigWallet.PKScript, + TxHash: "69deba39f5a0700cc713f67fe8cb5ed1e35a9f0d4a3a437d839103c6e26cb947", + OutputIdx: 2, + OutputAmount: 546, + PkScript: userMultisigWallet.PKScript, }, // user bitcoin UTXOs to pay tx fee { - TxHash: "4933e04e3d9320df6e9f046ff83cfc3e9f884d8811df0539af7aaca0218189aa", - OutputIdx: 0, - OutputAmount: 4000000, - PkScript: userMultisigWallet.PKScript, + TxHash: "16de7df933dacd95b0d3af7325a5a2e680a1b7dd447a97e7678d8dfa1ac750b4", + OutputIdx: 4, + OutputAmount: 445000, + PkScript: userMultisigWallet.PKScript, }, } diff --git a/relayer/chains/bitcoin/provider_test.go b/relayer/chains/bitcoin/provider_test.go index 5784d18d..c3c5799a 100644 --- a/relayer/chains/bitcoin/provider_test.go +++ b/relayer/chains/bitcoin/provider_test.go @@ -2,7 +2,9 @@ package bitcoin import ( "bytes" + "encoding/base64" "encoding/hex" + "encoding/json" "fmt" "math/big" "testing" @@ -10,8 +12,11 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" + "github.com/bxelab/runestone" "github.com/icon-project/centralized-relay/relayer/chains/icon" "github.com/icon-project/centralized-relay/relayer/chains/icon/types" + "github.com/icon-project/centralized-relay/relayer/events" + relayTypes "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" "go.uber.org/zap" ) @@ -46,15 +51,15 @@ func TestParseMessageFromTx(t *testing.T) { MessageType: 0, Action: "Deposit", TokenAddress: "0:1", - To: "0x2.icon/hx01ca85287d6342722fe733c25667676b9cf9f8a4", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", // user bitcoin address Amount: new(big.Int).SetUint64(15000).Bytes(), Data: []byte(""), }, ChainId: 1, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", // asset manager Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", // connector contract }, } @@ -101,7 +106,7 @@ func TestParseMessageFromTx(t *testing.T) { fmt.Println("err: ", err) txSearchRes := &TxSearchRes{ Tx: signedMsgTx, - Height: 3181070, + Height: 3181075, TxIndex: 21, BridgeMessage: bridgeMessage, } @@ -121,5 +126,232 @@ func TestParseMessageFromTx(t *testing.T) { iconMessage := iconProvider.NewIconMessage(iconProvider.GetAddressByEventType(relayerMessage.EventType), msg, icon.MethodRecvMessage) fmt.Println("iconMessage Method: ", iconMessage.Method) fmt.Println("iconMessage Params: ", iconMessage.Params) - // iconProvider.SendTransaction(nil, iconMessage) +} + +func TestParseRuneMessageFromTx(t *testing.T) { + chainParam := &chaincfg.TestNet3Params + logger, _ := zap.NewDevelopment() + provider := &Provider{ + logger: logger, + cfg: &Config{ + Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, + UniSatURL: "https://open-api-testnet.unisat.io", + UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", + }, + chainParam: &chaincfg.TestNet3Params, + bearToken: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", + } + provider.cfg.NID = "0x2.btc" + + provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" + msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) + multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) + provider.multisigAddrScript = multisigAddressScript + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "2904354:3119", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(200000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Connectors: []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + } + + inputs := []*multisig.Input{ + // user rune UTXOs to spend + { + TxHash: "69deba39f5a0700cc713f67fe8cb5ed1e35a9f0d4a3a437d839103c6e26cb947", + OutputIdx: 2, + OutputAmount: 546, + PkScript: userMultisigWallet.PKScript, + }, + // user bitcoin UTXOs to pay tx fee + { + TxHash: "16de7df933dacd95b0d3af7325a5a2e680a1b7dd447a97e7678d8dfa1ac750b4", + OutputIdx: 4, + OutputAmount: 445000, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendRune( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx + totalSigs := [][][]byte{} + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + // Decipher runestone + r := &runestone.Runestone{} + artifact, err := r.Decipher(signedMsgTx) + if err != nil { + fmt.Println(err) + return + } + a, _ := json.Marshal(artifact) + fmt.Printf("Artifact: %s\n", string(a)) + + bridgeMessage, err := multisig.ReadBridgeMessage(signedMsgTx) + fmt.Println("bridgeMessage: ", bridgeMessage) + fmt.Println("err: ", err) + txSearchRes := &TxSearchRes{ + Tx: signedMsgTx, + Height: 3181071, + TxIndex: 21, + BridgeMessage: bridgeMessage, + } + relayerMessage, err := provider.parseMessageFromTx(txSearchRes) + fmt.Println("relayerMessage Src: ", relayerMessage) + // fmt.Println("relayerMessage Sn: ", relayerMessage.Sn) + // fmt.Println("relayerMessage Data: ", relayerMessage.Data) + fmt.Println("err: ", err) + + msg := &types.RecvMessage{ + SrcNID: relayerMessage.Src, + ConnSn: types.NewHexInt(relayerMessage.Sn.Int64()), + Msg: types.NewHexBytes(relayerMessage.Data), + } + iconProvider := &icon.Provider{} + + iconMessage := iconProvider.NewIconMessage(iconProvider.GetAddressByEventType(relayerMessage.EventType), msg, icon.MethodRecvMessage) + fmt.Println("iconMessage Method: ", iconMessage.Method) + fmt.Println("iconMessage Params: ", iconMessage.Params) + +} + +// parse message from icon and build withdraw btc tx +func TestBuildWithdrawBtcTxMessage(t *testing.T) { + logger, _ := zap.NewDevelopment() + chainParam := &chaincfg.TestNet3Params + provider := &Provider{ + logger: logger, + cfg: &Config{ + Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, + UniSatURL: "https://open-api-testnet.unisat.io", + UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", + RecoveryLockTime: 1234, + MasterPubKey: "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2", + Slave1PubKey: "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052", + Slave2PubKey: "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833", + }, + chainParam: &chaincfg.TestNet3Params, + } + provider.cfg.NID = "0x2.btc" + + provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" + msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) + multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) + provider.multisigAddrScript = multisigAddressScript + + data, _ := base64.StdEncoding.DecodeString("+QEfAbkBG/kBGLMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5kAbhU+FKKV2l0aGRyYXdUb4MwOjG4PnRiMXBnZTh0aHUzdTBreXF3NXY1dmxoamd0eWR6MzJtbWtkeGRnanRsOTlqcjVmNTlxczB5YXhzNTZ3a3l6gicQ+Ei4RjB4Mi5idGMvdGIxcGd6eDg4MHlmcjdxOGRnejhkcWh3NTBzbmN1NGY0aG13NWNuMzgwMDM1NHR1emN5OWp4NXNodnY3c3U=") + message := &relayTypes.Message{ + Src: "0x2.icon", + Dst: "0x2.btc", + Sn: big.NewInt(11), + MessageHeight: 1000000, + EventType: events.EmitMessage, + Data: data, + } + + msWallet, err := provider.buildMultisigWallet() + if err != nil { + fmt.Println("err: ", err) + return + } + + inputs, tx, err := provider.buildTxMessage(message, 10, msWallet) + fmt.Println("err: ", err) + fmt.Println("inputs: ", inputs) + fmt.Println("tx: ", tx) + var signedTx bytes.Buffer + tx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + fmt.Println("hexSignedTx: ", hexSignedTx) +} + +// parse message from icon and build withdraw rune tx +func TestBuildWithdrawRunesTxMessage(t *testing.T) { + logger, _ := zap.NewDevelopment() + chainParam := &chaincfg.TestNet3Params + provider := &Provider{ + logger: logger, + cfg: &Config{ + Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, + UniSatURL: "https://open-api-testnet.unisat.io", + UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", + RequestTimeout: 10, + RecoveryLockTime: 1234, + MasterPubKey: "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2", + Slave1PubKey: "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052", + Slave2PubKey: "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833", + }, + chainParam: &chaincfg.TestNet3Params, + } + provider.cfg.NID = "0x2.btc" + + provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" + msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) + multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) + provider.multisigAddrScript = multisigAddressScript + + data, _ := base64.StdEncoding.DecodeString("+QEpAbkBJfkBIrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5uAbhe+FyKV2l0aGRyYXdUb4wyOTA0MzU0OjMxMTm4PnRiMXBnZTh0aHUzdTBreXF3NXY1dmxoamd0eWR6MzJtbWtkeGRnanRsOTlqcjVmNTlxczB5YXhzNTZ3a3l6gwENiPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1") + message := &relayTypes.Message{ + Src: "0x2.icon", + Dst: "0x2.btc", + Sn: big.NewInt(11), + MessageHeight: 1000000, + EventType: events.EmitMessage, + Data: data, + } + + msWallet, err := provider.buildMultisigWallet() + if err != nil { + fmt.Println("err: ", err) + return + } + + inputs, tx, err := provider.buildTxMessage(message, 10, msWallet) + fmt.Println("err: ", err) + fmt.Println("inputs: ", inputs) + fmt.Println("tx: ", tx) + var signedTx bytes.Buffer + tx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + fmt.Println("hexSignedTx: ", hexSignedTx) } diff --git a/relayer/chains/bitcoin/unisat_api.go b/relayer/chains/bitcoin/unisat_api.go index 14b7d115..75232c5b 100644 --- a/relayer/chains/bitcoin/unisat_api.go +++ b/relayer/chains/bitcoin/unisat_api.go @@ -10,8 +10,8 @@ import ( ) const ( - UNISAT_DEFAULT_MAINNET = "https://open-api.unisat.io" - UNISAT_DEFAULT_TESTNET = "https://open-api-testnet.unisat.io" + UNISAT_DEFAULT_MAINNET = "https://open-api.unisat.io" + UNISAT_DEFAULT_TESTNET = "https://open-api-testnet.unisat.io" ) type DataBlockchainInfo struct { @@ -175,30 +175,30 @@ type ResponseBtcUtxo struct { } type RuneDetail struct { - Amount string `json:"amount"` - RuneId string `json:"runeid"` - Rune string `json:"rune"` - SpacedRune string `json:"spacedRune"` - Symbol string `json:"symbol"` - Divisibility int `json:"divisibility"` + Amount string `json:"amount"` + RuneId string `json:"runeid"` + Rune string `json:"rune"` + SpacedRune string `json:"spacedRune"` + Symbol string `json:"symbol"` + Divisibility int `json:"divisibility"` } type RuneUTXO struct { - Height int64 `json:"height"` - Confirmations int64 `json:"confirmations"` - Address string `json:"address"` - Satoshi *big.Int `json:"satoshi"` - ScriptPk string `json:"scriptPk"` - TxId string `json:"txid"` - Vout int `json:"vout"` - Runes []RuneDetail `json:"runes"` + Height int64 `json:"height"` + Confirmations int64 `json:"confirmations"` + Address string `json:"address"` + Satoshi *big.Int `json:"satoshi"` + ScriptPk string `json:"scriptPk"` + TxId string `json:"txid"` + Vout int `json:"vout"` + Runes []RuneDetail `json:"runes"` } type DataRuneUtxoList struct { - Height int64 `json:"height"` - Start int `json:"start"` - Total int `json:"total"` - Utxo []RuneUTXO `json:"utxo"` + Height int64 `json:"height"` + Start int `json:"start"` + Total int `json:"total"` + Utxo []RuneUTXO `json:"utxo"` } type ResponseRuneUtxo struct { @@ -208,6 +208,11 @@ type ResponseRuneUtxo struct { Data DataRuneUtxoList `json:"data"` } +type ResponseUtxoRuneBalance struct { + Code int `json:"code"` + Data []RuneDetail `json:"data"` +} + func BtcUtxoUrl(server, address string, offset, limit int64) string { return fmt.Sprintf("%s/v1/indexer/address/%s/utxo-data?cursor=%d&size=%d", server, address, offset, limit) } @@ -216,6 +221,9 @@ func RuneUtxoUrl(server, address, runeId string, offset, limit int64) string { return fmt.Sprintf("%s/v1/indexer/address/%s/runes/%s/utxo?start=%d&limit=%d", server, address, runeId, offset, limit) } +func UtxoRuneBalanceUrl(server, txId string, index int) string { + return fmt.Sprintf("%s/v1/indexer/runes/utxo/%s/%d/balance", server, txId, index) +} func GetWithHeader(ctx context.Context, url string, header map[string]string, response interface{}) error { req, err := http.NewRequestWithContext(ctx, "GET", url, nil) @@ -260,3 +268,10 @@ func GetRuneUtxo(ctx context.Context, server, bear, address, runeId string, offs return resp, err } + +func GetUtxoRuneBalance(ctx context.Context, server, bear, txId string, index int) (ResponseUtxoRuneBalance, error) { + var resp ResponseUtxoRuneBalance + url := UtxoRuneBalanceUrl(server, txId, index) + err := GetWithBear(ctx, url, bear, &resp) + return resp, err +} diff --git a/relayer/chains/icon/route.go b/relayer/chains/icon/route.go index f156aa21..45cc098e 100644 --- a/relayer/chains/icon/route.go +++ b/relayer/chains/icon/route.go @@ -13,7 +13,7 @@ import ( func (p *Provider) Route(ctx context.Context, message *providerTypes.Message, callback providerTypes.TxResponseFunc) error { // TODO: remove this after testing - if message.Src == "0x2.btc" || message.Dst == "0x2.btc" { + if message.Src == "0x2.icon" || message.Dst == "0x2.icon" { p.log.Info("starting to route message", zap.Any("message", message)) iconMessage, err := p.MakeIconMessage(message) From d3f3d24746e9337c6051360cfad0b3b0ad294d12 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Wed, 6 Nov 2024 17:46:41 +0700 Subject: [PATCH 082/113] feat: validate btc message and refund --- relayer/chains/bitcoin/client.go | 28 ++- relayer/chains/bitcoin/helper.go | 7 +- relayer/chains/bitcoin/provider.go | 195 +++++++++------- relayer/chains/bitcoin/provider_test.go | 295 +++++++++++++++++------- relayer/chains/bitcoin/slave.go | 2 +- utils/multisig/bridge_tx.go | 16 +- 6 files changed, 373 insertions(+), 170 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index d114127f..5700fcfc 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -42,6 +42,7 @@ type IClient interface { DecodeAddress(btcAddr string) ([]byte, error) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearchRes, error) SendRawTransaction(ctx context.Context, url string, rawMsg []json.RawMessage) (string, error) + SendRawTransactionV2(rpcUrl string, txHex string) (string, error) } // grouped rpc api clients @@ -167,13 +168,34 @@ func (c *Client) DecodeAddress(btcAddr string) ([]byte, error) { return destinationAddrByte, nil } -func (c *Client) SendRawTransaction(ctx context.Context, url string, rawMsg []json.RawMessage) (string, error) { - +func (c *Client) SendRawTransaction(ctx context.Context, rpcUrl string, rawMsg []json.RawMessage) (string, error) { if len(rawMsg) == 0 { return "", fmt.Errorf("empty raw message") } - resp, err := http.Post(url, "text/plain", bytes.NewReader(rawMsg[0])) + resp, err := http.Post(rpcUrl, "text/plain", bytes.NewReader(rawMsg[0])) + if err != nil { + c.log.Error("failed to send transaction", zap.Error(err)) + return "", err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil || resp.StatusCode != http.StatusOK { + c.log.Error("failed to broadcast transaction", zap.Int("status", resp.StatusCode), zap.String("response", string(body))) + return "", fmt.Errorf("broadcast failed: %v", err) + } + + return string(body), nil +} + +func (c *Client) SendRawTransactionV2(rpcUrl string, txHex string) (string, error) { + if len(txHex) == 0 { + return "", fmt.Errorf("empty transaction hex") + } + + payload := fmt.Sprintf(`{"jsonrpc":"1.0","method":"sendrawtransaction","params":["%s"]}`, txHex) + resp, err := http.Post(rpcUrl, "text/plain", bytes.NewReader([]byte(payload))) if err != nil { c.log.Error("failed to send transaction", zap.Error(err)) return "", err diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index b2f7649c..bb8f5bd8 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -1,6 +1,7 @@ package bitcoin import ( + "encoding/binary" "math/big" "github.com/icon-project/icon-bridge/common/codec" @@ -37,6 +38,8 @@ func XcallFormat(callData []byte, from, to string, sn uint, protocols []string, return finalMessage, nil } -func mulDiv(a, nNumerator, nDenominator *big.Int) *big.Int { - return big.NewInt(0).Div(big.NewInt(0).Mul(a, nNumerator), nDenominator) +func uint64ToBytes(amount uint64) []byte { + bytes := make([]byte, 8) + binary.BigEndian.PutUint64(bytes, amount) + return bytes } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index f4d9414d..3e6d6063 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -42,6 +42,7 @@ var ( BTCToken = "0:1" MethodDeposit = "Deposit" MethodWithdrawTo = "WithdrawTo" + MethodRefundTo = "RefundTo" MasterMode = "master" SlaveMode = "slave" BtcDB = "btc.db" @@ -93,7 +94,6 @@ type Provider struct { LastSavedHeightFunc func() uint64 LastSerialNumFunc func() *big.Int multisigAddrScript []byte - bearToken string httpServer chan struct{} db *leveldb.DB chainParam *chaincfg.Params @@ -479,6 +479,16 @@ func (p *Provider) CreateBitcoinMultisigTx( bitcoinAmountRequired = MinSatsRequired * 2 } + } else if decodedData.Action == MethodRefundTo { + uintAmount := amount.Uint64() + bitcoinAmountRequired = int64(uintAmount) + outputs = []*wire.TxOut{ + // bitcoin send to receiver + { + Value: bitcoinAmountRequired, + PkScript: receiverPkScript, + }, + } } outputs = append(outputs, outputData...) @@ -487,6 +497,9 @@ func (p *Provider) CreateBitcoinMultisigTx( if err != nil { return nil, nil, err } + if estFee > bitcoinAmountRequired && decodedData.Action == MethodRefundTo { + return nil, nil, fmt.Errorf("estimated fee is greater than the amount") + } // create raw tx msgTx, err := multisig.CreateTx(inputs, outputs, msWallet.PKScript, estFee, 0) // msgTx, hexRawTx, txSigHashes, err := multisig.CreateMultisigTx(inputs, outputs, estFee, msWallet, nil, p.chainParam, msAddressStr, 0) @@ -528,11 +541,8 @@ func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128 estFee := int64(txSize) * feeRate count := 0 - loopEntered := false - var iterationOutputs []*wire.TxOut for sumSelectedInputs < satsToSend+estFee { - loopEntered = true // Create a fresh copy of outputs for each iteration iterationOutputs := make([]*wire.TxOut, len(outputs)) copy(iterationOutputs, outputs) @@ -555,14 +565,9 @@ func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128 count += 1 if count > 500 { - return nil, 0, fmt.Errorf("Not enough sats for fee") + return nil, 0, fmt.Errorf("not enough sats for fee") } } - // Need to do that cause avoid the same outputs being used for multiple transactions - outputs = outputsCopy - if loopEntered { - outputs = iterationOutputs - } return inputs, estFee, nil } @@ -620,7 +625,7 @@ func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multi feeRate, err := p.client.GetFeeFromMempool(p.cfg.MempoolURL + "/fees/recommended") if err != nil { p.logger.Error("failed to get recommended fee from mempool", zap.Error(err)) - feeRate = 0 + feeRate = 1 } inputs, msgTx, err := p.buildTxMessage(message, int64(feeRate), msWallet) if err != nil { @@ -689,8 +694,8 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) // Broadcast transaction to bitcoin network - txHash, err := p.client.SendRawTransaction(ctx, p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(`"` + signedMsgTxHex + `"`)}) - + // txHash, err := p.client.SendRawTransaction(ctx, p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(`"` + signedMsgTxHex + `"`)}) + txHash, err := p.client.SendRawTransactionV2(p.cfg.RPCUrl, signedMsgTxHex) if err != nil { p.logger.Error("failed to send raw transaction", zap.Error(err)) return err @@ -782,6 +787,30 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms }) } } + case events.RollbackMessage: + p.logger.Info("Detected rollback from wrong message", zap.String("sn", message.Sn.String())) + key := "RB" + message.Sn.String() + data, err := p.db.Get([]byte(key), nil) + if err != nil { + return nil, nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) + } + var storedData StoredMessageData + err = json.Unmarshal(data, &storedData) + if err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal stored rollback message data: %v", err) + } + + // only rollback if tokenAddress is BTC + if storedData.TokenAddress != BTCToken { + return nil, nil, fmt.Errorf("only support rollback for BTC") + } + decodedData = &MessageDecoded{ + Action: storedData.ActionMethod, + To: storedData.SenderAddress, + TokenAddress: storedData.TokenAddress, + Amount: uint64ToBytes(storedData.Amount), + } + default: return nil, nil, fmt.Errorf("unknown event type: %s", message.EventType) } @@ -805,22 +834,6 @@ func (p *Provider) handleSequence(ctx context.Context) error { return nil } -func (p *Provider) logTxFailed(err error, txHash string, code uint8) { - p.logger.Error("transaction failed", - zap.Error(err), - zap.String("tx_hash", txHash), - zap.Uint8("code", code), - ) -} - -func (p *Provider) logTxSuccess(height uint64, txHash string) { - p.logger.Info("successful transaction", - zap.Uint64("block_height", height), - zap.String("chain_id", p.cfg.NID), - zap.String("tx_hash", txHash), - ) -} - func (p *Provider) waitForTxResult(ctx context.Context, mk *relayTypes.MessageKey, txHash string, callback relayTypes.TxResponseFunc) { } @@ -1032,6 +1045,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err runeId := "" runeAmount := big.NewInt(0) actionMethod := "" + isMatchAmount := true // handle for bitcoin bridge // decode message from OP_RETURN p.logger.Info("parseMessageFromTx", @@ -1054,57 +1068,20 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err // todo verify transfer amount match in calldata if it // call 3rd to check rune amount tokenId := messageInfo.TokenAddress - amount := big.NewInt(0) - amount.SetBytes(messageInfo.Amount) destContract := messageInfo.To - p.logger.Info("tokenId", zap.String("tokenId", tokenId)) - p.logger.Info("amount", zap.String("amount", amount.String())) p.logger.Info("destContract", zap.String("destContract", destContract)) // call api to verify the data // https://docs.unisat.io/dev/unisat-developer-center/runes/get-utxo-runes-balance - verified := false receiverAddresses = p.extractOutputReceiver(tx.Tx) - for i, out := range tx.Tx.TxOut { - if bytes.Compare(out.PkScript, p.multisigAddrScript) != 0 { - continue - } - - if messageInfo.TokenAddress == BTCToken { - if amount.Cmp(big.NewInt(out.Value)) == 0 { - verified = true - break - } - } else { - runes, err := p.GetUTXORuneBalance(p.cfg.UniSatURL, tx.Tx.TxHash().String(), i, int64(p.cfg.RequestTimeout)) - if err != nil { - return nil, err - } - - if len(runes.Data) == 0 { - continue - } - - for _, runeOut := range runes.Data { - runeTokenBal, ok := big.NewInt(0).SetString(runeOut.Amount, 10) - if !ok { - return nil, fmt.Errorf("rune amount out invalid") - } - - if amount.Cmp(runeTokenBal) == 0 && runeOut.RuneId == messageInfo.TokenAddress { - runeId = runeOut.RuneId - runeAmount = runeTokenBal - verified = true - break - } - } - } - } - - if !verified { - return nil, fmt.Errorf("failed to verify transaction %v", tx.Tx.TxHash().String()) + _runeId, _runeAmount, _isMatchAmount, err := p.verifyBridgeTx(tx, messageInfo) + if err != nil { + return nil, err } + runeId = _runeId + runeAmount = _runeAmount + isMatchAmount = _isMatchAmount } // todo: verify bridge fee @@ -1131,9 +1108,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err data, _ := XcallFormat(decodeMessage, from, bridgeMessage.Receiver, uint(sn.Uint64()), bridgeMessage.Connectors, uint8(messageInfo.MessageType)) relayMessage := &relayTypes.Message{ - Dst: "0x2.icon", - // TODO: - // Dst: chainIdToName[bridgeMessage.ChainId], + Dst: chainIdToName[bridgeMessage.ChainId], Src: p.NID(), Sn: sn, Data: data, @@ -1141,8 +1116,16 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err EventType: events.EmitMessage, } + if !isMatchAmount { + xCallMessage.Action = MethodRefundTo + actionMethod = MethodRefundTo + relayMessage.EventType = events.RollbackMessage + // set dst to the same chain as source for relayer provider detection + relayMessage.Dst = relayMessage.Src + } var senderAddress string // Find sender address to store in db + // todo: check if this is correct for _, address := range receiverAddresses { if address != p.cfg.Address { senderAddress = address @@ -1150,12 +1133,13 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } } + byteAmount := big.NewInt(0).SetBytes(messageInfo.Amount) // When storing the message storedData := StoredMessageData{ OriginalMessage: relayMessage, TxHash: tx.Tx.TxHash().String(), OutputIndex: uint32(tx.TxIndex), - Amount: big.NewInt(0).SetBytes(messageInfo.Amount).Uint64(), + Amount: byteAmount.Uint64(), RecipientAddress: p.cfg.Address, SenderAddress: senderAddress, RuneId: runeId, @@ -1170,14 +1154,69 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err if err != nil { return nil, fmt.Errorf("failed to marshal stored rollback message data: %v", err) } - - err = p.db.Put([]byte("RB"+sn.String()), data, nil) + key := "RB" + sn.String() + err = p.db.Put([]byte(key), data, nil) if err != nil { return nil, fmt.Errorf("failed to store rollback message data: %v", err) } return relayMessage, nil } +func (p *Provider) verifyBridgeTx(tx *TxSearchRes, messageInfo *multisig.XCallMessage) (string, *big.Int, bool, error) { + verified := false + isMatchAmount := false + runeId := "" + runeAmount := big.NewInt(0) + amount := big.NewInt(0) + amount.SetBytes(messageInfo.Amount) + + for i, out := range tx.Tx.TxOut { + if !bytes.Equal(out.PkScript, p.multisigAddrScript) { + continue + } + + if messageInfo.TokenAddress == BTCToken { + verified = true + btcAmount := big.NewInt(out.Value) + if amount.Cmp(btcAmount) == 0 { + isMatchAmount = true + break + } else { + messageInfo.Amount = btcAmount.Bytes() + } + } else { + runes, err := p.GetUTXORuneBalance(p.cfg.UniSatURL, tx.Tx.TxHash().String(), i, int64(p.cfg.RequestTimeout)) + if err != nil { + return "", nil, false, err + } + + if len(runes.Data) == 0 { + continue + } + + for _, runeOut := range runes.Data { + runeTokenBal, ok := big.NewInt(0).SetString(runeOut.Amount, 10) + if !ok { + return "", nil, false, fmt.Errorf("rune amount out invalid") + } + + if amount.Cmp(runeTokenBal) == 0 && runeOut.RuneId == messageInfo.TokenAddress { + runeId = runeOut.RuneId + runeAmount = runeTokenBal + // runes tx is not verified if amount is not match + verified = true + isMatchAmount = true + break + } + } + } + } + if !verified { + return "", nil, false, fmt.Errorf("failed to verify transaction %v", tx.Tx.TxHash().String()) + } + return runeId, runeAmount, isMatchAmount, nil +} + func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayTypes.BlockInfo, error) { var messages []*relayTypes.BlockInfo for _, resultTx := range resultTxList { diff --git a/relayer/chains/bitcoin/provider_test.go b/relayer/chains/bitcoin/provider_test.go index c3c5799a..acf73782 100644 --- a/relayer/chains/bitcoin/provider_test.go +++ b/relayer/chains/bitcoin/provider_test.go @@ -7,10 +7,13 @@ import ( "encoding/json" "fmt" "math/big" + "os" + "path/filepath" "testing" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" "github.com/bxelab/runestone" "github.com/icon-project/centralized-relay/relayer/chains/icon" @@ -18,9 +21,74 @@ import ( "github.com/icon-project/centralized-relay/relayer/events" relayTypes "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" + "github.com/syndtr/goleveldb/leveldb" "go.uber.org/zap" ) +func initBtcProvider() (*Provider, string) { + tempDir, _ := os.MkdirTemp("", "bitcoin_provider_test") + + dbPath := filepath.Join(tempDir, "test.db") + db, _ := leveldb.OpenFile(dbPath, nil) + + logger, _ := zap.NewDevelopment() + + config := &Config{} + config = &Config{ + Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, + UniSatURL: "https://open-api-testnet.unisat.io", + UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", + RecoveryLockTime: 1234, + MasterPubKey: "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2", + Slave1PubKey: "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052", + Slave2PubKey: "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833", + MempoolURL: "https://mempool.space/testnet/api/v1", + SlaveServer1: "http://18.234.252.46:8081", + SlaveServer2: "http://3.81.55.23:8082", + Port: "8080", + RequestTimeout: 1000, + ApiKey: "key", + } + config.NID = "0x2.btc" + config.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" + // config.RPCUrl = "stylish-white-paper.btc-testnet.quiknode.pro/f87ecf84754d9daf8cf45b0334ba3fee9b356db6/" + config.RPCUrl = "http://lydialabs:lydialabsq23%21%40@54.92.152.113:18332" + config.User = "lydialabs" + config.Password = "lydialabsq23!@" + config.MasterPubKey = "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2" + config.Slave1PubKey = "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052" + config.Slave2PubKey = "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833" + config.RelayerPrivKey = "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy" + config.RecoveryLockTime = 1234 + config.OpCode = 0x5e + + connConfig := &rpcclient.ConnConfig{ + Host: config.RPCUrl, + User: config.User, + Pass: config.Password, + HTTPPostMode: true, + DisableTLS: true, + } + client, err := rpcclient.New(connConfig, nil) + if err != nil { + fmt.Println("err: ", err) + return nil, "" + } + + provider := &Provider{ + logger: logger, + db: db, + cfg: config, + client: &Client{client: client, log: logger}, + chainParam: &chaincfg.TestNet3Params, + } + + msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, provider.chainParam) + multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) + provider.multisigAddrScript = multisigAddressScript + return provider, tempDir +} + func TestParseMessageFromTx(t *testing.T) { // Create a mock Provider chainParam := &chaincfg.TestNet3Params @@ -49,14 +117,14 @@ func TestParseMessageFromTx(t *testing.T) { bridgeMsg := multisig.BridgeDecodedMsg{ Message: &multisig.XCallMessage{ MessageType: 0, - Action: "Deposit", + Action: MethodDeposit, TokenAddress: "0:1", To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", // user bitcoin address Amount: new(big.Int).SetUint64(15000).Bytes(), Data: []byte(""), }, - ChainId: 1, + ChainId: 3, Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", // asset manager Connectors: []string{ "cx577f5e756abd89cbcba38a58508b60a12754d2f5", // connector contract @@ -65,9 +133,9 @@ func TestParseMessageFromTx(t *testing.T) { inputs := []*multisig.Input{ { - TxHash: "16de7df933dacd95b0d3af7325a5a2e680a1b7dd447a97e7678d8dfa1ac750b4", - OutputIdx: 4, - OutputAmount: 445000, + TxHash: "af88dfc8907cc9867e83c05ec061472cdff8cc9b9f951282a5e0f6a0b0b7141b", + OutputIdx: 1, + OutputAmount: 909000, PkScript: userMultisigWallet.PKScript, }, } @@ -129,29 +197,13 @@ func TestParseMessageFromTx(t *testing.T) { } func TestParseRuneMessageFromTx(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - logger, _ := zap.NewDevelopment() - provider := &Provider{ - logger: logger, - cfg: &Config{ - Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, - UniSatURL: "https://open-api-testnet.unisat.io", - UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", - }, - chainParam: &chaincfg.TestNet3Params, - bearToken: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", - } - provider.cfg.NID = "0x2.btc" - - provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" - msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) - multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) - provider.multisigAddrScript = multisigAddressScript + btcProvider, termpDir := initBtcProvider() + defer os.Remove(termpDir) // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, btcProvider.chainParam) relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, btcProvider.chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) bridgeMsg := multisig.BridgeDecodedMsg{ @@ -181,9 +233,9 @@ func TestParseRuneMessageFromTx(t *testing.T) { }, // user bitcoin UTXOs to pay tx fee { - TxHash: "16de7df933dacd95b0d3af7325a5a2e680a1b7dd447a97e7678d8dfa1ac750b4", - OutputIdx: 4, - OutputAmount: 445000, + TxHash: "073af76df4d7503446ccf704469926ba584ed6a85df1ffb702d3a148a083bd87", + OutputIdx: 2, + OutputAmount: 2874285, PkScript: userMultisigWallet.PKScript, }, } @@ -236,7 +288,7 @@ func TestParseRuneMessageFromTx(t *testing.T) { TxIndex: 21, BridgeMessage: bridgeMessage, } - relayerMessage, err := provider.parseMessageFromTx(txSearchRes) + relayerMessage, err := btcProvider.parseMessageFromTx(txSearchRes) fmt.Println("relayerMessage Src: ", relayerMessage) // fmt.Println("relayerMessage Sn: ", relayerMessage.Sn) // fmt.Println("relayerMessage Data: ", relayerMessage.Data) @@ -257,27 +309,8 @@ func TestParseRuneMessageFromTx(t *testing.T) { // parse message from icon and build withdraw btc tx func TestBuildWithdrawBtcTxMessage(t *testing.T) { - logger, _ := zap.NewDevelopment() - chainParam := &chaincfg.TestNet3Params - provider := &Provider{ - logger: logger, - cfg: &Config{ - Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, - UniSatURL: "https://open-api-testnet.unisat.io", - UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", - RecoveryLockTime: 1234, - MasterPubKey: "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2", - Slave1PubKey: "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052", - Slave2PubKey: "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833", - }, - chainParam: &chaincfg.TestNet3Params, - } - provider.cfg.NID = "0x2.btc" - - provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" - msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) - multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) - provider.multisigAddrScript = multisigAddressScript + btcProvider, termpDir := initBtcProvider() + defer os.Remove(termpDir) data, _ := base64.StdEncoding.DecodeString("+QEfAbkBG/kBGLMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5kAbhU+FKKV2l0aGRyYXdUb4MwOjG4PnRiMXBnZTh0aHUzdTBreXF3NXY1dmxoamd0eWR6MzJtbWtkeGRnanRsOTlqcjVmNTlxczB5YXhzNTZ3a3l6gicQ+Ei4RjB4Mi5idGMvdGIxcGd6eDg4MHlmcjdxOGRnejhkcWh3NTBzbmN1NGY0aG13NWNuMzgwMDM1NHR1emN5OWp4NXNodnY3c3U=") message := &relayTypes.Message{ @@ -289,13 +322,13 @@ func TestBuildWithdrawBtcTxMessage(t *testing.T) { Data: data, } - msWallet, err := provider.buildMultisigWallet() + msWallet, err := btcProvider.buildMultisigWallet() if err != nil { fmt.Println("err: ", err) return } - inputs, tx, err := provider.buildTxMessage(message, 10, msWallet) + inputs, tx, err := btcProvider.buildTxMessage(message, 10, msWallet) fmt.Println("err: ", err) fmt.Println("inputs: ", inputs) fmt.Println("tx: ", tx) @@ -307,30 +340,9 @@ func TestBuildWithdrawBtcTxMessage(t *testing.T) { // parse message from icon and build withdraw rune tx func TestBuildWithdrawRunesTxMessage(t *testing.T) { - logger, _ := zap.NewDevelopment() - chainParam := &chaincfg.TestNet3Params - provider := &Provider{ - logger: logger, - cfg: &Config{ - Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, - UniSatURL: "https://open-api-testnet.unisat.io", - UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", - RequestTimeout: 10, - RecoveryLockTime: 1234, - MasterPubKey: "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2", - Slave1PubKey: "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052", - Slave2PubKey: "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833", - }, - chainParam: &chaincfg.TestNet3Params, - } - provider.cfg.NID = "0x2.btc" - - provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" - msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) - multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) - provider.multisigAddrScript = multisigAddressScript - - data, _ := base64.StdEncoding.DecodeString("+QEpAbkBJfkBIrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5uAbhe+FyKV2l0aGRyYXdUb4wyOTA0MzU0OjMxMTm4PnRiMXBnZTh0aHUzdTBreXF3NXY1dmxoamd0eWR6MzJtbWtkeGRnanRsOTlqcjVmNTlxczB5YXhzNTZ3a3l6gwENiPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1") + btcProvider, termpDir := initBtcProvider() + defer os.Remove(termpDir) + data, _ := base64.StdEncoding.DecodeString("+QEpAbkBJfkBIrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5uAbhe+FyKV2l0aGRyYXdUb4wyOTA0MzU0OjMxMTm4PnRiMXBneng8ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1") message := &relayTypes.Message{ Src: "0x2.icon", Dst: "0x2.btc", @@ -340,13 +352,13 @@ func TestBuildWithdrawRunesTxMessage(t *testing.T) { Data: data, } - msWallet, err := provider.buildMultisigWallet() + msWallet, err := btcProvider.buildMultisigWallet() if err != nil { fmt.Println("err: ", err) return } - inputs, tx, err := provider.buildTxMessage(message, 10, msWallet) + inputs, tx, err := btcProvider.buildTxMessage(message, 10, msWallet) fmt.Println("err: ", err) fmt.Println("inputs: ", inputs) fmt.Println("tx: ", tx) @@ -355,3 +367,130 @@ func TestBuildWithdrawRunesTxMessage(t *testing.T) { hexSignedTx := hex.EncodeToString(signedTx.Bytes()) fmt.Println("hexSignedTx: ", hexSignedTx) } + +func TestBuildRollbackBtcTxMessage(t *testing.T) { + // Create a mock Provider + btcProvider, termpDir := initBtcProvider() + defer os.Remove(termpDir) + // Create a mock TxSearchRes + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, btcProvider.chainParam, []int{0, 3}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 0, + Action: MethodDeposit, + TokenAddress: "0:1", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", // user bitcoin address + Amount: new(big.Int).SetUint64(15000).Bytes(), + Data: []byte(""), + }, + ChainId: 3, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", // asset manager + Connectors: []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", // connector contract + }, + } + + inputs := []*multisig.Input{ + { + TxHash: "0c95bf20150345ae6e726c986edb8c3019c325ea1049490755191085e3c453fa", + OutputIdx: 6, + OutputAmount: 2607546, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx + totalSigs := [][][]byte{} + // user key 1 sign tx + userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs1) + // user key 2 sign tx + userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs2) + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + signedMsgTxID := signedMsgTx.TxHash().String() + + fmt.Println("hexSignedTx: ", hexSignedTx) + fmt.Println("signedMsgTxID: ", signedMsgTxID) + fmt.Println("err sign: ", err) + + bridgeMessage, err := multisig.ReadBridgeMessage(signedMsgTx) + fmt.Println("bridgeMessage: ", bridgeMessage) + fmt.Println("err: ", err) + txSearchRes := &TxSearchRes{ + Tx: signedMsgTx, + Height: 3181075, + TxIndex: 21, + BridgeMessage: bridgeMessage, + } + relayerMessage, err := btcProvider.parseMessageFromTx(txSearchRes) + if err != nil { + fmt.Println("error: ", err) + } + inputs, msWallet, msgTx, relayerSigs, err := btcProvider.HandleBitcoinMessageTx(relayerMessage) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + totalSigs = [][][]byte{relayerSigs} + // send unsigned raw tx and message sn to 2 slave relayers to get sign + // rsi := slaveRequestParams{ + // MsgSn: relayerMessage.Sn.String(), + // } + + // slaveRequestData, _ := json.Marshal(rsi) + // slaveSigs := btcProvider.CallSlaves(slaveRequestData) + + // totalSigs = append(totalSigs, slaveSigs...) + // combine sigs + signedMsgTx, err = multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + btcProvider.logger.Info("signedMsgTx", zap.Any("transaction", signedMsgTx)) + var buf bytes.Buffer + err = signedMsgTx.Serialize(&buf) + + if err != nil { + btcProvider.logger.Error("error", zap.Error(err)) + } + + txSize := len(buf.Bytes()) + btcProvider.logger.Info("--------------------txSize--------------------", zap.Int("size", txSize)) + signedMsgTxHex := hex.EncodeToString(buf.Bytes()) + btcProvider.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + + txHash, err := btcProvider.client.SendRawTransactionV2(btcProvider.cfg.RPCUrl, signedMsgTxHex) + fmt.Println("txHash: ", txHash) + fmt.Println("err: ", err) +} + +func TestUint64ToBytes(t *testing.T) { + amount := uint64(15010) + bytesAmount := []byte(fmt.Sprintf("%d", amount)) + fmt.Println("bytesAmount: ", bytesAmount) + bigIntAmount := big.NewInt(0).SetBytes(bytesAmount) + fmt.Println("bigIntAmount: ", bigIntAmount.Uint64(), int64(bigIntAmount.Uint64())) +} diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index fbd26de8..0137042b 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -73,7 +73,7 @@ func buildAndSignTxFromDbMessage(sn string, p *Provider) ([][]byte, error) { if strings.Contains(sn, "RB") { p.logger.Info("Rollback message", zap.String("sn", sn)) - return nil, nil + // return nil, nil } var message *relayTypes.Message diff --git a/utils/multisig/bridge_tx.go b/utils/multisig/bridge_tx.go index 7b070f0d..814a01aa 100644 --- a/utils/multisig/bridge_tx.go +++ b/utils/multisig/bridge_tx.go @@ -20,7 +20,7 @@ func CreateBridgeTxSendBitcoin( outputs := []*wire.TxOut{ // bitcoin send to receiver { - Value: new(big.Int).SetBytes(msg.Message.Amount).Int64(), + Value: new(big.Int).SetBytes(msg.Message.Amount).Int64(), PkScript: receiverPkScript, }, } @@ -31,7 +31,7 @@ func CreateBridgeTxSendBitcoin( } for _, script := range bridgeScripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: 0, PkScript: script, }) } @@ -57,8 +57,8 @@ func CreateBridgeTxSendRune( runeOutput := &runestone.Runestone{ Edicts: []runestone.Edict{ { - ID: *runeId, - Amount: uint128.FromBig(new(big.Int).SetBytes(msg.Message.Amount)), + ID: *runeId, + Amount: uint128.FromBig(new(big.Int).SetBytes(msg.Message.Amount)), Output: 0, }, }, @@ -69,17 +69,17 @@ func CreateBridgeTxSendRune( outputs := []*wire.TxOut{ // rune send to receiver { - Value: DUST_UTXO_AMOUNT, + Value: DUST_UTXO_AMOUNT, PkScript: receiverPkScript, }, // rune change output { - Value: DUST_UTXO_AMOUNT, + Value: DUST_UTXO_AMOUNT, PkScript: senderPkScript, }, // rune OP_RETURN { - Value: 0, + Value: 0, PkScript: runeScript, }, } @@ -90,7 +90,7 @@ func CreateBridgeTxSendRune( } for _, script := range bridgeScripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: 0, PkScript: script, }) } From fd4112fffc18134847c17627a7142fa3360bed22 Mon Sep 17 00:00:00 2001 From: Shall Date: Thu, 7 Nov 2024 22:29:06 +0700 Subject: [PATCH 083/113] feat: add doc for bitcoin relayer --- docs/bitcoin-relayer.md | 120 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 docs/bitcoin-relayer.md diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md new file mode 100644 index 00000000..1d3157d4 --- /dev/null +++ b/docs/bitcoin-relayer.md @@ -0,0 +1,120 @@ +# Bitcoin Relayer + +This is a relayer for Bitcoin that allows you to send or receive BTC/Rune from your Bitcoin taproot wallet to your wallet on other chains. + +## Prerequisites + +- Understand the basics of Bitcoin transactions and Multisig taproot wallets +- Understand about Bitcoin RPC and the related APIs (Unisat, Quicknode, etc.) + +## Configuration + +config.yaml is the main configuration file for the Bitcoin relayer. It includes the following sections: + +```yaml +bitcoin: + type: bitcoin + value: + rpc-url: # Bitcoin RPC URL + rpc-user: # Bitcoin RPC User + rpc-password: # Bitcoin RPC Password + address: # Bitcoin Taproot multisig address + unisat-url: # Unisat API URL + unisat-key: # Unisat API Key + network-id: # Bitcoin Network ID (1: Bitcoin Mainnet, 2: Bitcoin Testnet) + op-code: # Bitcoin OP Code (0x5e: default) + finality-block: # Bitcoin Finality Block (10: default) + nid: 0x2.btc # Bitcoin NID (0x1.btc: Bitcoin Mainnet, 0x2.btc: Bitcoin Testnet) + chain-name: bitcoin # Bitcoin Chain Name + mode: master # master or slave + slave-server-1: # Slave Server 1 URL (only used when mode is master) + slave-server-2: # Slave Server 2 URL (only used when mode is master) + port: 8082 # Server Port + api-key: key # Slave Server API Key (Using to authenticate between the master and slave servers) + masterPubKey: # Master Public Key (public key of the master wallet) + slave1PubKey: # Slave 1 Public Key (public key of the slave wallet 1) + slave2PubKey: # Slave 2 Public Key (public key of the slave wallet 2) + relayerPrivKey: # Relayer Private Key (private key of the relayer it depends the deployed server that which start for master/slave1/slave2 server) + recoveryLockTime: # Recovery Lock Time (recovery lock time of the master wallet) + start-height: # Start Height (start height) +``` + +# How it works + +The mechanism of the Bitcoin relayer is based on the master-slave architecture. + +## Relayer Multisig Taproot Wallet + +- Because in Bitcoin network that not support the smart contract, so the Relayer Multisig Taproot Wallet is the wallet that will receive the BTC/Rune, keep them and the logic to handle send and receive BTC/Rune will process based on this wallet + +- The private key of the Relayer Multisig Taproot Wallet was generated from the `relayerPrivKey` in the config.yaml file + +- This Wallet Address was combined from 3 different public keys: the master public key, slave1 public key and slave2 public key + +- To spend token from this wallet, it needs 3 signatures from the 3 public keys (the master public key and one of the slave public keys) + +**_Note: The order of the public keys in the wallet address is important, it must be the same between the order when we generate the Relayer Multisig Taproot Wallet and sign the transaction_** + +## Master Server + +The master server will crawl Bitcoin transaction from the Bitcoin network and check if the transaction is a valid transaction with recipient is Relayer multigsig wallet address and the condition that contain value of OP_RETURN data is the same as the `op-code` (OP_RETURN OP_PUSHNUM_14) in the config.yaml file. +The master server is the main server that handles: + +- Requesting the slave servers to sign the transactions +- Combining the signatures from the slave servers and itself then broadcasting the transaction to the Bitcoin network + +## Slave Servers + +It works as the same with the master server, but the slave servers will not broadcast transaction instead of they crawl transactions and cache them, and waiting for the master request to sign the transactions and send the signature back to the master server. + +## Data Structure + +Based on the XCall message structure, The Bitcoin Relayer was designed and implemented to parse message with structure `OP_RETURN OP_PUSHNUM_14 YOUR _PAYLOAD`. + +Because OP_RETURN is only limited to 80 bytes by Bitcoin Core's default standardness rules, so the payload `(YOUR_PAYLOAD)` will be split into multiple parts with the maximum size of 76 bytes for each part and to grarentee . + +The Bitcoin Relayer will decode the message from the Bitcoin transaction and parse the payload to `BridgeDecodedMsg` data structure. + +```golang +type BridgeDecodedMsg struct { + Message *XCallMessage + ChainId uint8 + Receiver string + Connectors []string +} + +type XCallMessage struct { + MessageType uint8 + Action string + TokenAddress string + From string + To string + Amount []byte + Data []byte +} +``` + +**Example:** + +```golang +bridgeMsg := BridgeDecodedMsg{ + Message: XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "0:1", + To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", + From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", + Amount: new(big.Int).SetUint64(100000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Connectors: []string{ + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + }, + } +``` + +### Deploy the Relayer + +Since the Bitcoin relayer works based on the master-slave architecture, so we need to deploy seperate the master server and at least 2 slave servers, in totally there are 3 servers need to be run at the same time. From c8184607b7712a50ef3974f7e12492f20b3975e1 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Tue, 12 Nov 2024 09:19:52 +0700 Subject: [PATCH 084/113] feat: call sign tx to slave with feeRate --- relayer/chains/bitcoin/client.go | 10 +- relayer/chains/bitcoin/provider.go | 150 ++++++++++++++++++++------- relayer/chains/bitcoin/slave.go | 8 +- relayer/chains/bitcoin/unisat_api.go | 41 ++++++++ utils/multisig/tx.go | 8 +- 5 files changed, 165 insertions(+), 52 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 5700fcfc..196b7b9c 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -20,7 +20,7 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" ) -type FeeResponse struct { +type MempoolFeeResponse struct { FastestFee uint64 `json:"fastestFee"` HalfHourFee uint64 `json:"halfHourFee"` HourFee uint64 `json:"hourFee"` @@ -42,7 +42,7 @@ type IClient interface { DecodeAddress(btcAddr string) ([]byte, error) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearchRes, error) SendRawTransaction(ctx context.Context, url string, rawMsg []json.RawMessage) (string, error) - SendRawTransactionV2(rpcUrl string, txHex string) (string, error) + SendRawTxByRpc(rpcUrl string, txHex string) (string, error) } // grouped rpc api clients @@ -134,7 +134,7 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch // Print the block hash to a string blockHashStr := fmt.Sprintf("%v", blockHash) - c.log.Info("Block Hash", zap.String("blockHash", blockHashStr)) + c.log.Info("Block Hash", zap.String("blockHash", blockHashStr), zap.Uint64("height", i)) block, err := c.client.GetBlock(blockHash) if err != nil { @@ -189,7 +189,7 @@ func (c *Client) SendRawTransaction(ctx context.Context, rpcUrl string, rawMsg [ return string(body), nil } -func (c *Client) SendRawTransactionV2(rpcUrl string, txHex string) (string, error) { +func (c *Client) SendRawTxByRpc(rpcUrl string, txHex string) (string, error) { if len(txHex) == 0 { return "", fmt.Errorf("empty transaction hex") } @@ -233,7 +233,7 @@ func (c *Client) GetFeeFromMempool(mempoolURL string) (uint64, error) { c.log.Error("Error reading response: %v", zap.Error(err)) } - var feeResponse FeeResponse + var feeResponse MempoolFeeResponse if err := json.NewDecoder(resp.Body).Decode(&feeResponse); err != nil { return 0, err } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 3e6d6063..5457967b 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -72,7 +72,8 @@ type CSMessageResult struct { } type slaveRequestParams struct { - MsgSn string `json:"msgSn"` + MsgSn string `json:"msgSn"` + FeeRate int `json:"feeRate"` } type StoredMessageData struct { OriginalMessage *relayTypes.Message @@ -105,6 +106,7 @@ type Config struct { RequestTimeout int `json:"request-timeout" yaml:"request-timeout"` // seconds UniSatURL string `json:"unisat-url" yaml:"unisat-url"` UniSatKey string `json:"unisat-key" yaml:"unisat-key"` + UniSatWalletURL string `json:"unisat-wallet-url" yaml:"unisat-wallet-url"` MempoolURL string `json:"mempool-url" yaml:"mempool-url"` Type string `json:"type" yaml:"type"` User string `json:"rpc-user" yaml:"rpc-user"` @@ -140,7 +142,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri return nil, fmt.Errorf("failed to open or create database: %v", err) } - client, err := newClient(ctx, c.RPCUrl, c.User, c.Password, true, false, log) + client, err := newClient(ctx, c.RPCUrl, c.User, c.Password, true, true, log) if err != nil { db.Close() // Close the database if client creation fails return nil, fmt.Errorf("failed to create new client: %v", err) @@ -267,7 +269,6 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn p.logger.Error("failed to determine start height", zap.Error(err)) return err } - // startHeight := uint64(3082427) pollHeightTicker := time.NewTicker(time.Second * 60) // do scan each 2 mins pollHeightTicker.Stop() @@ -277,16 +278,21 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn for { select { case <-pollHeightTicker.C: - //pollHeightTicker.Stop() - //startHeight = p.GetLastSavedHeight() latestHeight, err = p.QueryLatestHeight(ctx) if err != nil { p.logger.Error("failed to get latest block height", zap.Error(err)) continue } default: - if startHeight < latestHeight { - p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", latestHeight)) + toHeight := latestHeight + if p.cfg.Mode == MasterMode { + // master mode should query slower slave 1 block + // for ensure slave cache tx data before calling to get signed tx + toHeight = latestHeight - 1 + } + + if startHeight < toHeight { + p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", toHeight)) startHeight = p.runBlockQuery(ctx, blockInfoChan, startHeight, latestHeight) } } @@ -316,8 +322,8 @@ func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { return withdrawInfo, withdrawInfoWrapperV2.Data, nil } -func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, timeout int64, addressPkScript []byte) ([]*multisig.Input, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*timeout)) +func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, addressPkScript []byte) ([]*multisig.Input, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*int64(p.cfg.RequestTimeout))) defer cancel() // TODO: loop query until sastified amountRequired resp, err := GetBtcUtxo(ctx, server, p.cfg.UniSatKey, address, 0, 64) @@ -337,6 +343,10 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, if totalAmount >= amountRequired { break } + isSpent, _ := p.isSpentUTXO(utxo.TxId, utxo.Vout) + if isSpent { + continue + } outputAmount := utxo.Satoshi.Int64() inputs = append(inputs, &multisig.Input{ TxHash: utxo.TxId, @@ -350,8 +360,8 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, return inputs, nil } -func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, timeout int64, addressPkScript []byte) ([]*multisig.Input, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*timeout)) +func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, addressPkScript []byte) ([]*multisig.Input, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*int64(p.cfg.RequestTimeout))) defer cancel() // TODO: loop query until sastified amountRequired resp, err := GetRuneUtxo(ctx, server, p.cfg.UniSatKey, address, runeId, 0, 64) @@ -371,15 +381,20 @@ func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired u if totalAmount.Cmp(amountRequired) >= 0 { break } + if len(utxo.Runes) != 1 { + // return nil, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) + continue + } + isSpent, _ := p.isSpentUTXO(utxo.TxId, utxo.Vout) + if isSpent { + continue + } inputs = append(inputs, &multisig.Input{ TxHash: utxo.TxId, OutputIdx: uint32(utxo.Vout), OutputAmount: utxo.Satoshi.Int64(), PkScript: addressPkScript, }) - if len(utxo.Runes) != 1 { - return nil, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) - } runeAmount, _ := uint128.FromString(utxo.Runes[0].Amount) totalAmount = totalAmount.Add(runeAmount) } @@ -387,8 +402,8 @@ func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired u return inputs, nil } -func (p *Provider) GetUTXORuneBalance(server, txId string, index int, timeout int64) (*ResponseUtxoRuneBalance, error) { - ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*timeout)) +func (p *Provider) GetUTXORuneBalance(server, txId string, index int) (*ResponseUtxoRuneBalance, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*int64(p.cfg.RequestTimeout))) defer cancel() resp, err := GetUtxoRuneBalance(ctx, server, p.cfg.UniSatKey, txId, index) if err != nil { @@ -397,6 +412,16 @@ func (p *Provider) GetUTXORuneBalance(server, txId string, index int, timeout in return &resp, nil } +func (p *Provider) GetFastestFee() (int, error) { + ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*int64(p.cfg.RequestTimeout))) + defer cancel() + fastestFee, err := GetFastestFee(ctx, p.cfg.UniSatWalletURL) + if err != nil { + return 0, err + } + return fastestFee, nil +} + func (p *Provider) CreateBitcoinMultisigTx( outputData []*wire.TxOut, feeRate int64, @@ -480,6 +505,9 @@ func (p *Provider) CreateBitcoinMultisigTx( bitcoinAmountRequired = MinSatsRequired * 2 } } else if decodedData.Action == MethodRefundTo { + if decodedData.TokenAddress != BTCToken { + return nil, nil, fmt.Errorf("refund is only supported for btc token, current token: %s", decodedData.TokenAddress) + } uintAmount := amount.Uint64() bitcoinAmountRequired = int64(uintAmount) outputs = []*wire.TxOut{ @@ -497,12 +525,21 @@ func (p *Provider) CreateBitcoinMultisigTx( if err != nil { return nil, nil, err } - if estFee > bitcoinAmountRequired && decodedData.Action == MethodRefundTo { - return nil, nil, fmt.Errorf("estimated fee is greater than the amount") + + if decodedData.Action == MethodRefundTo { + if estFee >= bitcoinAmountRequired { + return nil, nil, fmt.Errorf("estimated fee is greater than the amount") + } else { + for _, output := range outputs { + if bytes.Equal(output.PkScript, receiverPkScript) { + output.Value = bitcoinAmountRequired - estFee + break + } + } + } } // create raw tx msgTx, err := multisig.CreateTx(inputs, outputs, msWallet.PKScript, estFee, 0) - // msgTx, hexRawTx, txSigHashes, err := multisig.CreateMultisigTx(inputs, outputs, estFee, msWallet, nil, p.chainParam, msAddressStr, 0) return inputs, msgTx, err } @@ -577,7 +614,7 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 inputs := []*multisig.Input{} if !runeToSend.IsZero() { // query rune UTXOs from unisat - runeInputs, err := p.GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, int64(p.cfg.RequestTimeout), addressPkScript) + runeInputs, err := p.GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, addressPkScript) if err != nil { return nil, err } @@ -586,7 +623,7 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 // TODO: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo // query bitcoin UTXOs from unisat - bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, address, satToSend, int64(p.cfg.RequestTimeout), addressPkScript) + bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, address, satToSend, addressPkScript) if err != nil { return nil, err } @@ -617,35 +654,37 @@ func (p *Provider) buildMultisigWallet() (*multisig.MultisigWallet, error) { return msWallet, nil } -func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message) ([]*multisig.Input, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, error) { +func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message, feeRate int) ([]*multisig.Input, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, int, error) { msWallet, err := p.buildMultisigWallet() if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, 0, err } - feeRate, err := p.client.GetFeeFromMempool(p.cfg.MempoolURL + "/fees/recommended") - if err != nil { - p.logger.Error("failed to get recommended fee from mempool", zap.Error(err)) - feeRate = 1 + if feeRate == 0 { + feeRate, err = p.GetFastestFee() + if err != nil { + p.logger.Error("failed to get fastest fee from unisat", zap.Error(err)) + feeRate = 1 + } } inputs, msgTx, err := p.buildTxMessage(message, int64(feeRate), msWallet) if err != nil { p.logger.Error("failed to build tx message: %v", zap.Error(err)) - return nil, nil, nil, nil, err + return nil, nil, nil, nil, 0, err } relayerSigs, err := multisig.SignTapMultisig(p.cfg.RelayerPrivKey, msgTx, inputs, msWallet, 0) if err != nil { p.logger.Error("failed to sign tx message: %v", zap.Error(err)) - return nil, nil, nil, nil, err + return nil, nil, nil, nil, 0, err } - return inputs, msWallet, msgTx, relayerSigs, err + return inputs, msWallet, msgTx, relayerSigs, feeRate, err } func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { p.logger.Info("starting to route message", zap.Any("message", message)) messageDstDetail := strings.Split(message.Dst, ".") - if strings.Split(message.Src, ".")[1] == "icon" && messageDstDetail[1] == "btc" { - + messageSrcDetail := strings.Split(message.Src, ".") + if (messageSrcDetail[1] == "icon" || messageSrcDetail[1] == "btc") && messageDstDetail[1] == "btc" { if p.cfg.Mode == SlaveMode { // store the message in LevelDB key := []byte(message.Sn.String()) @@ -659,7 +698,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb return nil } else if p.cfg.Mode == MasterMode { - inputs, msWallet, msgTx, relayerSigs, err := p.HandleBitcoinMessageTx(message) + inputs, msWallet, msgTx, relayerSigs, feeRate, err := p.HandleBitcoinMessageTx(message, 0) if err != nil { p.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) return err @@ -667,7 +706,8 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb totalSigs := [][][]byte{relayerSigs} // send unsigned raw tx and message sn to 2 slave relayers to get sign rsi := slaveRequestParams{ - MsgSn: message.Sn.String(), + MsgSn: message.Sn.String(), + FeeRate: feeRate, } slaveRequestData, _ := json.Marshal(rsi) @@ -693,22 +733,51 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb signedMsgTxHex := hex.EncodeToString(buf.Bytes()) p.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + p.cacheSpentUTXOs(inputs) + // Broadcast transaction to bitcoin network // txHash, err := p.client.SendRawTransaction(ctx, p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(`"` + signedMsgTxHex + `"`)}) - txHash, err := p.client.SendRawTransactionV2(p.cfg.RPCUrl, signedMsgTxHex) + + txHash, err := p.client.SendRawTxByRpc(p.cfg.RPCUrl, signedMsgTxHex) if err != nil { + p.removeCachedSpentUTXOs(inputs) p.logger.Error("failed to send raw transaction", zap.Error(err)) return err } p.logger.Info("txHash", zap.String("transaction_hash", txHash)) - // TODO: After successful broadcast, request slaves to remove the message from LevelDB if it exists } } return nil } +func (p *Provider) cacheSpentUTXOs(inputs []*multisig.Input) { + prefix := fmt.Sprintf("%s_utxo_spent", p.cfg.NID) + for _, input := range inputs { + key := fmt.Sprintf("%s_%s_%d", prefix, input.TxHash, input.OutputIdx) + p.db.Put([]byte(key), []byte{1}, nil) + } +} + +func (p *Provider) removeCachedSpentUTXOs(inputs []*multisig.Input) { + prefix := fmt.Sprintf("%s_utxo_spent", p.cfg.NID) + for _, input := range inputs { + key := fmt.Sprintf("%s_%s_%d", prefix, input.TxHash, input.OutputIdx) + p.db.Delete([]byte(key), nil) + } +} + +func (p *Provider) isSpentUTXO(txHash string, outputIdx int) (bool, error) { + prefix := fmt.Sprintf("%s_utxo_spent", p.cfg.NID) + key := fmt.Sprintf("%s_%s_%d", prefix, txHash, outputIdx) + data, err := p.db.Get([]byte(key), nil) + if err != nil { + return false, err + } + return len(data) > 0, nil +} + // TODO: Implement proper callback handling // callback(message.MessageKey(), txResponse, nil) @@ -734,7 +803,7 @@ func (p *Provider) decodeMessage(message *relayTypes.Message) (CSMessageResult, func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, msWallet *multisig.MultisigWallet) ([]*multisig.Input, *wire.MsgTx, error) { outputs := []*wire.TxOut{} decodedData := &MessageDecoded{} - + fmt.Println("eventType: ", message.EventType) switch message.EventType { case events.EmitMessage: messageDecoded, err := p.decodeMessage(message) @@ -766,10 +835,10 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms Action: storedData.ActionMethod, To: storedData.SenderAddress, TokenAddress: storedData.TokenAddress, - Amount: []byte(fmt.Sprintf("%d", storedData.Amount)), + Amount: uint64ToBytes(storedData.Amount), } if storedData.RuneId != "" { - decodedData.Amount = []byte(fmt.Sprintf("%d", storedData.RuneAmount)) + decodedData.Amount = uint64ToBytes(storedData.RuneAmount) } } else { // Perform WithdrawData @@ -1155,6 +1224,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err return nil, fmt.Errorf("failed to marshal stored rollback message data: %v", err) } key := "RB" + sn.String() + p.logger.Info("stored rollback message key", zap.String("key", key)) err = p.db.Put([]byte(key), data, nil) if err != nil { return nil, fmt.Errorf("failed to store rollback message data: %v", err) @@ -1185,7 +1255,7 @@ func (p *Provider) verifyBridgeTx(tx *TxSearchRes, messageInfo *multisig.XCallMe messageInfo.Amount = btcAmount.Bytes() } } else { - runes, err := p.GetUTXORuneBalance(p.cfg.UniSatURL, tx.Tx.TxHash().String(), i, int64(p.cfg.RequestTimeout)) + runes, err := p.GetUTXORuneBalance(p.cfg.UniSatURL, tx.Tx.TxHash().String(), i) if err != nil { return "", nil, false, err } diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index 0137042b..1eb070c4 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -53,7 +53,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { http.Error(w, "Error decoding request body", http.StatusInternalServerError) return } - sigs, _ := buildAndSignTxFromDbMessage(rsi.MsgSn, p) + sigs, _ := buildAndSignTxFromDbMessage(rsi.MsgSn, rsi.FeeRate, p) // return sigs to master returnData, _ := json.Marshal(sigs) w.Write(returnData) @@ -63,7 +63,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { } } -func buildAndSignTxFromDbMessage(sn string, p *Provider) ([][]byte, error) { +func buildAndSignTxFromDbMessage(sn string, feeRate int, p *Provider) ([][]byte, error) { p.logger.Info("Slave start to build and sign tx from db message", zap.String("sn", sn)) key := sn data, err := p.db.Get([]byte(key), nil) @@ -73,7 +73,7 @@ func buildAndSignTxFromDbMessage(sn string, p *Provider) ([][]byte, error) { if strings.Contains(sn, "RB") { p.logger.Info("Rollback message", zap.String("sn", sn)) - // return nil, nil + return nil, nil } var message *relayTypes.Message @@ -82,7 +82,7 @@ func buildAndSignTxFromDbMessage(sn string, p *Provider) ([][]byte, error) { return nil, err } - _, _, _, relayerSigns, err := p.HandleBitcoinMessageTx(message) + _, _, _, relayerSigns, _, err := p.HandleBitcoinMessageTx(message, feeRate) if err != nil { return nil, err } diff --git a/relayer/chains/bitcoin/unisat_api.go b/relayer/chains/bitcoin/unisat_api.go index 75232c5b..9ba348b7 100644 --- a/relayer/chains/bitcoin/unisat_api.go +++ b/relayer/chains/bitcoin/unisat_api.go @@ -213,6 +213,22 @@ type ResponseUtxoRuneBalance struct { Data []RuneDetail `json:"data"` } +type ResponseFeeSummary struct { + Code int `json:"code"` + Message string `json:"msg"` + Data FeeSummary `json:"data"` +} + +type FeeSummary struct { + List []FeeSummaryDetail `json:"list"` +} + +type FeeSummaryDetail struct { + Title string `json:"title"` + FeeRate int `json:"feeRate"` + Desc string `json:"desc"` +} + func BtcUtxoUrl(server, address string, offset, limit int64) string { return fmt.Sprintf("%s/v1/indexer/address/%s/utxo-data?cursor=%d&size=%d", server, address, offset, limit) } @@ -225,6 +241,10 @@ func UtxoRuneBalanceUrl(server, txId string, index int) string { return fmt.Sprintf("%s/v1/indexer/runes/utxo/%s/%d/balance", server, txId, index) } +func FeeSummaryUrl(server string) string { + return fmt.Sprintf("%s/v5/default/fee-summary", server) +} + func GetWithHeader(ctx context.Context, url string, header map[string]string, response interface{}) error { req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { @@ -275,3 +295,24 @@ func GetUtxoRuneBalance(ctx context.Context, server, bear, txId string, index in err := GetWithBear(ctx, url, bear, &resp) return resp, err } + +func GetFeeSummary(ctx context.Context, server string) (ResponseFeeSummary, error) { + var resp ResponseFeeSummary + url := FeeSummaryUrl(server) + err := GetWithHeader(ctx, url, nil, &resp) + return resp, err +} + +func GetFastestFee(ctx context.Context, server string) (int, error) { + resp, err := GetFeeSummary(ctx, server) + if err != nil { + return 0, err + } + fastestFee := resp.Data.List[0].FeeRate + for _, detail := range resp.Data.List { + if detail.Title == "Fast" { + fastestFee = detail.FeeRate + } + } + return fastestFee, nil +} diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index 3e0916b1..f1ec2470 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -6,10 +6,10 @@ import ( "fmt" "strings" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/btcsuite/btcd/btcutil" ) func TransposeSigs(sigs [][][]byte) [][][]byte { @@ -22,7 +22,9 @@ func TransposeSigs(sigs [][][]byte) [][][]byte { } for i := 0; i < xl; i++ { for j := 0; j < yl; j++ { - result[i][j] = sigs[j][i] + if len(sigs[j]) > i { + result[i][j] = sigs[j][i] + } } } @@ -157,7 +159,7 @@ func CombineTapMultisig( if bytes.Equal(inputs[idx].PkScript, multisigWallet.PKScript) { reverseV := [][]byte{} for i := len(v) - 1; i >= 0; i-- { - if (len(v[i]) != 0) { + if len(v[i]) != 0 { reverseV = append(reverseV, v[i]) } } From 626433de753d16fa21663f4f5f63f57b910366cc Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Tue, 12 Nov 2024 16:49:27 +0700 Subject: [PATCH 085/113] fix: set rune amount when withdraw --- relayer/chains/bitcoin/provider.go | 20 ++++++++++++++++---- relayer/chains/icon/route.go | 2 +- relayer/provider/provider.go | 19 ++++++++++--------- utils/multisig/constants.go | 12 ++++++------ 4 files changed, 33 insertions(+), 20 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 5457967b..1b84b475 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -46,7 +46,7 @@ var ( MasterMode = "master" SlaveMode = "slave" BtcDB = "btc.db" - MinSatsRequired int64 = 1000 + MinSatsRequired int64 = 546 WitnessSize = 125 ) @@ -473,7 +473,7 @@ func (p *Provider) CreateBitcoinMultisigTx( Edicts: []runestone.Edict{ { ID: *runeRequired, - Amount: uint128.FromBig(amount), + Amount: runeAmountRequired, Output: 0, }, }, @@ -618,6 +618,9 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 if err != nil { return nil, err } + if len(runeInputs) == 0 { + return nil, fmt.Errorf("no rune UTXOs found") + } inputs = append(inputs, runeInputs...) } @@ -627,6 +630,9 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 if err != nil { return nil, err } + if len(bitcoinInputs) == 0 { + return nil, fmt.Errorf("no bitcoin UTXOs found") + } inputs = append(inputs, bitcoinInputs...) return inputs, nil @@ -694,7 +700,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Error("failed to store message in LevelDB: %v", zap.Error(err)) return err } - p.logger.Info("Message stored in LevelDB", zap.String("key", string(key))) + p.logger.Info("Message stored in LevelDB", zap.String("key", string(key)), zap.Any("message", message)) return nil } else if p.cfg.Mode == MasterMode { @@ -738,7 +744,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb // Broadcast transaction to bitcoin network // txHash, err := p.client.SendRawTransaction(ctx, p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(`"` + signedMsgTxHex + `"`)}) - txHash, err := p.client.SendRawTxByRpc(p.cfg.RPCUrl, signedMsgTxHex) + txHash, err := p.client.SendRawTxByRpc(p.cfg.BroadcastTxUrl, signedMsgTxHex) if err != nil { p.removeCachedSpentUTXOs(inputs) p.logger.Error("failed to send raw transaction", zap.Error(err)) @@ -1229,6 +1235,9 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err if err != nil { return nil, fmt.Errorf("failed to store rollback message data: %v", err) } + if p.cfg.Mode == SlaveMode { + return nil, nil + } return relayMessage, nil } @@ -1294,6 +1303,9 @@ func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayT if err != nil { return nil, err } + if msg == nil { + continue + } msg.MessageHeight = resultTx.Height p.logger.Info("Detected eventlog", diff --git a/relayer/chains/icon/route.go b/relayer/chains/icon/route.go index 45cc098e..b06d99b4 100644 --- a/relayer/chains/icon/route.go +++ b/relayer/chains/icon/route.go @@ -13,7 +13,7 @@ import ( func (p *Provider) Route(ctx context.Context, message *providerTypes.Message, callback providerTypes.TxResponseFunc) error { // TODO: remove this after testing - if message.Src == "0x2.icon" || message.Dst == "0x2.icon" { + if (message.Src == "0x2.icon" || message.Src == "0x2.btc") && message.Dst == "0x2.icon" { p.log.Info("starting to route message", zap.Any("message", message)) iconMessage, err := p.MakeIconMessage(message) diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 9b8cb8aa..3c8605ef 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -53,15 +53,16 @@ type ChainProvider interface { // CommonConfig is the common configuration for all chain providers type CommonConfig struct { - ChainName string `json:"-" yaml:"-"` - RPCUrl string `json:"rpc-url" yaml:"rpc-url"` - StartHeight uint64 `json:"start-height" yaml:"start-height"` - Address string `json:"address" yaml:"address"` - Contracts types.ContractConfigMap `json:"contracts" yaml:"contracts"` - FinalityBlock uint64 `json:"finality-block" yaml:"finality-block"` - NID string `json:"nid" yaml:"nid"` - HomeDir string `json:"-" yaml:"-"` - Disabled bool `json:"disabled" yaml:"disabled"` + ChainName string `json:"-" yaml:"-"` + RPCUrl string `json:"rpc-url" yaml:"rpc-url"` + BroadcastTxUrl string `json:"broadcast-tx-url" yaml:"broadcast-tx-url"` + StartHeight uint64 `json:"start-height" yaml:"start-height"` + Address string `json:"address" yaml:"address"` + Contracts types.ContractConfigMap `json:"contracts" yaml:"contracts"` + FinalityBlock uint64 `json:"finality-block" yaml:"finality-block"` + NID string `json:"nid" yaml:"nid"` + HomeDir string `json:"-" yaml:"-"` + Disabled bool `json:"disabled" yaml:"disabled"` } // Enabled returns true if the provider is enabled diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 5fb1a920..77377250 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,9 +1,9 @@ package multisig -const( - MIN_SAT = 100 - SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" - DUST_UTXO_AMOUNT int64 = 1000 - +const ( + MIN_SAT = 100 + SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" + DUST_UTXO_AMOUNT int64 = 546 + PART_LIMIT = 76 -) \ No newline at end of file +) From 5f93683d6306c2af8b0b93ec561b4850971c37d2 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Fri, 15 Nov 2024 11:11:38 +0700 Subject: [PATCH 086/113] feat: remove opreturn in bridge message --- relayer/chains/bitcoin/client.go | 60 +------- relayer/chains/bitcoin/provider.go | 216 ++++++++++++----------------- relayer/provider/provider.go | 19 ++- utils/multisig/bridge_script.go | 12 +- utils/multisig/bridge_tx.go | 27 ++-- utils/multisig/constants.go | 10 +- 6 files changed, 116 insertions(+), 228 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index 196b7b9c..cf229a5a 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -38,11 +38,9 @@ type IClient interface { Subscribe(ctx context.Context, _, query string) error Unsubscribe(ctx context.Context, _, query string) error GetFee(ctx context.Context) (uint64, error) - GetFeeFromMempool(mempoolURL string) (uint64, error) DecodeAddress(btcAddr string) ([]byte, error) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearchRes, error) - SendRawTransaction(ctx context.Context, url string, rawMsg []json.RawMessage) (string, error) - SendRawTxByRpc(rpcUrl string, txHex string) (string, error) + SendRawTransaction(url string, rawMsg []json.RawMessage) (string, error) } // grouped rpc api clients @@ -168,12 +166,12 @@ func (c *Client) DecodeAddress(btcAddr string) ([]byte, error) { return destinationAddrByte, nil } -func (c *Client) SendRawTransaction(ctx context.Context, rpcUrl string, rawMsg []json.RawMessage) (string, error) { +func (c *Client) SendRawTransaction(url string, rawMsg []json.RawMessage) (string, error) { if len(rawMsg) == 0 { return "", fmt.Errorf("empty raw message") } - resp, err := http.Post(rpcUrl, "text/plain", bytes.NewReader(rawMsg[0])) + resp, err := http.Post(url, "text/plain", bytes.NewReader(rawMsg[0])) if err != nil { c.log.Error("failed to send transaction", zap.Error(err)) return "", err @@ -188,55 +186,3 @@ func (c *Client) SendRawTransaction(ctx context.Context, rpcUrl string, rawMsg [ return string(body), nil } - -func (c *Client) SendRawTxByRpc(rpcUrl string, txHex string) (string, error) { - if len(txHex) == 0 { - return "", fmt.Errorf("empty transaction hex") - } - - payload := fmt.Sprintf(`{"jsonrpc":"1.0","method":"sendrawtransaction","params":["%s"]}`, txHex) - resp, err := http.Post(rpcUrl, "text/plain", bytes.NewReader([]byte(payload))) - if err != nil { - c.log.Error("failed to send transaction", zap.Error(err)) - return "", err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil || resp.StatusCode != http.StatusOK { - c.log.Error("failed to broadcast transaction", zap.Int("status", resp.StatusCode), zap.String("response", string(body))) - return "", fmt.Errorf("broadcast failed: %v", err) - } - - return string(body), nil -} - -func (c *Client) GetFeeFromMempool(mempoolURL string) (uint64, error) { - - client := &http.Client{} - - req, err := http.NewRequest("GET", mempoolURL, nil) - - if err != nil { - c.log.Error("Failed to create request: %v", zap.Error(err)) - } - - resp, err := client.Do(req) - - if err != nil { - c.log.Error("Failed to send request: %v", zap.Error(err)) - } - - defer resp.Body.Close() - - if err != nil { - c.log.Error("Error reading response: %v", zap.Error(err)) - } - - var feeResponse MempoolFeeResponse - if err := json.NewDecoder(resp.Body).Decode(&feeResponse); err != nil { - return 0, err - } - - return feeResponse.FastestFee, nil -} diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 1b84b475..23debe7e 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -39,15 +39,16 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) var ( - BTCToken = "0:1" - MethodDeposit = "Deposit" - MethodWithdrawTo = "WithdrawTo" - MethodRefundTo = "RefundTo" - MasterMode = "master" - SlaveMode = "slave" - BtcDB = "btc.db" - MinSatsRequired int64 = 546 - WitnessSize = 125 + BTCToken = "0:1" + MethodDeposit = "Deposit" + MethodWithdrawTo = "WithdrawTo" + MethodRefundTo = "RefundTo" + MethodRollback = "Rollback" + MasterMode = "master" + SlaveMode = "slave" + BtcDB = "btc.db" + // MinSatsRequired int64 = 300 + WitnessSize = 125 ) var chainIdToName = map[uint8]string{ @@ -142,7 +143,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri return nil, fmt.Errorf("failed to open or create database: %v", err) } - client, err := newClient(ctx, c.RPCUrl, c.User, c.Password, true, true, log) + client, err := newClient(ctx, c.RPCUrl, c.User, c.Password, true, false, log) if err != nil { db.Close() // Close the database if client creation fails return nil, fmt.Errorf("failed to create new client: %v", err) @@ -299,29 +300,6 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn } } -func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { - withdrawInfoWrapper := CSMessage{} - _, err := codec.RLP.UnmarshalFromBytes(input, &withdrawInfoWrapper) - if err != nil { - log.Fatal(err.Error()) - } - - // withdraw info data - withdrawInfoWrapperV2 := CSMessageRequestV2{} - _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapper.Payload, &withdrawInfoWrapperV2) - if err != nil { - log.Fatal(err.Error()) - } - // withdraw info - withdrawInfo := &MessageDecoded{} - _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapperV2.Data, &withdrawInfo) - if err != nil { - log.Fatal(err.Error()) - } - - return withdrawInfo, withdrawInfoWrapperV2.Data, nil -} - func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, addressPkScript []byte) ([]*multisig.Input, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*int64(p.cfg.RequestTimeout))) defer cancel() @@ -487,12 +465,12 @@ func (p *Provider) CreateBitcoinMultisigTx( outputs = []*wire.TxOut{ // rune send to receiver { - Value: MinSatsRequired, + Value: multisig.RUNE_DUST_UTXO_AMOUNT, PkScript: receiverPkScript, }, // rune change output { - Value: MinSatsRequired, + Value: multisig.RUNE_DUST_UTXO_AMOUNT, PkScript: msWallet.PKScript, }, // rune OP_RETURN @@ -502,7 +480,7 @@ func (p *Provider) CreateBitcoinMultisigTx( }, } - bitcoinAmountRequired = MinSatsRequired * 2 + bitcoinAmountRequired = multisig.RUNE_DUST_UTXO_AMOUNT * 2 } } else if decodedData.Action == MethodRefundTo { if decodedData.TokenAddress != BTCToken { @@ -742,9 +720,7 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.cacheSpentUTXOs(inputs) // Broadcast transaction to bitcoin network - // txHash, err := p.client.SendRawTransaction(ctx, p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(`"` + signedMsgTxHex + `"`)}) - - txHash, err := p.client.SendRawTxByRpc(p.cfg.BroadcastTxUrl, signedMsgTxHex) + txHash, err := p.client.SendRawTransaction(p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(signedMsgTxHex)}) if err != nil { p.removeCachedSpentUTXOs(inputs) p.logger.Error("failed to send raw transaction", zap.Error(err)) @@ -784,9 +760,6 @@ func (p *Provider) isSpentUTXO(txHash string, outputIdx int) (bool, error) { return len(data) > 0, nil } -// TODO: Implement proper callback handling -// callback(message.MessageKey(), txResponse, nil) - func (p *Provider) decodeMessage(message *relayTypes.Message) (CSMessageResult, error) { wrapperInfo := CSMessage{} @@ -806,6 +779,52 @@ func (p *Provider) decodeMessage(message *relayTypes.Message) (CSMessageResult, return messageDecoded, nil } +func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { + withdrawInfoWrapper := CSMessage{} + _, err := codec.RLP.UnmarshalFromBytes(input, &withdrawInfoWrapper) + if err != nil { + log.Fatal(err.Error()) + } + + // withdraw info data + withdrawInfoWrapperV2 := CSMessageRequestV2{} + _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapper.Payload, &withdrawInfoWrapperV2) + if err != nil { + log.Fatal(err.Error()) + } + // withdraw info + withdrawInfo := &MessageDecoded{} + _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapperV2.Data, &withdrawInfo) + if err != nil { + log.Fatal(err.Error()) + } + + return withdrawInfo, withdrawInfoWrapperV2.Data, nil +} + +func (p *Provider) storedDataToMessageDecoded(sn string) (*MessageDecoded, []byte, error) { + data, err := p.db.Get([]byte("RB"+sn), nil) + if err != nil { + return nil, nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) + } + var storedData StoredMessageData + err = json.Unmarshal(data, &storedData) + if err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal stored rollback message data: %v", err) + } + decodedData := &MessageDecoded{ + Action: storedData.ActionMethod, + To: storedData.SenderAddress, + TokenAddress: storedData.TokenAddress, + Amount: uint64ToBytes(storedData.Amount), + } + if storedData.RuneId != "" { + decodedData.Amount = uint64ToBytes(storedData.RuneAmount) + } + decodeDataBuffer, _ := codec.RLP.MarshalToBytes(decodedData) + return decodedData, decodeDataBuffer, nil +} + func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, msWallet *multisig.MultisigWallet) ([]*multisig.Input, *wire.MsgTx, error) { outputs := []*wire.TxOut{} decodedData := &MessageDecoded{} @@ -828,63 +847,38 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms // message code 0 is need to rollback // Process RollbackMessage p.logger.Info("Detected rollback message", zap.String("sn", messageDecoded.Sn.String())) - data, err := p.db.Get([]byte("RB"+messageDecoded.Sn.String()), nil) - if err != nil { - return nil, nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) - } - var storedData StoredMessageData - err = json.Unmarshal(data, &storedData) + messageDecoded, decodeDataBuffer, err := p.storedDataToMessageDecoded(messageDecoded.Sn.String()) if err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal stored rollback message data: %v", err) - } - decodedData = &MessageDecoded{ - Action: storedData.ActionMethod, - To: storedData.SenderAddress, - TokenAddress: storedData.TokenAddress, - Amount: uint64ToBytes(storedData.Amount), - } - if storedData.RuneId != "" { - decodedData.Amount = uint64ToBytes(storedData.RuneAmount) + p.logger.Error("failed to get decode data: %v", zap.Error(err)) + return nil, nil, err } + scripts, _ := multisig.EncodePayloadToScripts(decodeDataBuffer) + outputs = multisig.BuildBridgeScriptsOutputs(outputs, scripts) + decodedData = messageDecoded } else { // Perform WithdrawData - data, opreturnData, err := decodeWithdrawToMessage(message.Data) + data, opBufferData, err := decodeWithdrawToMessage(message.Data) decodedData = data if err != nil { p.logger.Error("failed to decode message: %v", zap.Error(err)) return nil, nil, err } - scripts, _ := multisig.EncodePayloadToScripts(opreturnData) - for _, script := range scripts { - outputs = append(outputs, &wire.TxOut{ - Value: 0, - PkScript: script, - }) - } + scripts, _ := multisig.EncodePayloadToScripts(opBufferData) + outputs = multisig.BuildBridgeScriptsOutputs(outputs, scripts) } case events.RollbackMessage: - p.logger.Info("Detected rollback from wrong message", zap.String("sn", message.Sn.String())) - key := "RB" + message.Sn.String() - data, err := p.db.Get([]byte(key), nil) - if err != nil { - return nil, nil, fmt.Errorf("failed to retrieve stored rollback message data: %v", err) - } - var storedData StoredMessageData - err = json.Unmarshal(data, &storedData) + p.logger.Info("Detected refund message", zap.String("sn", message.Sn.String())) + messageDecoded, decodeDataBuffer, err := p.storedDataToMessageDecoded(message.Sn.String()) if err != nil { - return nil, nil, fmt.Errorf("failed to unmarshal stored rollback message data: %v", err) - } - - // only rollback if tokenAddress is BTC - if storedData.TokenAddress != BTCToken { - return nil, nil, fmt.Errorf("only support rollback for BTC") + p.logger.Error("failed to get decode data: %v", zap.Error(err)) + return nil, nil, err } - decodedData = &MessageDecoded{ - Action: storedData.ActionMethod, - To: storedData.SenderAddress, - TokenAddress: storedData.TokenAddress, - Amount: uint64ToBytes(storedData.Amount), + if messageDecoded.TokenAddress != BTCToken { + return nil, nil, fmt.Errorf("only support refund for BTC") } + decodedData = messageDecoded + scripts, _ := multisig.EncodePayloadToScripts(decodeDataBuffer) + outputs = multisig.BuildBridgeScriptsOutputs(outputs, scripts) default: return nil, nil, fmt.Errorf("unknown event type: %s", message.EventType) @@ -993,13 +987,6 @@ func (p *Provider) ClaimFee(ctx context.Context) error { // GetFee returns the fee for the given networkID // responseFee is used to determine if the fee should be returned func (p *Provider) GetFee(ctx context.Context, networkID string, responseFee bool) (uint64, error) { - //getFee := types.NewExecGetFee(networkID, responseFee) - //data, err := jsoniter.Marshal(getFee) - //if err != nil { - // return 0, err - //} - //return p.client.GetFee(ctx, p.cfg.Contracts[relayTypes.ConnectionContract], data) - return 0, nil } @@ -1050,35 +1037,6 @@ func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64 return heightChan } -func (p *Provider) getBlockInfoStream(ctx context.Context, done <-chan bool, heightStreamChan <-chan *HeightRange) <-chan interface{} { - blockInfoStream := make(chan interface{}) - go func(blockInfoChan chan interface{}, heightChan <-chan *HeightRange) { - defer close(blockInfoChan) - for { - select { - case <-done: - return - case height, ok := <-heightChan: - if ok { - for { - messages, err := p.fetchBlockMessages(ctx, height) - if err != nil { - p.logger.Error("failed to fetch block messages", zap.Error(err), zap.Any("height", height)) - time.Sleep(time.Second * 3) - } else { - for _, message := range messages { - blockInfoChan <- message - } - break - } - } - } - } - } - }(blockInfoStream, heightStreamChan) - return blockInfoStream -} - func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { var ( @@ -1119,7 +1077,6 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err receiverAddresses := []string{} runeId := "" runeAmount := big.NewInt(0) - actionMethod := "" isMatchAmount := true // handle for bitcoin bridge // decode message from OP_RETURN @@ -1138,7 +1095,6 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } if messageInfo.Action == MethodDeposit && isValidConnector { - actionMethod = MethodDeposit // maybe get this function name from cf file // todo verify transfer amount match in calldata if it // call 3rd to check rune amount @@ -1159,12 +1115,6 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err isMatchAmount = _isMatchAmount } - // todo: verify bridge fee - - // parse message - - // todo: handle for rad fi - // TODO: call xcallformat and then replace to data sn := new(big.Int).SetUint64(tx.Height<<32 + tx.TxIndex) @@ -1191,13 +1141,17 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err EventType: events.EmitMessage, } + actionMethod := MethodRollback + + // validate message amount failed -> refund to user if !isMatchAmount { - xCallMessage.Action = MethodRefundTo actionMethod = MethodRefundTo + // only set rollbackMessage because eventType variable can not be changed relayMessage.EventType = events.RollbackMessage // set dst to the same chain as source for relayer provider detection relayMessage.Dst = relayMessage.Src } + var senderAddress string // Find sender address to store in db // todo: check if this is correct @@ -1209,7 +1163,7 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } byteAmount := big.NewInt(0).SetBytes(messageInfo.Amount) - // When storing the message + // stored message for rollback and refund case storedData := StoredMessageData{ OriginalMessage: relayMessage, TxHash: tx.Tx.TxHash().String(), diff --git a/relayer/provider/provider.go b/relayer/provider/provider.go index 3c8605ef..9b8cb8aa 100644 --- a/relayer/provider/provider.go +++ b/relayer/provider/provider.go @@ -53,16 +53,15 @@ type ChainProvider interface { // CommonConfig is the common configuration for all chain providers type CommonConfig struct { - ChainName string `json:"-" yaml:"-"` - RPCUrl string `json:"rpc-url" yaml:"rpc-url"` - BroadcastTxUrl string `json:"broadcast-tx-url" yaml:"broadcast-tx-url"` - StartHeight uint64 `json:"start-height" yaml:"start-height"` - Address string `json:"address" yaml:"address"` - Contracts types.ContractConfigMap `json:"contracts" yaml:"contracts"` - FinalityBlock uint64 `json:"finality-block" yaml:"finality-block"` - NID string `json:"nid" yaml:"nid"` - HomeDir string `json:"-" yaml:"-"` - Disabled bool `json:"disabled" yaml:"disabled"` + ChainName string `json:"-" yaml:"-"` + RPCUrl string `json:"rpc-url" yaml:"rpc-url"` + StartHeight uint64 `json:"start-height" yaml:"start-height"` + Address string `json:"address" yaml:"address"` + Contracts types.ContractConfigMap `json:"contracts" yaml:"contracts"` + FinalityBlock uint64 `json:"finality-block" yaml:"finality-block"` + NID string `json:"nid" yaml:"nid"` + HomeDir string `json:"-" yaml:"-"` + Disabled bool `json:"disabled" yaml:"disabled"` } // Enabled returns true if the provider is enabled diff --git a/utils/multisig/bridge_script.go b/utils/multisig/bridge_script.go index bf2c9e3d..68f05cb0 100644 --- a/utils/multisig/bridge_script.go +++ b/utils/multisig/bridge_script.go @@ -114,12 +114,10 @@ func EncodePayloadToScripts(payload []byte) ([][]byte, error) { if len(payload) > 0 { chunks = append(chunks, payload) } - // turn parts to OP_RETURN script + // turn parts to OP_BRIDGE_IDENT script scripts := [][]byte{} for _, part := range chunks { builder := txscript.NewScriptBuilder() - - builder.AddOp(txscript.OP_RETURN) builder.AddOp(OP_BRIDGE_IDENT) builder.AddData(part) @@ -139,7 +137,6 @@ func CreateBridgeMessageScripts(msg *BridgeDecodedMsg) ([][]byte, error) { if err != nil { return nil, err } - return EncodePayloadToScripts(payload) } @@ -147,12 +144,9 @@ func ReadBridgeMessage(transaction *wire.MsgTx) (*BridgeDecodedMsg, error) { payload := []byte{} for _, output := range transaction.TxOut { tokenizer := txscript.MakeScriptTokenizer(0, output.PkScript) - if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != txscript.OP_RETURN { - // Check for OP_RETURN - continue - } + + // Check for OP_BRIDGE_IDENT if !tokenizer.Next() || tokenizer.Err() != nil || tokenizer.Opcode() != OP_BRIDGE_IDENT { - // Check to ignore non Bridge protocol identifier (Rune or RadFi) continue } diff --git a/utils/multisig/bridge_tx.go b/utils/multisig/bridge_tx.go index 814a01aa..ce52da2e 100644 --- a/utils/multisig/bridge_tx.go +++ b/utils/multisig/bridge_tx.go @@ -15,8 +15,6 @@ func CreateBridgeTxSendBitcoin( receiverPkScript []byte, txFee int64, ) (*wire.MsgTx, error) { - // TODO: verify msg content - outputs := []*wire.TxOut{ // bitcoin send to receiver { @@ -29,14 +27,19 @@ func CreateBridgeTxSendBitcoin( if err != nil { return nil, err } + outputs = BuildBridgeScriptsOutputs(outputs, bridgeScripts) + + return CreateTx(inputs, outputs, senderPkScript, txFee, 0) +} + +func BuildBridgeScriptsOutputs(outputs []*wire.TxOut, bridgeScripts [][]byte) []*wire.TxOut { for _, script := range bridgeScripts { outputs = append(outputs, &wire.TxOut{ - Value: 0, + Value: OP_MIN_DUST_AMOUNT, PkScript: script, }) } - - return CreateTx(inputs, outputs, senderPkScript, txFee, 0) + return outputs } func CreateBridgeTxSendRune( @@ -46,8 +49,6 @@ func CreateBridgeTxSendRune( receiverPkScript []byte, txFee int64, ) (*wire.MsgTx, error) { - // TODO: verify msg content - // create runestone OP_RETURN runeId, err := runestone.RuneIdFromString(msg.Message.TokenAddress) if err != nil { @@ -69,12 +70,12 @@ func CreateBridgeTxSendRune( outputs := []*wire.TxOut{ // rune send to receiver { - Value: DUST_UTXO_AMOUNT, + Value: RUNE_DUST_UTXO_AMOUNT, PkScript: receiverPkScript, }, // rune change output { - Value: DUST_UTXO_AMOUNT, + Value: RUNE_DUST_UTXO_AMOUNT, PkScript: senderPkScript, }, // rune OP_RETURN @@ -88,12 +89,6 @@ func CreateBridgeTxSendRune( if err != nil { return nil, err } - for _, script := range bridgeScripts { - outputs = append(outputs, &wire.TxOut{ - Value: 0, - PkScript: script, - }) - } - + outputs = BuildBridgeScriptsOutputs(outputs, bridgeScripts) return CreateTx(inputs, outputs, senderPkScript, txFee, 0) } diff --git a/utils/multisig/constants.go b/utils/multisig/constants.go index 77377250..e13d996f 100644 --- a/utils/multisig/constants.go +++ b/utils/multisig/constants.go @@ -1,9 +1,9 @@ package multisig const ( - MIN_SAT = 100 - SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" - DUST_UTXO_AMOUNT int64 = 546 - - PART_LIMIT = 76 + MIN_SAT = 100 + SHARED_RANDOM_HEX = "6b628bf19d167cbaaee09a3c7a43159a8bf1111eae0703a144fb4caad92de49c" + RUNE_DUST_UTXO_AMOUNT = 546 + OP_MIN_DUST_AMOUNT = 547 + PART_LIMIT = 40 ) From 4736f653a39511e5b9ba027f573856cbfa7b3a0f Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Fri, 15 Nov 2024 13:09:06 +0700 Subject: [PATCH 087/113] feat: calculate tx vsize --- relayer/chains/bitcoin/provider.go | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 23debe7e..bbcc54bd 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -47,8 +47,7 @@ var ( MasterMode = "master" SlaveMode = "slave" BtcDB = "btc.db" - // MinSatsRequired int64 = 300 - WitnessSize = 125 + WitnessSize = 380 ) var chainIdToName = map[uint8]string{ @@ -534,7 +533,9 @@ func (p *Provider) calculateTxSize(inputs []*multisig.Input, outputs []*wire.TxO if err != nil { return 0, err } - txSize := len(rawTxBytes.Bytes()) + len(inputs)*WitnessSize + baseSize := len(rawTxBytes.Bytes()) + totalSize := baseSize + len(inputs)*WitnessSize + txSize := (baseSize*3 + totalSize) / 4 return txSize, nil } @@ -832,11 +833,8 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms switch message.EventType { case events.EmitMessage: messageDecoded, err := p.decodeMessage(message) - if err != nil { - p.logger.Error("failed to decode message: %v", zap.Error(err)) - } - // transaction message decoded successfully + // transaction message from icon decoded successfully // withdraw message has no messageDecoded.Code if err == nil { // 1 is transaction already success, no need to rollback @@ -890,12 +888,10 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms // call the smart contract to send the message func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (string, error) { - return "", nil } func (p *Provider) sendTx(ctx context.Context, signedMsg *wire.MsgTx) (string, error) { - return "", nil } @@ -909,23 +905,19 @@ func (p *Provider) waitForTxResult(ctx context.Context, mk *relayTypes.MessageKe func (p *Provider) pollTxResultStream(ctx context.Context, txHash string, maxWaitInterval time.Duration) <-chan *types.TxResult { txResChan := make(chan *types.TxResult) - return txResChan } func (p *Provider) subscribeTxResultStream(ctx context.Context, txHash string, maxWaitInterval time.Duration) <-chan *types.TxResult { txResChan := make(chan *types.TxResult) - return txResChan } func (p *Provider) MessageReceived(ctx context.Context, key *relayTypes.MessageKey) (bool, error) { - return false, nil } func (p *Provider) QueryBalance(ctx context.Context, addr string) (*relayTypes.Coin, error) { - return nil, nil } From ccb1c4ee9c2f913f813edf2a93e8e19356b623d1 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Fri, 15 Nov 2024 14:43:07 +0700 Subject: [PATCH 088/113] fix: build multisig tx with rollback case --- relayer/chains/bitcoin/provider.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index bbcc54bd..6be7940d 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -427,7 +427,7 @@ func (p *Provider) CreateBitcoinMultisigTx( // add withdraw output amount := new(big.Int).SetBytes(decodedData.Amount) - if decodedData.Action == MethodWithdrawTo || decodedData.Action == MethodDeposit { + if decodedData.Action == MethodWithdrawTo || decodedData.Action == MethodDeposit || decodedData.Action == MethodRollback { if decodedData.TokenAddress == BTCToken { // transfer btc bitcoinAmountRequired = amount.Int64() From 6705a683f980ce59ac797d17836a13a614576153 Mon Sep 17 00:00:00 2001 From: Shall Date: Fri, 15 Nov 2024 22:14:55 +0700 Subject: [PATCH 089/113] fix: update listener logic --- relayer/chains/bitcoin/provider.go | 35 ++++++++++++++++++------------ 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 6be7940d..218d7af4 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -270,7 +270,7 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn return err } - pollHeightTicker := time.NewTicker(time.Second * 60) // do scan each 2 mins + pollHeightTicker := time.NewTicker(time.Second * 60) pollHeightTicker.Stop() p.logger.Info("Start from height", zap.Uint64("height", startHeight), zap.Uint64("finality block", p.FinalityBlock(ctx))) @@ -278,22 +278,18 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn for { select { case <-pollHeightTicker.C: + pollHeightTicker.Stop() + startHeight = p.GetLastSavedHeight() latestHeight, err = p.QueryLatestHeight(ctx) if err != nil { p.logger.Error("failed to get latest block height", zap.Error(err)) - continue + pollHeightTicker.Reset(time.Second * 60) } default: - toHeight := latestHeight - if p.cfg.Mode == MasterMode { - // master mode should query slower slave 1 block - // for ensure slave cache tx data before calling to get signed tx - toHeight = latestHeight - 1 - } - - if startHeight < toHeight { - p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", toHeight)) + if startHeight < latestHeight { + p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", latestHeight)) startHeight = p.runBlockQuery(ctx, blockInfoChan, startHeight, latestHeight) + pollHeightTicker.Reset(time.Second * 60) } } } @@ -1021,14 +1017,25 @@ func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64 select { case <-done: return - case heightChan <- &HeightRange{Start: fromHeight, End: fromHeight + 2}: - fromHeight += 2 + case heightChan <- &HeightRange{ + Start: fromHeight, + End: fromHeight + min(2, toHeight-fromHeight), + }: + fromHeight += min(2, toHeight-fromHeight) } } }(fromHeight, toHeight, heightChan) return heightChan } +// Helper function to get minimum of two uint64 values +func min(a, b uint64) uint64 { + if a <= b { + return a + } + return b +} + func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { var ( @@ -1041,7 +1048,7 @@ func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRan if err != nil { return nil, err } - + p.logger.Info("TxSearch", zap.String("StartHeight", fmt.Sprintf("%d", heightInfo.Start)), zap.String("EndHeight", fmt.Sprintf("%d", heightInfo.End))) searchParam := TxSearchParam{ StartHeight: heightInfo.Start, EndHeight: heightInfo.End, From b8ca4af4043d78dc6d299d4b1f7a1fb4331a92a5 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Sat, 16 Nov 2024 00:48:11 +0700 Subject: [PATCH 090/113] feat: handle callback --- relayer/chains/bitcoin/provider.go | 151 +++++++++++++++++++---------- relayer/chains/bitcoin/slave.go | 141 ++++++++++++++++++++------- relayer/chains/icon/route.go | 5 +- relayer/relay.go | 7 ++ 4 files changed, 217 insertions(+), 87 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 218d7af4..b5338acf 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -55,9 +55,13 @@ var chainIdToName = map[uint8]string{ 2: "0x1.btc", 3: "0x2.icon", 4: "0x2.btc", - // Add more mappings as needed } +var ( + MessageStatusPending = "pending" + MessageStatusSuccess = "success" +) + type MessageDecoded struct { Action string TokenAddress string @@ -75,6 +79,13 @@ type slaveRequestParams struct { MsgSn string `json:"msgSn"` FeeRate int `json:"feeRate"` } + +type slaveRequestUpdateRelayMessageStatus struct { + MsgSn string `json:"msgSn"` + Status string `json:"status"` + TxHash string `json:"txHash"` +} + type StoredMessageData struct { OriginalMessage *relayTypes.Message TxHash string @@ -88,6 +99,12 @@ type StoredMessageData struct { TokenAddress string } +type StoredRelayMessage struct { + Message *relayTypes.Message + Status string + TxHash string +} + type Provider struct { logger *zap.Logger cfg *Config @@ -182,7 +199,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri return p, nil } -func (p *Provider) CallSlaves(slaveRequestData []byte) [][][]byte { +func (p *Provider) CallSlaves(slaveRequestData []byte, path string) [][][]byte { resultChan := make(chan [][][]byte) go func() { responses := make(chan struct { @@ -192,8 +209,8 @@ func (p *Provider) CallSlaves(slaveRequestData []byte) [][][]byte { var wg sync.WaitGroup wg.Add(2) - go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer1, slaveRequestData, responses, 1, &wg) - go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer2, slaveRequestData, responses, 2, &wg) + go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer1+path, slaveRequestData, responses, 1, &wg) + go requestPartialSign(p.cfg.ApiKey, p.cfg.SlaveServer2+path, slaveRequestData, responses, 2, &wg) go func() { wg.Wait() @@ -667,9 +684,25 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb messageSrcDetail := strings.Split(message.Src, ".") if (messageSrcDetail[1] == "icon" || messageSrcDetail[1] == "btc") && messageDstDetail[1] == "btc" { if p.cfg.Mode == SlaveMode { - // store the message in LevelDB key := []byte(message.Sn.String()) - value, _ := json.Marshal(message) + + // check if the message is already success + storedRelayerMessage := StoredRelayMessage{} + data, _ := p.db.Get(key, nil) + if len(data) > 0 { + json.Unmarshal(data, &storedRelayerMessage) + if storedRelayerMessage.Status == MessageStatusSuccess { + callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: storedRelayerMessage.TxHash}, nil) + return nil + } + } + + // store the message in LevelDB + storedMessage := StoredRelayMessage{ + Message: message, + Status: MessageStatusPending, + } + value, _ := json.Marshal(storedMessage) err := p.db.Put(key, value, nil) if err != nil { p.logger.Error("failed to store message in LevelDB: %v", zap.Error(err)) @@ -678,53 +711,23 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb p.logger.Info("Message stored in LevelDB", zap.String("key", string(key)), zap.Any("message", message)) return nil } else if p.cfg.Mode == MasterMode { - - inputs, msWallet, msgTx, relayerSigs, feeRate, err := p.HandleBitcoinMessageTx(message, 0) + txHash, err := p.sendTransaction(ctx, message) if err != nil { - p.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) + p.logger.Error("failed to send transaction: %v", zap.Error(err)) return err } - totalSigs := [][][]byte{relayerSigs} - // send unsigned raw tx and message sn to 2 slave relayers to get sign - rsi := slaveRequestParams{ - MsgSn: message.Sn.String(), - FeeRate: feeRate, - } - - slaveRequestData, _ := json.Marshal(rsi) - slaveSigs := p.CallSlaves(slaveRequestData) - p.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) - totalSigs = append(totalSigs, slaveSigs...) - // combine sigs - signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) - - if err != nil { - p.logger.Error("err combine tx: ", zap.Error(err)) - } - p.logger.Info("signedMsgTx", zap.Any("transaction", signedMsgTx)) - var buf bytes.Buffer - err = signedMsgTx.Serialize(&buf) - - if err != nil { - log.Fatal(err) - } - - txSize := len(buf.Bytes()) - p.logger.Info("--------------------txSize--------------------", zap.Int("size", txSize)) - signedMsgTxHex := hex.EncodeToString(buf.Bytes()) - p.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) - - p.cacheSpentUTXOs(inputs) - // Broadcast transaction to bitcoin network - txHash, err := p.client.SendRawTransaction(p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(signedMsgTxHex)}) - if err != nil { - p.removeCachedSpentUTXOs(inputs) - p.logger.Error("failed to send raw transaction", zap.Error(err)) - return err + // call to slave to clear message + rsi := slaveRequestUpdateRelayMessageStatus{ + MsgSn: message.Sn.String(), + Status: MessageStatusSuccess, + TxHash: txHash, } + slaveRequestData, _ := json.Marshal(rsi) + p.CallSlaves(slaveRequestData, "/update-relayer-message-status") - p.logger.Info("txHash", zap.String("transaction_hash", txHash)) + callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: txHash}, nil) + return nil } } @@ -776,7 +779,7 @@ func (p *Provider) decodeMessage(message *relayTypes.Message) (CSMessageResult, return messageDecoded, nil } -func decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { +func (p *Provider) decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byte, error) { withdrawInfoWrapper := CSMessage{} _, err := codec.RLP.UnmarshalFromBytes(input, &withdrawInfoWrapper) if err != nil { @@ -851,7 +854,7 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms decodedData = messageDecoded } else { // Perform WithdrawData - data, opBufferData, err := decodeWithdrawToMessage(message.Data) + data, opBufferData, err := p.decodeWithdrawToMessage(message.Data) decodedData = data if err != nil { p.logger.Error("failed to decode message: %v", zap.Error(err)) @@ -887,8 +890,54 @@ func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (strin return "", nil } -func (p *Provider) sendTx(ctx context.Context, signedMsg *wire.MsgTx) (string, error) { - return "", nil +func (p *Provider) sendTransaction(ctx context.Context, message *relayTypes.Message) (string, error) { + inputs, msWallet, msgTx, relayerSigs, feeRate, err := p.HandleBitcoinMessageTx(message, 0) + if err != nil { + p.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) + return "", err + } + totalSigs := [][][]byte{relayerSigs} + // send unsigned raw tx and message sn to 2 slave relayers to get sign + rsi := slaveRequestParams{ + MsgSn: message.Sn.String(), + FeeRate: feeRate, + } + + slaveRequestData, _ := json.Marshal(rsi) + slaveSigs := p.CallSlaves(slaveRequestData, "") + p.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) + totalSigs = append(totalSigs, slaveSigs...) + // combine sigs + signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) + + if err != nil { + p.logger.Error("err combine tx: ", zap.Error(err)) + } + p.logger.Info("signedMsgTx", zap.Any("transaction", signedMsgTx)) + var buf bytes.Buffer + err = signedMsgTx.Serialize(&buf) + + if err != nil { + log.Fatal(err) + } + + txSize := len(buf.Bytes()) + p.logger.Info("--------------------txSize--------------------", zap.Int("size", txSize)) + signedMsgTxHex := hex.EncodeToString(buf.Bytes()) + p.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + + p.cacheSpentUTXOs(inputs) + + // Broadcast transaction to bitcoin network + txHash, err := p.client.SendRawTransaction(p.cfg.MempoolURL, []json.RawMessage{json.RawMessage(signedMsgTxHex)}) + if err != nil { + p.removeCachedSpentUTXOs(inputs) + p.logger.Error("failed to send raw transaction", zap.Error(err)) + return "", err + } + + p.logger.Info("txHash", zap.String("transaction_hash", txHash)) + return txHash, nil } func (p *Provider) handleSequence(ctx context.Context) error { diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index 1eb070c4..dce52ac7 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -6,7 +6,6 @@ import ( "net/http" "strings" - relayTypes "github.com/icon-project/centralized-relay/relayer/types" "go.uber.org/zap" ) @@ -14,6 +13,9 @@ func startSlave(c *Config, p *Provider) { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { handleRoot(w, r, p) }) + http.HandleFunc("/update-relayer-message-status", func(w http.ResponseWriter, r *http.Request) { + handleUpdateRelayerMessageStatus(w, r, p) + }) port := c.Port server := &http.Server{ Addr: ":" + port, @@ -26,41 +28,79 @@ func startSlave(c *Config, p *Provider) { func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { p.logger.Info("Slave starting on port", zap.String("port", p.cfg.Port)) - if r.Method == http.MethodPost { - apiKey := r.Header.Get("x-api-key") - if apiKey == "" { - p.logger.Error("Missing API Key") - http.Error(w, "Missing API Key", http.StatusUnauthorized) - return - } - apiKeyHeader := p.cfg.ApiKey - if apiKey != apiKeyHeader { - p.logger.Error("Invalid API Key", zap.String("apiKey", apiKey)) - http.Error(w, "Invalid API Key", http.StatusForbidden) - return - } - body, err := io.ReadAll(r.Body) - if err != nil { - p.logger.Error("Error reading request body", zap.Error(err)) - http.Error(w, "Error reading request body", http.StatusInternalServerError) - return - } - - var rsi slaveRequestParams - err = json.Unmarshal(body, &rsi) - if err != nil { - p.logger.Error("Error decoding request body", zap.Error(err)) - http.Error(w, "Error decoding request body", http.StatusInternalServerError) - return - } - sigs, _ := buildAndSignTxFromDbMessage(rsi.MsgSn, rsi.FeeRate, p) - // return sigs to master - returnData, _ := json.Marshal(sigs) - w.Write(returnData) - } else { + if !validateMethod(w, r, p) { + return + } + if !authorizeRequest(w, r, p) { + return + } + body, err := io.ReadAll(r.Body) + if err != nil { + p.logger.Error("Error reading request body", zap.Error(err)) + http.Error(w, "Error reading request body", http.StatusInternalServerError) + return + } + + var rsi slaveRequestParams + err = json.Unmarshal(body, &rsi) + if err != nil { + p.logger.Error("Error decoding request body", zap.Error(err)) + http.Error(w, "Error decoding request body", http.StatusInternalServerError) + return + } + sigs, _ := buildAndSignTxFromDbMessage(rsi.MsgSn, rsi.FeeRate, p) + // return sigs to master + returnData, _ := json.Marshal(sigs) + w.Write(returnData) +} + +func handleUpdateRelayerMessageStatus(w http.ResponseWriter, r *http.Request, p *Provider) { + if !validateMethod(w, r, p) { + return + } + if !authorizeRequest(w, r, p) { + return + } + body, err := io.ReadAll(r.Body) + if err != nil { + p.logger.Error("Error reading request body", zap.Error(err)) + http.Error(w, "Error reading request body", http.StatusInternalServerError) + return + } + var rsi slaveRequestUpdateRelayMessageStatus + err = json.Unmarshal(body, &rsi) + if err != nil { + p.logger.Error("Error decoding request body", zap.Error(err)) + http.Error(w, "Error decoding request body", http.StatusInternalServerError) + return + } + p.logger.Info("Slave update relayer message status", zap.String("sn", rsi.MsgSn)) + p.updateRelayerMessageStatus(rsi) +} + +func authorizeRequest(w http.ResponseWriter, r *http.Request, p *Provider) bool { + apiKey := r.Header.Get("x-api-key") + if apiKey == "" { + p.logger.Error("Missing API Key") + http.Error(w, "Missing API Key", http.StatusUnauthorized) + return false + } + apiKeyHeader := p.cfg.ApiKey + if apiKey != apiKeyHeader { + p.logger.Error("Invalid API Key", zap.String("apiKey", apiKey)) + http.Error(w, "Invalid API Key", http.StatusForbidden) + return false + } + return true +} + +func validateMethod(w http.ResponseWriter, r *http.Request, p *Provider) bool { + if r.Method != http.MethodPost { p.logger.Error("Method not allowed", zap.String("method", r.Method)) http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return false } + return true } func buildAndSignTxFromDbMessage(sn string, feeRate int, p *Provider) ([][]byte, error) { @@ -76,16 +116,47 @@ func buildAndSignTxFromDbMessage(sn string, feeRate int, p *Provider) ([][]byte, return nil, nil } - var message *relayTypes.Message + var message *StoredRelayMessage err = json.Unmarshal(data, &message) if err != nil { return nil, err } - _, _, _, relayerSigns, _, err := p.HandleBitcoinMessageTx(message, feeRate) + _, _, _, relayerSigns, _, err := p.HandleBitcoinMessageTx(message.Message, feeRate) if err != nil { return nil, err } return relayerSigns, nil } + +func (p *Provider) updateRelayerMessageStatus(params slaveRequestUpdateRelayMessageStatus) (bool, error) { + p.logger.Info("Slave update relayer message status", zap.String("sn", params.MsgSn)) + key := params.MsgSn + data, err := p.db.Get([]byte(key), nil) + if err != nil { + return false, err + } + + if strings.Contains(params.MsgSn, "RB") { + p.logger.Info("Rollback message", zap.String("sn", params.MsgSn)) + return true, nil + } + + var message *StoredRelayMessage + err = json.Unmarshal(data, &message) + if err != nil { + return false, err + } + + message.Status = params.Status + message.TxHash = params.TxHash + + value, _ := json.Marshal(message) + err = p.db.Put([]byte(key), value, nil) + if err != nil { + return false, err + } + + return true, nil +} diff --git a/relayer/chains/icon/route.go b/relayer/chains/icon/route.go index b06d99b4..2b52fa7f 100644 --- a/relayer/chains/icon/route.go +++ b/relayer/chains/icon/route.go @@ -3,6 +3,7 @@ package icon import ( "context" "fmt" + "strings" "github.com/icon-project/centralized-relay/relayer/chains/icon/types" "github.com/icon-project/centralized-relay/relayer/events" @@ -13,7 +14,9 @@ import ( func (p *Provider) Route(ctx context.Context, message *providerTypes.Message, callback providerTypes.TxResponseFunc) error { // TODO: remove this after testing - if (message.Src == "0x2.icon" || message.Src == "0x2.btc") && message.Dst == "0x2.icon" { + srcChain := strings.Split(message.Src, ".")[1] + dstChain := strings.Split(message.Dst, ".")[1] + if (srcChain == "icon" || srcChain == "btc") && dstChain == "icon" { p.log.Info("starting to route message", zap.Any("message", message)) iconMessage, err := p.MakeIconMessage(message) diff --git a/relayer/relay.go b/relayer/relay.go index 4e281e47..714618c9 100644 --- a/relayer/relay.go +++ b/relayer/relay.go @@ -3,6 +3,7 @@ package relayer import ( "context" "fmt" + "strings" "time" "github.com/icon-project/centralized-relay/relayer/store" @@ -214,7 +215,13 @@ func (r *Relayer) getActiveMessagesFromStore(nId string, maxMessages uint) ([]*t func (r *Relayer) processMessages(ctx context.Context) { for _, src := range r.chains { for key, message := range src.MessageCache.Messages { + // REMOVE AFTER TESTING + dstChain := strings.Split(message.Dst, ".")[1] + if dstChain != "btc" && dstChain != "icon" { + continue + } dst, err := r.FindChainRuntime(message.Dst) + if err != nil { r.log.Error("dst chain nid not found", zap.String("nid", message.Dst)) r.ClearMessages(ctx, []*types.MessageKey{&key}, src) From e66302f6557b2a0bfbfa2e3c866027308cd8902a Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Sat, 16 Nov 2024 01:17:11 +0700 Subject: [PATCH 091/113] fix: del cache relaymessage after success --- relayer/chains/bitcoin/provider.go | 7 +++---- relayer/chains/icon/route.go | 4 +--- relayer/relay.go | 3 +-- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index b5338acf..801fb6a8 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -680,9 +680,7 @@ func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message, feeRate i func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { p.logger.Info("starting to route message", zap.Any("message", message)) - messageDstDetail := strings.Split(message.Dst, ".") - messageSrcDetail := strings.Split(message.Src, ".") - if (messageSrcDetail[1] == "icon" || messageSrcDetail[1] == "btc") && messageDstDetail[1] == "btc" { + if (strings.HasSuffix(message.Src, "icon") || strings.HasSuffix(message.Src, "btc")) && strings.HasSuffix(message.Dst, "btc") { if p.cfg.Mode == SlaveMode { key := []byte(message.Sn.String()) @@ -692,6 +690,8 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb if len(data) > 0 { json.Unmarshal(data, &storedRelayerMessage) if storedRelayerMessage.Status == MessageStatusSuccess { + // delete cached message + p.db.Delete(key, nil) callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: storedRelayerMessage.TxHash}, nil) return nil } @@ -729,7 +729,6 @@ func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callb callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: txHash}, nil) return nil } - } return nil } diff --git a/relayer/chains/icon/route.go b/relayer/chains/icon/route.go index 2b52fa7f..6403802d 100644 --- a/relayer/chains/icon/route.go +++ b/relayer/chains/icon/route.go @@ -14,9 +14,7 @@ import ( func (p *Provider) Route(ctx context.Context, message *providerTypes.Message, callback providerTypes.TxResponseFunc) error { // TODO: remove this after testing - srcChain := strings.Split(message.Src, ".")[1] - dstChain := strings.Split(message.Dst, ".")[1] - if (srcChain == "icon" || srcChain == "btc") && dstChain == "icon" { + if (strings.HasSuffix(message.Src, "icon") || strings.HasSuffix(message.Src, "btc")) && strings.HasSuffix(message.Dst, "icon") { p.log.Info("starting to route message", zap.Any("message", message)) iconMessage, err := p.MakeIconMessage(message) diff --git a/relayer/relay.go b/relayer/relay.go index 714618c9..1704333b 100644 --- a/relayer/relay.go +++ b/relayer/relay.go @@ -216,8 +216,7 @@ func (r *Relayer) processMessages(ctx context.Context) { for _, src := range r.chains { for key, message := range src.MessageCache.Messages { // REMOVE AFTER TESTING - dstChain := strings.Split(message.Dst, ".")[1] - if dstChain != "btc" && dstChain != "icon" { + if !strings.HasSuffix(message.Dst, "btc") && !strings.HasSuffix(message.Dst, "icon") { continue } dst, err := r.FindChainRuntime(message.Dst) From 94b73633f03ea0aaeaa5fb3e89425117bdc1b956 Mon Sep 17 00:00:00 2001 From: Shall Date: Sat, 16 Nov 2024 12:21:24 +0700 Subject: [PATCH 092/113] fix: update log to track fetch bitcoin block number --- relayer/chains/bitcoin/client.go | 4 ---- relayer/chains/bitcoin/provider.go | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index cf229a5a..ceb0d65f 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -130,10 +130,6 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch return nil, err } - // Print the block hash to a string - blockHashStr := fmt.Sprintf("%v", blockHash) - c.log.Info("Block Hash", zap.String("blockHash", blockHashStr), zap.Uint64("height", i)) - block, err := c.client.GetBlock(blockHash) if err != nil { c.log.Error("Failed to get block", zap.Error(err)) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 801fb6a8..07aac8d0 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -1096,7 +1096,7 @@ func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRan if err != nil { return nil, err } - p.logger.Info("TxSearch", zap.String("StartHeight", fmt.Sprintf("%d", heightInfo.Start)), zap.String("EndHeight", fmt.Sprintf("%d", heightInfo.End))) + p.logger.Info("Fetching Block Messages", zap.String("StartHeight", fmt.Sprintf("%d", heightInfo.Start)), zap.String("EndHeight", fmt.Sprintf("%d", heightInfo.End))) searchParam := TxSearchParam{ StartHeight: heightInfo.Start, EndHeight: heightInfo.End, From be4b0228765dfddd15b5cb71d958429bb14cd8e8 Mon Sep 17 00:00:00 2001 From: Shall Date: Sat, 16 Nov 2024 12:26:43 +0700 Subject: [PATCH 093/113] chore: ignore data and keystore folder --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d2c7c281..eded4c79 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,6 @@ vendor .*env /go.work -/go.work.sum \ No newline at end of file +/go.work.sum +keystore +data \ No newline at end of file From 9b49c0c1b4fd399e9d7ba81c706b088aa06798e3 Mon Sep 17 00:00:00 2001 From: Shall Date: Sat, 16 Nov 2024 14:37:44 +0700 Subject: [PATCH 094/113] feat: add condition to query block --- relayer/chains/bitcoin/provider.go | 4 ++++ relayer/chains/icon/route.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 07aac8d0..6d57bb8d 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -1337,6 +1337,10 @@ func (p *Provider) runBlockQuery(ctx context.Context, blockInfoChan chan *relayT heightStream := p.getHeightStream(done, fromHeight, toHeight) diff := int(toHeight-fromHeight) / 2 + remain := (toHeight - fromHeight) % 2 + if remain == 1 { + diff += 1 + } numOfPipelines := p.getNumOfPipelines(diff) wg := &sync.WaitGroup{} diff --git a/relayer/chains/icon/route.go b/relayer/chains/icon/route.go index 6403802d..f42d6a67 100644 --- a/relayer/chains/icon/route.go +++ b/relayer/chains/icon/route.go @@ -14,7 +14,7 @@ import ( func (p *Provider) Route(ctx context.Context, message *providerTypes.Message, callback providerTypes.TxResponseFunc) error { // TODO: remove this after testing - if (strings.HasSuffix(message.Src, "icon") || strings.HasSuffix(message.Src, "btc")) && strings.HasSuffix(message.Dst, "icon") { + if strings.HasSuffix(message.Src, "btc") { p.log.Info("starting to route message", zap.Any("message", message)) iconMessage, err := p.MakeIconMessage(message) From 219d74444b84aabfe442917fcbe09d32220d736f Mon Sep 17 00:00:00 2001 From: Shall Date: Sat, 16 Nov 2024 17:29:39 +0700 Subject: [PATCH 095/113] fix: interval time to get new block --- relayer/chains/bitcoin/provider.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 6d57bb8d..50897cee 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -296,14 +296,16 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn select { case <-pollHeightTicker.C: pollHeightTicker.Stop() - startHeight = p.GetLastSavedHeight() latestHeight, err = p.QueryLatestHeight(ctx) if err != nil { p.logger.Error("failed to get latest block height", zap.Error(err)) pollHeightTicker.Reset(time.Second * 60) + } else if latestHeight < startHeight { + p.logger.Warn("latest block height is less than start height, sleep 3 minutes to wait for new block", zap.Uint64("latest-height", latestHeight), zap.Uint64("start-height", startHeight)) + pollHeightTicker.Reset(time.Minute * 3) } default: - if startHeight < latestHeight { + if startHeight <= latestHeight { p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", latestHeight)) startHeight = p.runBlockQuery(ctx, blockInfoChan, startHeight, latestHeight) pollHeightTicker.Reset(time.Second * 60) From 8b24dc428489403e3eb927b14587accc9c55e48d Mon Sep 17 00:00:00 2001 From: spiderlipovitan <35133731+spiderlipovitan@users.noreply.github.com> Date: Sat, 16 Nov 2024 19:57:51 +0700 Subject: [PATCH 096/113] feat: save handled message (#16) --- relayer/chains/bitcoin/provider.go | 94 ++++++++++++++++-------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 50897cee..f9ed9caa 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -680,57 +680,61 @@ func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message, feeRate i } func (p *Provider) Route(ctx context.Context, message *relayTypes.Message, callback relayTypes.TxResponseFunc) error { - p.logger.Info("starting to route message", zap.Any("message", message)) - if (strings.HasSuffix(message.Src, "icon") || strings.HasSuffix(message.Src, "btc")) && strings.HasSuffix(message.Dst, "btc") { - if p.cfg.Mode == SlaveMode { - key := []byte(message.Sn.String()) - - // check if the message is already success - storedRelayerMessage := StoredRelayMessage{} - data, _ := p.db.Get(key, nil) - if len(data) > 0 { - json.Unmarshal(data, &storedRelayerMessage) - if storedRelayerMessage.Status == MessageStatusSuccess { - // delete cached message - p.db.Delete(key, nil) - callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: storedRelayerMessage.TxHash}, nil) - return nil - } - } - - // store the message in LevelDB - storedMessage := StoredRelayMessage{ - Message: message, - Status: MessageStatusPending, - } - value, _ := json.Marshal(storedMessage) - err := p.db.Put(key, value, nil) - if err != nil { - p.logger.Error("failed to store message in LevelDB: %v", zap.Error(err)) - return err - } - p.logger.Info("Message stored in LevelDB", zap.String("key", string(key)), zap.Any("message", message)) - return nil - } else if p.cfg.Mode == MasterMode { - txHash, err := p.sendTransaction(ctx, message) - if err != nil { - p.logger.Error("failed to send transaction: %v", zap.Error(err)) - return err + p.logger.Info("starting to route message", zap.Any("message", message)) + + key := []byte(message.Sn.String()) + storedRelayerMessage := StoredRelayMessage{} + data, _ := p.db.Get(key, nil) + if len(data) > 0 { + json.Unmarshal(data, &storedRelayerMessage) + if storedRelayerMessage.Status == MessageStatusSuccess { + p.logger.Info("Message already success", zap.Any("message", storedRelayerMessage)) + callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: storedRelayerMessage.TxHash}, nil) + return nil } + } - // call to slave to clear message - rsi := slaveRequestUpdateRelayMessageStatus{ - MsgSn: message.Sn.String(), - Status: MessageStatusSuccess, - TxHash: txHash, - } - slaveRequestData, _ := json.Marshal(rsi) - p.CallSlaves(slaveRequestData, "/update-relayer-message-status") + storedMessage := StoredRelayMessage{ + Message: message, + Status: MessageStatusPending, + } + value, _ := json.Marshal(storedMessage) + err := p.db.Put(key, value, nil) + if err != nil { + p.logger.Error("failed to store message in LevelDB: %v", zap.Error(err)) + return err + } + p.logger.Info("Message stored in LevelDB", zap.String("key", string(key)), zap.Any("message", message)) - callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: txHash}, nil) + if p.cfg.Mode != MasterMode { return nil } + txHash, err := p.sendTransaction(ctx, message) + if err != nil { + p.logger.Error("failed to send transaction: %v", zap.Error(err)) + return err + } + p.logger.Info("transaction sent", zap.String("txHash", txHash), zap.Any("message", message)) + + // update message status to success and save + storedMessage.Status = MessageStatusSuccess + storedMessage.TxHash = txHash + value, _ = json.Marshal(storedMessage) + p.db.Put(key, value, nil) + + // call to slave to update message status + rsi := slaveRequestUpdateRelayMessageStatus{ + MsgSn: message.Sn.String(), + Status: MessageStatusSuccess, + TxHash: txHash, + } + slaveRequestData, _ := json.Marshal(rsi) + p.CallSlaves(slaveRequestData, "/update-relayer-message-status") + + // callback to clear relayer message + callback(message.MessageKey(), &relayTypes.TxResponse{Code: relayTypes.Success, TxHash: txHash}, nil) + return nil } return nil } From 8f3f82b5e1b1d1cddd3ca3486d888b16b9dfa46b Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Sat, 16 Nov 2024 20:31:37 +0700 Subject: [PATCH 097/113] fix: remove unused --- relayer/chains/bitcoin/provider.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index f9ed9caa..29a41dc5 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -1242,9 +1242,6 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err if err != nil { return nil, fmt.Errorf("failed to store rollback message data: %v", err) } - if p.cfg.Mode == SlaveMode { - return nil, nil - } return relayMessage, nil } From f417347bb1cd2c3665cd0bfea490d93f24d341fe Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Sun, 17 Nov 2024 16:54:17 +0700 Subject: [PATCH 098/113] fix: slave select default input from master --- relayer/chains/bitcoin/client.go | 1 + relayer/chains/bitcoin/provider.go | 63 +++++++++++++++++++++--------- relayer/chains/bitcoin/slave.go | 14 +++---- 3 files changed, 53 insertions(+), 25 deletions(-) diff --git a/relayer/chains/bitcoin/client.go b/relayer/chains/bitcoin/client.go index ceb0d65f..adba5d44 100644 --- a/relayer/chains/bitcoin/client.go +++ b/relayer/chains/bitcoin/client.go @@ -127,6 +127,7 @@ func (c *Client) TxSearch(ctx context.Context, param TxSearchParam) ([]*TxSearch blockHash, err := c.client.GetBlockHash(int64(i)) if err != nil { + c.log.Error("Failed to get block hash", zap.Error(err)) return nil, err } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 29a41dc5..b2bdb808 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -39,7 +39,7 @@ import ( //var _ provider.ChainProvider = (*Provider)(nil) var ( - BTCToken = "0:1" + BTCToken = "0:0" MethodDeposit = "Deposit" MethodWithdrawTo = "WithdrawTo" MethodRefundTo = "RefundTo" @@ -76,8 +76,14 @@ type CSMessageResult struct { } type slaveRequestParams struct { - MsgSn string `json:"msgSn"` - FeeRate int `json:"feeRate"` + MsgSn string `json:"msgSn"` + FeeRate int `json:"feeRate"` + Inputs []slaveRequestInput `json:"inputs"` +} +type slaveRequestInput struct { + TxHash string `json:"txHash"` + Output int `json:"output"` + Amount int64 `json:"amount"` } type slaveRequestUpdateRelayMessageStatus struct { @@ -300,12 +306,12 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn if err != nil { p.logger.Error("failed to get latest block height", zap.Error(err)) pollHeightTicker.Reset(time.Second * 60) - } else if latestHeight < startHeight { + } else if latestHeight <= startHeight { p.logger.Warn("latest block height is less than start height, sleep 3 minutes to wait for new block", zap.Uint64("latest-height", latestHeight), zap.Uint64("start-height", startHeight)) pollHeightTicker.Reset(time.Minute * 3) } default: - if startHeight <= latestHeight { + if startHeight < latestHeight { p.logger.Debug("Query started", zap.Uint64("from-height", startHeight), zap.Uint64("to-height", latestHeight)) startHeight = p.runBlockQuery(ctx, blockInfoChan, startHeight, latestHeight) pollHeightTicker.Reset(time.Second * 60) @@ -419,6 +425,7 @@ func (p *Provider) CreateBitcoinMultisigTx( feeRate int64, decodedData *MessageDecoded, msWallet *multisig.MultisigWallet, + reqInputs []slaveRequestInput, ) ([]*multisig.Input, *wire.MsgTx, error) { // build receiver Pk Script receiverAddr, err := btcutil.DecodeAddress(decodedData.To, p.chainParam) @@ -513,7 +520,7 @@ func (p *Provider) CreateBitcoinMultisigTx( outputs = append(outputs, outputData...) // ----- BUILD INPUTS ----- - inputs, estFee, err := p.computeTx(feeRate, bitcoinAmountRequired, runeAmountRequired, decodedData.TokenAddress, msAddressStr, outputs, msWallet) + inputs, estFee, err := p.computeTx(feeRate, bitcoinAmountRequired, runeAmountRequired, decodedData.TokenAddress, msAddressStr, outputs, msWallet, reqInputs) if err != nil { return nil, nil, err } @@ -554,12 +561,12 @@ func (p *Provider) calculateTxSize(inputs []*multisig.Input, outputs []*wire.TxO return txSize, nil } -func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128.Uint128, runeId, address string, outputs []*wire.TxOut, msWallet *multisig.MultisigWallet) ([]*multisig.Input, int64, error) { +func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128.Uint128, runeId, address string, outputs []*wire.TxOut, msWallet *multisig.MultisigWallet, reqInputs []slaveRequestInput) ([]*multisig.Input, int64, error) { outputsCopy := make([]*wire.TxOut, len(outputs)) copy(outputsCopy, outputs) - inputs, err := p.selectUnspentUTXOs(satsToSend, runeToSend, runeId, address, msWallet.PKScript) + inputs, err := p.selectUnspentUTXOs(satsToSend, runeToSend, runeId, address, msWallet.PKScript, reqInputs) sumSelectedInputs := multisig.SumInputsSat(inputs) if err != nil { return nil, 0, err @@ -580,7 +587,7 @@ func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128 newSatsToSend := satsToSend + estFee var err error - inputs, err = p.selectUnspentUTXOs(newSatsToSend, runeToSend, runeId, address, msWallet.PKScript) + inputs, err = p.selectUnspentUTXOs(newSatsToSend, runeToSend, runeId, address, msWallet.PKScript, reqInputs) if err != nil { return nil, 0, err } @@ -603,9 +610,20 @@ func (p *Provider) computeTx(feeRate int64, satsToSend int64, runeToSend uint128 return inputs, estFee, nil } -func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint128, runeId string, address string, addressPkScript []byte) ([]*multisig.Input, error) { +func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint128, runeId string, address string, addressPkScript []byte, reqInputs []slaveRequestInput) ([]*multisig.Input, error) { // add tx fee the the required bitcoin amount inputs := []*multisig.Input{} + if len(reqInputs) > 0 { + for _, input := range reqInputs { + inputs = append(inputs, &multisig.Input{ + TxHash: input.TxHash, + OutputIdx: uint32(input.Output), + OutputAmount: input.Amount, + PkScript: addressPkScript, + }) + } + return inputs, nil + } if !runeToSend.IsZero() { // query rune UTXOs from unisat runeInputs, err := p.GetRuneUTXOs(p.cfg.UniSatURL, address, runeId, runeToSend, addressPkScript) @@ -654,7 +672,7 @@ func (p *Provider) buildMultisigWallet() (*multisig.MultisigWallet, error) { return msWallet, nil } -func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message, feeRate int) ([]*multisig.Input, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, int, error) { +func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message, feeRate int, reqInputs []slaveRequestInput) ([]*multisig.Input, *multisig.MultisigWallet, *wire.MsgTx, [][]byte, int, error) { msWallet, err := p.buildMultisigWallet() if err != nil { return nil, nil, nil, nil, 0, err @@ -666,7 +684,7 @@ func (p *Provider) HandleBitcoinMessageTx(message *relayTypes.Message, feeRate i feeRate = 1 } } - inputs, msgTx, err := p.buildTxMessage(message, int64(feeRate), msWallet) + inputs, msgTx, err := p.buildTxMessage(message, int64(feeRate), msWallet, reqInputs) if err != nil { p.logger.Error("failed to build tx message: %v", zap.Error(err)) return nil, nil, nil, nil, 0, err @@ -830,10 +848,9 @@ func (p *Provider) storedDataToMessageDecoded(sn string) (*MessageDecoded, []byt return decodedData, decodeDataBuffer, nil } -func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, msWallet *multisig.MultisigWallet) ([]*multisig.Input, *wire.MsgTx, error) { +func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, msWallet *multisig.MultisigWallet, reqInputs []slaveRequestInput) ([]*multisig.Input, *wire.MsgTx, error) { outputs := []*wire.TxOut{} decodedData := &MessageDecoded{} - fmt.Println("eventType: ", message.EventType) switch message.EventType { case events.EmitMessage: messageDecoded, err := p.decodeMessage(message) @@ -886,7 +903,7 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms return nil, nil, fmt.Errorf("unknown event type: %s", message.EventType) } - inputs, msgTx, err := p.CreateBitcoinMultisigTx(outputs, feeRate, decodedData, msWallet) + inputs, msgTx, err := p.CreateBitcoinMultisigTx(outputs, feeRate, decodedData, msWallet, reqInputs) return inputs, msgTx, err } @@ -896,16 +913,25 @@ func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (strin } func (p *Provider) sendTransaction(ctx context.Context, message *relayTypes.Message) (string, error) { - inputs, msWallet, msgTx, relayerSigs, feeRate, err := p.HandleBitcoinMessageTx(message, 0) + inputs, msWallet, msgTx, relayerSigs, feeRate, err := p.HandleBitcoinMessageTx(message, 0, []slaveRequestInput{}) if err != nil { p.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) return "", err } totalSigs := [][][]byte{relayerSigs} // send unsigned raw tx and message sn to 2 slave relayers to get sign + slaveInputs := []slaveRequestInput{} + for _, input := range inputs { + slaveInputs = append(slaveInputs, slaveRequestInput{ + TxHash: input.TxHash, + Output: int(input.OutputIdx), + Amount: input.OutputAmount, + }) + } rsi := slaveRequestParams{ MsgSn: message.Sn.String(), FeeRate: feeRate, + Inputs: slaveInputs, } slaveRequestData, _ := json.Marshal(rsi) @@ -1305,7 +1331,8 @@ func (p *Provider) getMessagesFromTxList(resultTxList []*TxSearchRes) ([]*relayT for _, resultTx := range resultTxList { msg, err := p.parseMessageFromTx(resultTx) if err != nil { - return nil, err + p.logger.Error("Failed to parse message from tx", zap.Error(err)) + continue } if msg == nil { continue @@ -1369,7 +1396,7 @@ func (p *Provider) runBlockQuery(ctx context.Context, blockInfoChan chan *relayT }(wg, heightStream) } wg.Wait() - return toHeight + 1 + return toHeight } func (p *Provider) getAddressesFromTx(txOut *wire.TxOut, chainParams *chaincfg.Params) []string { diff --git a/relayer/chains/bitcoin/slave.go b/relayer/chains/bitcoin/slave.go index dce52ac7..4ddd81ce 100644 --- a/relayer/chains/bitcoin/slave.go +++ b/relayer/chains/bitcoin/slave.go @@ -48,7 +48,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request, p *Provider) { http.Error(w, "Error decoding request body", http.StatusInternalServerError) return } - sigs, _ := buildAndSignTxFromDbMessage(rsi.MsgSn, rsi.FeeRate, p) + sigs, _ := buildAndSignTxFromDbMessage(rsi, p) // return sigs to master returnData, _ := json.Marshal(sigs) w.Write(returnData) @@ -103,16 +103,16 @@ func validateMethod(w http.ResponseWriter, r *http.Request, p *Provider) bool { return true } -func buildAndSignTxFromDbMessage(sn string, feeRate int, p *Provider) ([][]byte, error) { - p.logger.Info("Slave start to build and sign tx from db message", zap.String("sn", sn)) - key := sn +func buildAndSignTxFromDbMessage(params slaveRequestParams, p *Provider) ([][]byte, error) { + p.logger.Info("Slave start to build and sign tx from db message", zap.String("sn", params.MsgSn)) + key := params.MsgSn data, err := p.db.Get([]byte(key), nil) if err != nil { return nil, err } - if strings.Contains(sn, "RB") { - p.logger.Info("Rollback message", zap.String("sn", sn)) + if strings.Contains(params.MsgSn, "RB") { + p.logger.Info("Rollback message", zap.String("sn", params.MsgSn)) return nil, nil } @@ -122,7 +122,7 @@ func buildAndSignTxFromDbMessage(sn string, feeRate int, p *Provider) ([][]byte, return nil, err } - _, _, _, relayerSigns, _, err := p.HandleBitcoinMessageTx(message.Message, feeRate) + _, _, _, relayerSigns, _, err := p.HandleBitcoinMessageTx(message.Message, params.FeeRate, params.Inputs) if err != nil { return nil, err } From 161c65acae60333dcfc4e1c8764e8f06b9868eb4 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Sun, 17 Nov 2024 18:53:44 +0700 Subject: [PATCH 099/113] feat: mainnet test --- .../chains/bitcoin/provider_mainnet_test.go | 596 ++++++++++++++++ relayer/chains/bitcoin/provider_route_test.go | 606 ---------------- relayer/chains/bitcoin/provider_test.go | 662 ++++++++++-------- 3 files changed, 977 insertions(+), 887 deletions(-) create mode 100644 relayer/chains/bitcoin/provider_mainnet_test.go delete mode 100644 relayer/chains/bitcoin/provider_route_test.go diff --git a/relayer/chains/bitcoin/provider_mainnet_test.go b/relayer/chains/bitcoin/provider_mainnet_test.go new file mode 100644 index 00000000..f3806da2 --- /dev/null +++ b/relayer/chains/bitcoin/provider_mainnet_test.go @@ -0,0 +1,596 @@ +package bitcoin + +import ( + "bytes" + "encoding/base64" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + "os" + "path/filepath" + "testing" + + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/txscript" + "github.com/icon-project/centralized-relay/relayer/events" + relayTypes "github.com/icon-project/centralized-relay/relayer/types" + "github.com/icon-project/centralized-relay/utils/multisig" + "github.com/syndtr/goleveldb/leveldb" + "go.uber.org/zap" +) + +const ( + // MAIN NET + MAINNET_USER_WALLET_ADDRESS = "" + MAINNET_RELAYER_ADDRESS = "" + MAINNET_ASSET_MANAGER_ADDRESS = "" + MAINNET_ASSET_MANAGER_ADDRESS_WRONG = "" + MAINNET_CONNECTION_ADDRESS = "" + MAINNET_TX_FEE = 20000 +) + +func initBtcProviderMainnet() (*Provider, string) { + tempDir, _ := os.MkdirTemp("", "bitcoin_provider_test") + + dbPath := filepath.Join(tempDir, "test.db") + db, _ := leveldb.OpenFile(dbPath, nil) + + logger, _ := zap.NewDevelopment() + + config := &Config{} + config = &Config{ + UniSatURL: "https://open-api.unisat.io", + UniSatKey: "", + + MasterPubKey: "", + Slave1PubKey: "", + Slave2PubKey: "", + RelayerPrivKey: "", + RecoveryLockTime: 0, + OpCode: 0x5e, + MempoolURL: "https://mempool.space/api/v1", + SlaveServer1: "http://localhost:8081", + SlaveServer2: "http://localhost:8082", + Port: "8080", + RequestTimeout: 1000, + ApiKey: "key", + Connections: []string{MAINNET_CONNECTION_ADDRESS}, + } + config.NID = "0x1.btc" + config.Address = MAINNET_RELAYER_ADDRESS + config.RPCUrl = "" + config.User = "123" + config.Password = "123" + + connConfig := &rpcclient.ConnConfig{ + Host: config.RPCUrl, + User: config.User, + Pass: config.Password, + HTTPPostMode: true, + DisableTLS: true, + } + client, err := rpcclient.New(connConfig, nil) + if err != nil { + fmt.Println("err: ", err) + return nil, "" + } + + provider := &Provider{ + logger: logger, + db: db, + cfg: config, + client: &Client{client: client, log: logger}, + chainParam: &chaincfg.MainNetParams, + } + + msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, provider.chainParam) + multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) + provider.multisigAddrScript = multisigAddressScript + return provider, tempDir +} + +func buildUserMultisigWalletMainnet(chainParam *chaincfg.Params) ([]string, *multisig.MultisigWallet, error) { + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 1}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + return userPrivKeys, userMultisigWallet, nil +} + +// parse message from icon and build withdraw btc tx +func TestBuildWithdrawBtcTxMessageMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + + // decode message from icon + data, _ := base64.StdEncoding.DecodeString("+QEfAbkBG/kBGLMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5kAbhU+FKKV2l0aGRyYXdUb4MwOjG4PnRiMXBnZTh0aHUzdTBreXF3NXY1dmxoamd0eWR6MzJtbWtkeGRnanRsOTlqcjVmNTlxczB5YXhzNTZ3a3l6gicQ+Ei4RjB4Mi5idGMvdGIxcGd6eDg4MHlmcjdxOGRnejhkcWh3NTBzbmN1NGY0aG13NWNuMzgwMDM1NHR1emN5OWp4NXNodnY3c3U=") + message := &relayTypes.Message{ + Src: "0x1.icon", + Dst: "0x1.btc", + Sn: big.NewInt(11), + MessageHeight: 1000000, + EventType: events.EmitMessage, + Data: data, + } + feeRate := 10 + + inputs, msWallet, msgTx, relayerSigs, feeRate, err := btcProvider.HandleBitcoinMessageTx(message, feeRate, []slaveRequestInput{}) + if err != nil { + btcProvider.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) + // return + } + totalSigs := [][][]byte{relayerSigs} + // send unsigned raw tx and message sn to 2 slave relayers to get sign + rsi := slaveRequestParams{ + MsgSn: message.Sn.String(), + FeeRate: feeRate, + } + + slaveRequestData, _ := json.Marshal(rsi) + slaveSigs := btcProvider.CallSlaves(slaveRequestData, "") + btcProvider.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) + totalSigs = append(totalSigs, slaveSigs...) + // combine sigs + signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + var buf bytes.Buffer + err = signedMsgTx.Serialize(&buf) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + signedMsgTxHex := hex.EncodeToString(buf.Bytes()) + btcProvider.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + + btcProvider.cacheSpentUTXOs(inputs) + + // Broadcast transaction to bitcoin network + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(signedMsgTxHex)}) + if err != nil { + btcProvider.removeCachedSpentUTXOs(inputs) + btcProvider.logger.Error("failed to send raw transaction", zap.Error(err)) + // return + } + + btcProvider.logger.Info("txHash", zap.String("transaction_hash", txHash)) +} + +// parse message from icon and build withdraw rune tx +func TestBuildWithdrawRunesTxMessageMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + // decode message from icon + data, _ := base64.StdEncoding.DecodeString("+QEoAbkBJPkBIbMweDIuaWNvbi9jeDhjOWEyMTNjZDVkY2ViZmI1MzljMzBlMWFmNmQ3Nzk5MGIyMDBjYTS4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi6wArhd+FuKV2l0aGRyYXdUb4wyOTA0MzU0OjMxMTm4PnRiMXB5OHZ4ZTdlY3dqdGRsdmNjcmVrZ3E1dTkwcnpzZzV3djZhamg0YXZjcDRxNXBrdjYyOWRxeDZlZGg5gg+g+Ei4RjB4Mi5idGMvdGIxcGYwYXRwdDJkM3plbDZ1ZHdzMzhwa3JoMmU0OXZxZDNjNWpjdWQzYTgyc3JwaG5tcGU1NXEwZWNyems=") + message := &relayTypes.Message{ + Src: "0x1.icon", + Dst: "0x1.btc", + Sn: big.NewInt(12), + MessageHeight: 46166601, + EventType: events.EmitMessage, + Data: data, + } + feeRate := 10 + inputs, msWallet, msgTx, relayerSigs, feeRate, err := btcProvider.HandleBitcoinMessageTx(message, feeRate, []slaveRequestInput{}) + if err != nil { + btcProvider.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) + // return + } + totalSigs := [][][]byte{relayerSigs} + // send unsigned raw tx and message sn to 2 slave relayers to get sign + rsi := slaveRequestParams{ + MsgSn: message.Sn.String(), + FeeRate: feeRate, + } + + slaveRequestData, _ := json.Marshal(rsi) + slaveSigs := btcProvider.CallSlaves(slaveRequestData, "") + btcProvider.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) + totalSigs = append(totalSigs, slaveSigs...) + // combine sigs + signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + var buf bytes.Buffer + err = signedMsgTx.Serialize(&buf) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + signedMsgTxHex := hex.EncodeToString(buf.Bytes()) + btcProvider.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + + btcProvider.cacheSpentUTXOs(inputs) + + // Broadcast transaction to bitcoin network + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(signedMsgTxHex)}) + if err != nil { + btcProvider.removeCachedSpentUTXOs(inputs) + btcProvider.logger.Error("failed to send raw transaction", zap.Error(err)) + } + + btcProvider.logger.Info("txHash", zap.String("transaction_hash", txHash)) +} + +func TestBuildRollbackBtcTxMessageMainnet(t *testing.T) { + // Create a mock Provider + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(MAINNET_RELAYER_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletMainnet(btcProvider.chainParam) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "0:0", + To: "0x1.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address + From: MAINNET_USER_WALLET_ADDRESS, // user bitcoin address + Amount: new(big.Int).SetUint64(5000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: MAINNET_ASSET_MANAGER_ADDRESS, // asset manager + Connectors: []string{ + MAINNET_CONNECTION_ADDRESS, // connector contract + }, + } + + inputs := []*multisig.Input{ + { + TxHash: "89095d016b50644a328667cd5543b0f29c0f2a81242094ea7318bded49cf30a8", + OutputIdx: 8, + OutputAmount: 202763, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + MAINNET_TX_FEE, + ) + if err != nil { + fmt.Println("err: ", err) + } + + // add 10 to output amount to make wrong amount + msgTx.TxOut[0].Value = msgTx.TxOut[0].Value + 10 + + // sign tx + totalSigs := [][][]byte{} + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + + fmt.Println("hexSignedTx: ", hexSignedTx) + + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) + fmt.Println("err: ", err) + +} + +func TestDepositBitcoinToIconMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(MAINNET_RELAYER_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletMainnet(btcProvider.chainParam) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "0:0", + To: "0x1.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: MAINNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(1000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: MAINNET_ASSET_MANAGER_ADDRESS, + Connectors: []string{ + MAINNET_CONNECTION_ADDRESS, + }, + } + + inputs := []*multisig.Input{ + { + TxHash: "e57619adbb62c2e8add13eb2694010f3ba337cf5007ca3674224c272feffb097", + OutputIdx: 6, + OutputAmount: 271530, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + MAINNET_TX_FEE, + ) + + // log hex of unsigned tx + + // sign tx + totalSigs := [][][]byte{} + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } + // COMBINE SIGN + + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + fmt.Println("hexSignedTx: ", hexSignedTx) + + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) + fmt.Println("err: ", err) +} +func TestDepositBitcoinToIconFailMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(MAINNET_RELAYER_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletMainnet(btcProvider.chainParam) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "0:0", + To: "0x1.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: MAINNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(3000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: MAINNET_ASSET_MANAGER_ADDRESS_WRONG, + Connectors: []string{ + MAINNET_CONNECTION_ADDRESS, + }, + } + + inputs := []*multisig.Input{ + { + TxHash: "37ba284f4664c517af1c7fbca8b6ce19b293fe5e4125ac42e35f8b6671968d64", + OutputIdx: 6, + OutputAmount: 234779, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + MAINNET_TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx + totalSigs := [][][]byte{} + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + fmt.Println("hexSignedTx: ", hexSignedTx) + + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) + fmt.Println("err: ", err) +} + +func TestDepositRuneToIconMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(MAINNET_RELAYER_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletMainnet(btcProvider.chainParam) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "1:0", + To: "0x1.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: MAINNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(1).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: MAINNET_ASSET_MANAGER_ADDRESS, + Connectors: []string{ + MAINNET_CONNECTION_ADDRESS, + }, + } + + inputs := []*multisig.Input{ + // user rune UTXOs to spend + { + TxHash: "e6107730017b2b84e187add5c3fed5a71edcda0b85b982297282137fe0480234", + OutputIdx: 1, + OutputAmount: 546, + PkScript: userMultisigWallet.PKScript, + }, + // user bitcoin UTXOs to pay tx fee + { + TxHash: "9a9d955dff45c6cef6f4e41a12052dde21179069a2e17fe8f381f6c75e112b6a", + OutputIdx: 6, + OutputAmount: 261795, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendRune( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + MAINNET_TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx + totalSigs := [][][]byte{} + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + + fmt.Println("hexSignedTx: ", hexSignedTx) + + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) + fmt.Println("err: ", err) +} + +func TestDepositRuneToIconFailMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(MAINNET_RELAYER_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletMainnet(btcProvider.chainParam) + + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "1:0", + To: "0x1.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: MAINNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(1).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: MAINNET_ASSET_MANAGER_ADDRESS_WRONG, + Connectors: []string{ + MAINNET_CONNECTION_ADDRESS, + }, + } + + inputs := []*multisig.Input{ + // user rune UTXOs to spend + { + TxHash: "924c7c6bd13f465b0b50cb8ad883544b22bfe54fae42e2ecfc9f9609a1b616f7", + OutputIdx: 1, + OutputAmount: 546, + PkScript: userMultisigWallet.PKScript, + }, + // user bitcoin UTXOs to pay tx fee + { + TxHash: "b84060ce292dd61f8490bae54f8354caa8642de730e5f409b72d67b05617dcb0", + OutputIdx: 6, + OutputAmount: 226044, + PkScript: userMultisigWallet.PKScript, + }, + } + + // create tx + msgTx, err := multisig.CreateBridgeTxSendRune( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + MAINNET_TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx + totalSigs := [][][]byte{} + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) + + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + fmt.Println("hexSignedTx: ", hexSignedTx) + + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.RPCUrl, []json.RawMessage{json.RawMessage(`"` + hexSignedTx + `"`)}) + fmt.Println("txHash: ", txHash) + fmt.Println("err: ", err) +} + +func TestBuildRelayerMultisigWalletMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + msWallet, err := btcProvider.buildMultisigWallet() + fmt.Println("err: ", err) + fmt.Println("msWallet TapScriptTree: ", msWallet.TapScriptTree) + fmt.Println("msWallet TapLeaves: ", msWallet.TapLeaves) + fmt.Println("msWallet PKScript: ", hex.EncodeToString(msWallet.PKScript)) + fmt.Println("msWallet SharedPublicKey: ", msWallet.SharedPublicKey.ToECDSA()) + // log msWallet address + addr, err := multisig.AddressOnChain(btcProvider.chainParam, msWallet) + fmt.Println("msWallet Address: ", addr.String()) + fmt.Println("err: ", err) +} + +func TestBuildUserMultisigWalletMainnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderMainnet() + defer os.Remove(termpDir) + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletMainnet(btcProvider.chainParam) + fmt.Println("userPrivKeys: ", userPrivKeys) + fmt.Println("userMultisigWallet: ", userMultisigWallet) + addr, err := multisig.AddressOnChain(btcProvider.chainParam, userMultisigWallet) + fmt.Println("userMultisigWallet Address: ", addr.String()) + fmt.Println("err: ", err) +} diff --git a/relayer/chains/bitcoin/provider_route_test.go b/relayer/chains/bitcoin/provider_route_test.go deleted file mode 100644 index b6c1ca5f..00000000 --- a/relayer/chains/bitcoin/provider_route_test.go +++ /dev/null @@ -1,606 +0,0 @@ -package bitcoin - -import ( - "bytes" - "context" - "encoding/base64" - "encoding/hex" - "encoding/json" - "fmt" - "math/big" - "os" - "path/filepath" - "testing" - - "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcd/txscript" - "github.com/btcsuite/btcd/wire" - "github.com/bxelab/runestone" - "github.com/icon-project/centralized-relay/relayer/events" - "github.com/icon-project/centralized-relay/relayer/types" - "github.com/icon-project/centralized-relay/utils/multisig" - "github.com/stretchr/testify/assert" - "github.com/syndtr/goleveldb/leveldb" - "go.uber.org/zap" -) - -const ( - TX_FEE = 10000 - RELAYER_MULTISIG_ADDRESS = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" - USER_MULTISIG_ADDRESS = "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" -) - -func TestDecodeWithdrawToMessage(t *testing.T) { - input := "+QEdAbkBGfkBFrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1gh6FAbhS+FCKV2l0aGRyYXdUb4MwOjC4PnRiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1ZPhIuEYweDIuYnRjL3RiMXBneng4ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1" - // Decode base64 - decodedBytes, _ := base64.StdEncoding.DecodeString(input) - - result, data, err := decodeWithdrawToMessage(decodedBytes) - - fmt.Println("data", data) - - assert.NoError(t, err) - assert.NotNil(t, result) - assert.Equal(t, "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", result.To) - assert.Equal(t, big.NewInt(100).Bytes(), result.Amount) - assert.Equal(t, "WithdrawTo", result.Action) - assert.Equal(t, "0:0", result.TokenAddress) -} - -func TestProvider_Route(t *testing.T) { - // Setup - tempDir, err := os.MkdirTemp("", "bitcoin_provider_test") - assert.NoError(t, err) - defer os.RemoveAll(tempDir) - - dbPath := filepath.Join(tempDir, "test.db") - db, err := leveldb.OpenFile(dbPath, nil) - assert.NoError(t, err) - defer db.Close() - - logger, _ := zap.NewDevelopment() - provider := &Provider{ - logger: logger, - cfg: &Config{Mode: SlaveMode}, - db: db, - } - - // Create a test message - testMessage := &types.Message{ - Dst: "destination", - Src: "source", - Sn: big.NewInt(123), - Data: []byte("test data"), - MessageHeight: 456, - EventType: events.EmitMessage, - } - - // Test storing the message - err = provider.Route(context.Background(), testMessage, nil) - assert.NoError(t, err) - - // Test retrieving the message - key := []byte(fmt.Sprintf("bitcoin_message_%s", testMessage.Sn.String())) - storedData, err := db.Get(key, nil) - assert.NoError(t, err) - - var retrievedMessage types.Message - err = json.Unmarshal(storedData, &retrievedMessage) - assert.NoError(t, err) - - assert.Equal(t, testMessage.Dst, retrievedMessage.Dst) - assert.Equal(t, testMessage.Src, retrievedMessage.Src) - assert.Equal(t, testMessage.Sn.String(), retrievedMessage.Sn.String()) - assert.Equal(t, testMessage.Data, retrievedMessage.Data) - assert.Equal(t, testMessage.MessageHeight, retrievedMessage.MessageHeight) - assert.Equal(t, testMessage.EventType, retrievedMessage.EventType) - - // Test deleting the message - err = db.Delete(key, nil) - assert.NoError(t, err) - - _, err = db.Get(key, nil) - assert.Error(t, err) // Should return an error as the key no longer exists -} - -func TestDepositBitcoinToIcon(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) - relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) - // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - bridgeMsg := multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ - MessageType: 1, - Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(100000).Bytes(), - Data: []byte(""), - }, - ChainId: 1, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", - Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, - } - - inputs := []*multisig.Input{ - { - TxHash: "e57c10e27f75dbf0856163ca5f825b5af7ffbb3874f606b31330464ddd9df9a1", - OutputIdx: 4, - OutputAmount: 2974000, - PkScript: userMultisigWallet.PKScript, - }, - } - - // create tx - msgTx, err := multisig.CreateBridgeTxSendBitcoin( - &bridgeMsg, - inputs, - userMultisigWallet.PKScript, - relayerPkScript, - TX_FEE, - ) - fmt.Println("err: ", err) - // sign tx - totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) - // COMBINE SIGN - signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // TODO: test the signedMsgTx -} - -func TestDepositBitcoinToIconFail1(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - inputs := []*multisig.Input{ - { - TxHash: "eeb8c9f79ecfe7c084b2af95bf82acebd130185a0d188283d78abb58d85eddff", - OutputIdx: 4, - OutputAmount: 2999000, - PkScript: userMultisigWallet.PKScript, - }, - } - - outputs := []*wire.TxOut{} - - // Add Bridge Message - scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ - Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), - Data: []byte(""), - }, - ChainId: 1, - Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", - Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, - }) - for _, script := range scripts { - outputs = append(outputs, &wire.TxOut{ - Value: 0, - PkScript: script, - }) - } - - msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) - fmt.Println("err: ", err) - // sign tx - totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) - // COMBINE SIGN - signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // TODO: test the signedMsgTx -} - -func TestDepositBitcoinToIconFail2(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) - relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) - // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - inputs := []*multisig.Input{ - { - TxHash: "0416795b227e1a6a64eeb7bf7542d15964d18ac4c4732675d3189cda8d38bed7", - OutputIdx: 3, - OutputAmount: 2998000, - PkScript: userMultisigWallet.PKScript, - }, - } - - outputs := []*wire.TxOut{} - - // Add Bridge Message - scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ - Action: "Deposit", - TokenAddress: "0:1", // wrong token address - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000000).Bytes(), // - Data: []byte(""), - }, - ChainId: 1, - Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", - Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, - }) - for _, script := range scripts { - outputs = append(outputs, &wire.TxOut{ - Value: 0, - PkScript: script, - }) - } - - // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &wire.TxOut{ - Value: 1000, - PkScript: relayerPkScript, - }) - - msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) - fmt.Println("err: ", err) - // sign tx - totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) - // COMBINE SIGN - signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // TODO: test the signedMsgTx -} - -func TestDepositBitcoinToIconFail3(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) - relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) - // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - inputs := []*multisig.Input{ - { - TxHash: "dc21f89436d9fbda2cc521ed9b8988c7cbf84cdc67d728b2b2709a5efe7e775a", - OutputIdx: 4, - OutputAmount: 2996000, - PkScript: userMultisigWallet.PKScript, - }, - } - - outputs := []*wire.TxOut{} - - // Add Bridge Message - scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ - Action: "Deposit", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000).Bytes(), // wrong amount - Data: []byte(""), - }, - ChainId: 1, - Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", - Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, - }) - for _, script := range scripts { - outputs = append(outputs, &wire.TxOut{ - Value: 0, - PkScript: script, - }) - } - - // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &wire.TxOut{ - Value: 10000, - PkScript: relayerPkScript, - }) - - msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) - fmt.Println("err: ", err) - // sign tx - totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) - // COMBINE SIGN - signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // TODO: test the signedMsgTx -} - -func TestDepositBitcoinToIconFail4(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) - relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) - // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - inputs := []*multisig.Input{ - { - TxHash: "1e29fa62942f92dd4cf688e219641b54229fbc2ec2dc74cc9c1c7f247c7172b2", - OutputIdx: 4, - OutputAmount: 2985000, - PkScript: userMultisigWallet.PKScript, - }, - } - - outputs := []*wire.TxOut{} - - // Add Bridge Message - scripts, _ := multisig.CreateBridgeMessageScripts(&multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ - Action: "Withdraw", - TokenAddress: "0:1", - To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(1000).Bytes(), - Data: []byte(""), - }, - ChainId: 1, - Receiver: "cx8b52dfea0aa1e548288102df15ad7159f7266106", - Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, - }) - for _, script := range scripts { - outputs = append(outputs, &wire.TxOut{ - Value: 0, - PkScript: script, - }) - } - - // Add transfering bitcoin to relayer multisig - outputs = append(outputs, &wire.TxOut{ - Value: 10000, - PkScript: relayerPkScript, - }) - - msgTx, err := multisig.CreateTx(inputs, outputs, userMultisigWallet.PKScript, TX_FEE, 0) - fmt.Println("err: ", err) - // sign tx - totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) - // COMBINE SIGN - signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // TODO: test the signedMsgTx -} - -// ... existing code ... - -func TestDecodeBitcoinTransaction(t *testing.T) { - // The raw transaction hex string - rawTxHex := "02000000000101b272717c247f1c9ccc74dcc22ebc9f22541b6419e288f64cdd922f9462fa291e040000000001000000050000000000000000506a5e4c4cf88588576974686472617783303a31b83e74623170677a7838383079667237713864677a38647168773530736e6375346634686d7735636e3338303033353474757a6379396a7835736876760000000000000000506a5e4c4c377375b33078322e69636f6e2f6878343532653233356639663166643130303662313934316564316164313965663531643131393266368203e88001738b52dfea0aa1e548288102df15ad7100000000000000001d6a5e1a59f726610673577f5e756abd89cbcba38a58508b60a12754d2f510270000000000002251204bfab0ad4d88b3fd71ae844e1b0eeacd4ac03638a4b1c6c7a754061bcf61cd2830612d0000000000225120408c73bc891f8076a047682eea3e13c72a9adf6ea62713bdf1a557c1608591a903405a713aad72e1a2717cab16446e84a0de1c9f908a100c5903086a97910adc1327db65d21c8533c4fe087027195db4ebe7d8595624382e39b7aba829e3b29a29dc2551b275207303e7756826cf3fabc2f9c06978c542039effbb7493627cad22236e3ff10ee4ac41c18a23958fc9bf526c81a09bca529d685adc6900a04e2f520a26c63aa0b61a770f27c71b203eebab28e2e37b992abd8e6e5f9d887bdc2d5ab0efde76df79d3520400000000" - - // Decode the raw transaction - txBytes, err := hex.DecodeString(rawTxHex) - assert.NoError(t, err) - - var tx wire.MsgTx - err = tx.Deserialize(bytes.NewReader(txBytes)) - assert.NoError(t, err) - - // Extract sender information (from the input) - assert.Equal(t, 1, len(tx.TxIn), "Expected 1 input") - prevOutHash := tx.TxIn[0].PreviousOutPoint.Hash.String() - prevOutIndex := tx.TxIn[0].PreviousOutPoint.Index - fmt.Printf("Sender (Input): %s:%d\n", prevOutHash, prevOutIndex) - - // Extract receiver information (from the outputs) - assert.Equal(t, 5, len(tx.TxOut), "Expected 5 outputs") - - for i, out := range tx.TxOut { - fmt.Printf("Output %d:\n", i) - fmt.Printf(" Amount: %d satoshis\n", out.Value) - - // Attempt to parse the output script - scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(out.PkScript, &chaincfg.TestNet3Params) - if err != nil { - fmt.Printf(" Script: Unable to parse (possibly OP_RETURN)\n") - } else { - fmt.Printf(" Script Class: %s\n", scriptClass) - if len(addresses) > 0 { - fmt.Printf(" Receiver Address: %s\n", addresses[0].String()) - } - } - - // If it's an OP_RETURN output, print the data - if scriptClass == txscript.NullDataTy { - fmt.Printf(" OP_RETURN Data: %x\n", out.PkScript[2:]) - } - - fmt.Println() - } - - // Add assertions for specific outputs - assert.Equal(t, txscript.NullDataTy, txscript.GetScriptClass(tx.TxOut[0].PkScript)) - assert.Equal(t, txscript.NullDataTy, txscript.GetScriptClass(tx.TxOut[1].PkScript)) - assert.Equal(t, txscript.NullDataTy, txscript.GetScriptClass(tx.TxOut[2].PkScript)) - - _, addresses, _, err := txscript.ExtractPkScriptAddrs(tx.TxOut[3].PkScript, &chaincfg.TestNet3Params) - assert.NoError(t, err) - assert.Equal(t, 1, len(addresses)) - assert.Equal(t, "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", addresses[0].String()) - - _, addresses, _, err = txscript.ExtractPkScriptAddrs(tx.TxOut[4].PkScript, &chaincfg.TestNet3Params) - assert.NoError(t, err) - assert.Equal(t, 1, len(addresses)) - assert.Equal(t, "tb1pqqqqp399et2xygdj5xreqhjjvcmzhxw4aywxecjdzew6hylgvsesf3hn0c", addresses[0].String()) -} - -func TestDepositRuneToIcon(t *testing.T) { - chainParam := &chaincfg.TestNet3Params - // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) - relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) - // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) - - bridgeMsg := multisig.BridgeDecodedMsg{ - Message: &multisig.XCallMessage{ - MessageType: 1, - Action: "Deposit", - TokenAddress: "2904354:3119", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(10000).Bytes(), - Data: []byte(""), - }, - ChainId: 1, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", - Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", - }, - } - - inputs := []*multisig.Input{ - // user rune UTXOs to spend - { - TxHash: "69deba39f5a0700cc713f67fe8cb5ed1e35a9f0d4a3a437d839103c6e26cb947", - OutputIdx: 2, - OutputAmount: 546, - PkScript: userMultisigWallet.PKScript, - }, - // user bitcoin UTXOs to pay tx fee - { - TxHash: "16de7df933dacd95b0d3af7325a5a2e680a1b7dd447a97e7678d8dfa1ac750b4", - OutputIdx: 4, - OutputAmount: 445000, - PkScript: userMultisigWallet.PKScript, - }, - } - - // create tx - msgTx, err := multisig.CreateBridgeTxSendRune( - &bridgeMsg, - inputs, - userMultisigWallet.PKScript, - relayerPkScript, - TX_FEE, - ) - fmt.Println("err: ", err) - // sign tx - totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) - // COMBINE SIGN - signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - - var signedTx bytes.Buffer - signedMsgTx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - - // Decipher runestone - r := &runestone.Runestone{} - artifact, err := r.Decipher(signedMsgTx) - if err != nil { - fmt.Println(err) - return - } - a, _ := json.Marshal(artifact) - fmt.Printf("Artifact: %s\n", string(a)) - - // TODO: test the signedMsgTx -} diff --git a/relayer/chains/bitcoin/provider_test.go b/relayer/chains/bitcoin/provider_test.go index acf73782..aeb37eff 100644 --- a/relayer/chains/bitcoin/provider_test.go +++ b/relayer/chains/bitcoin/provider_test.go @@ -15,9 +15,6 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/txscript" - "github.com/bxelab/runestone" - "github.com/icon-project/centralized-relay/relayer/chains/icon" - "github.com/icon-project/centralized-relay/relayer/chains/icon/types" "github.com/icon-project/centralized-relay/relayer/events" relayTypes "github.com/icon-project/centralized-relay/relayer/types" "github.com/icon-project/centralized-relay/utils/multisig" @@ -25,7 +22,17 @@ import ( "go.uber.org/zap" ) -func initBtcProvider() (*Provider, string) { +const ( + // TESTNET + TESTNET_USER_WALLET_ADDRESS = "" + TESTNET_RELAYER_ADDRESS = "" + TESTNET_ASSET_MANAGER_ADDRESS = "" + TESTNET_ASSET_MANAGER_ADDRESS_WRONG = "" + TESTNET_CONNECTION_ADDRESS = "" + TESTNET_TX_FEE = 20000 +) + +func initBtcProviderTestnet() (*Provider, string) { tempDir, _ := os.MkdirTemp("", "bitcoin_provider_test") dbPath := filepath.Join(tempDir, "test.db") @@ -35,32 +42,28 @@ func initBtcProvider() (*Provider, string) { config := &Config{} config = &Config{ - Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, - UniSatURL: "https://open-api-testnet.unisat.io", - UniSatKey: "60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d", - RecoveryLockTime: 1234, - MasterPubKey: "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2", - Slave1PubKey: "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052", - Slave2PubKey: "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833", - MempoolURL: "https://mempool.space/testnet/api/v1", - SlaveServer1: "http://18.234.252.46:8081", - SlaveServer2: "http://3.81.55.23:8082", + UniSatURL: "https://open-api.unisat.io", + UniSatKey: "", + + MasterPubKey: "", + Slave1PubKey: "", + Slave2PubKey: "", + RelayerPrivKey: "", + RecoveryLockTime: 0, + OpCode: 0x5e, + MempoolURL: "https://mempool.space/api/v1", + SlaveServer1: "http://localhost:8081", + SlaveServer2: "http://localhost:8082", Port: "8080", RequestTimeout: 1000, ApiKey: "key", + Connections: []string{TESTNET_CONNECTION_ADDRESS}, } config.NID = "0x2.btc" - config.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" - // config.RPCUrl = "stylish-white-paper.btc-testnet.quiknode.pro/f87ecf84754d9daf8cf45b0334ba3fee9b356db6/" - config.RPCUrl = "http://lydialabs:lydialabsq23%21%40@54.92.152.113:18332" - config.User = "lydialabs" - config.Password = "lydialabsq23!@" - config.MasterPubKey = "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2" - config.Slave1PubKey = "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052" - config.Slave2PubKey = "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833" - config.RelayerPrivKey = "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy" - config.RecoveryLockTime = 1234 - config.OpCode = 0x5e + config.Address = TESTNET_RELAYER_ADDRESS + config.RPCUrl = "" + config.User = "123" + config.Password = "123" connConfig := &rpcclient.ConnConfig{ Host: config.RPCUrl, @@ -89,53 +92,167 @@ func initBtcProvider() (*Provider, string) { return provider, tempDir } -func TestParseMessageFromTx(t *testing.T) { - // Create a mock Provider - chainParam := &chaincfg.TestNet3Params - logger, _ := zap.NewDevelopment() - provider := &Provider{ - logger: logger, - cfg: &Config{ - Connections: []string{"cx577f5e756abd89cbcba38a58508b60a12754d2f5"}, - }, - chainParam: &chaincfg.TestNet3Params, +func buildUserMultisigWalletTestnet(chainParam *chaincfg.Params) ([]string, *multisig.MultisigWallet, error) { + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 1}, 1, 1) + userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + return userPrivKeys, userMultisigWallet, nil +} + +// parse message from icon and build withdraw btc tx +func TestBuildWithdrawBtcTxMessageTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() + defer os.Remove(termpDir) + + // decode message from icon + data, _ := base64.StdEncoding.DecodeString("+QEfAbkBG/kBGLMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5kAbhU+FKKV2l0aGRyYXdUb4MwOjG4PnRiMXBnZTh0aHUzdTBreXF3NXY1dmxoamd0eWR6MzJtbWtkeGRnanRsOTlqcjVmNTlxczB5YXhzNTZ3a3l6gicQ+Ei4RjB4Mi5idGMvdGIxcGd6eDg4MHlmcjdxOGRnejhkcWh3NTBzbmN1NGY0aG13NWNuMzgwMDM1NHR1emN5OWp4NXNodnY3c3U=") + message := &relayTypes.Message{ + Src: "0x2.icon", + Dst: "0x2.btc", + Sn: big.NewInt(11), + MessageHeight: 1000000, + EventType: events.EmitMessage, + Data: data, } - provider.cfg.NID = "0x2.btc" + feeRate := 10 - provider.cfg.Address = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" - msPubkey, _ := btcutil.DecodeAddress(provider.cfg.Address, chainParam) - multisigAddressScript, _ := txscript.PayToAddrScript(msPubkey) - provider.multisigAddrScript = multisigAddressScript - // Create a mock TxSearchRes + inputs, msWallet, msgTx, relayerSigs, feeRate, err := btcProvider.HandleBitcoinMessageTx(message, feeRate, []slaveRequestInput{}) + if err != nil { + btcProvider.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) + // return + } + totalSigs := [][][]byte{relayerSigs} + // send unsigned raw tx and message sn to 2 slave relayers to get sign + rsi := slaveRequestParams{ + MsgSn: message.Sn.String(), + FeeRate: feeRate, + } + + slaveRequestData, _ := json.Marshal(rsi) + slaveSigs := btcProvider.CallSlaves(slaveRequestData, "") + btcProvider.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) + totalSigs = append(totalSigs, slaveSigs...) + // combine sigs + signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + var buf bytes.Buffer + err = signedMsgTx.Serialize(&buf) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + signedMsgTxHex := hex.EncodeToString(buf.Bytes()) + btcProvider.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + + btcProvider.cacheSpentUTXOs(inputs) + + // Broadcast transaction to bitcoin network + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(signedMsgTxHex)}) + if err != nil { + btcProvider.removeCachedSpentUTXOs(inputs) + btcProvider.logger.Error("failed to send raw transaction", zap.Error(err)) + // return + } + + btcProvider.logger.Info("txHash", zap.String("transaction_hash", txHash)) +} + +// parse message from icon and build withdraw rune tx +func TestBuildWithdrawRunesTxMessageTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() + defer os.Remove(termpDir) + // decode message from icon + data, _ := base64.StdEncoding.DecodeString("+QEoAbkBJPkBIbMweDIuaWNvbi9jeDhjOWEyMTNjZDVkY2ViZmI1MzljMzBlMWFmNmQ3Nzk5MGIyMDBjYTS4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi6wArhd+FuKV2l0aGRyYXdUb4wyOTA0MzU0OjMxMTm4PnRiMXB5OHZ4ZTdlY3dqdGRsdmNjcmVrZ3E1dTkwcnpzZzV3djZhamg0YXZjcDRxNXBrdjYyOWRxeDZlZGg5gg+g+Ei4RjB4Mi5idGMvdGIxcGYwYXRwdDJkM3plbDZ1ZHdzMzhwa3JoMmU0OXZxZDNjNWpjdWQzYTgyc3JwaG5tcGU1NXEwZWNyems=") + message := &relayTypes.Message{ + Src: "0x2.icon", + Dst: "0x2.btc", + Sn: big.NewInt(12), + MessageHeight: 46166601, + EventType: events.EmitMessage, + Data: data, + } + feeRate := 10 + inputs, msWallet, msgTx, relayerSigs, feeRate, err := btcProvider.HandleBitcoinMessageTx(message, feeRate, []slaveRequestInput{}) + if err != nil { + btcProvider.logger.Error("failed to handle bitcoin message tx: %v", zap.Error(err)) + // return + } + totalSigs := [][][]byte{relayerSigs} + // send unsigned raw tx and message sn to 2 slave relayers to get sign + rsi := slaveRequestParams{ + MsgSn: message.Sn.String(), + FeeRate: feeRate, + } + + slaveRequestData, _ := json.Marshal(rsi) + slaveSigs := btcProvider.CallSlaves(slaveRequestData, "") + btcProvider.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) + totalSigs = append(totalSigs, slaveSigs...) + // combine sigs + signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + var buf bytes.Buffer + err = signedMsgTx.Serialize(&buf) + + if err != nil { + btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + } + + signedMsgTxHex := hex.EncodeToString(buf.Bytes()) + btcProvider.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + + btcProvider.cacheSpentUTXOs(inputs) + + // Broadcast transaction to bitcoin network + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(signedMsgTxHex)}) + if err != nil { + btcProvider.removeCachedSpentUTXOs(inputs) + btcProvider.logger.Error("failed to send raw transaction", zap.Error(err)) + } + + btcProvider.logger.Info("txHash", zap.String("transaction_hash", txHash)) +} + +func TestBuildRollbackBtcTxMessageTestnet(t *testing.T) { + // Create a mock Provider + btcProvider, termpDir := initBtcProviderTestnet() + defer os.Remove(termpDir) // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, chainParam) + decodedAddr, _ := btcutil.DecodeAddress(TESTNET_RELAYER_ADDRESS, btcProvider.chainParam) relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletTestnet(btcProvider.chainParam) bridgeMsg := multisig.BridgeDecodedMsg{ Message: &multisig.XCallMessage{ - MessageType: 0, - Action: MethodDeposit, - TokenAddress: "0:1", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", // user bitcoin address - Amount: new(big.Int).SetUint64(15000).Bytes(), + MessageType: 1, + Action: "Deposit", + TokenAddress: "0:0", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address + From: TESTNET_USER_WALLET_ADDRESS, // user bitcoin address + Amount: new(big.Int).SetUint64(5000).Bytes(), Data: []byte(""), }, - ChainId: 3, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", // asset manager + ChainId: 1, + Receiver: TESTNET_ASSET_MANAGER_ADDRESS, // asset manager Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", // connector contract + TESTNET_CONNECTION_ADDRESS, // connector contract }, } inputs := []*multisig.Input{ { - TxHash: "af88dfc8907cc9867e83c05ec061472cdff8cc9b9f951282a5e0f6a0b0b7141b", - OutputIdx: 1, - OutputAmount: 909000, + TxHash: "89095d016b50644a328667cd5543b0f29c0f2a81242094ea7318bded49cf30a8", + OutputIdx: 8, + OutputAmount: 202763, PkScript: userMultisigWallet.PKScript, }, } @@ -146,351 +263,334 @@ func TestParseMessageFromTx(t *testing.T) { inputs, userMultisigWallet.PKScript, relayerPkScript, - TX_FEE, + TESTNET_TX_FEE, ) - fmt.Println("err: ", err) + if err != nil { + fmt.Println("err: ", err) + } + + // add 10 to output amount to make wrong amount + msgTx.TxOut[0].Value = msgTx.TxOut[0].Value + 10 + // sign tx totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } // COMBINE SIGN signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - bridgeMessage, err := multisig.ReadBridgeMessage(signedMsgTx) - fmt.Println("bridgeMessage: ", bridgeMessage) - fmt.Println("err: ", err) - txSearchRes := &TxSearchRes{ - Tx: signedMsgTx, - Height: 3181075, - TxIndex: 21, - BridgeMessage: bridgeMessage, - } - relayerMessage, err := provider.parseMessageFromTx(txSearchRes) - fmt.Println("relayerMessage Src: ", relayerMessage.Src) - fmt.Println("relayerMessage Sn: ", relayerMessage.Sn) - fmt.Println("relayerMessage Data: ", relayerMessage.Data) + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) fmt.Println("err: ", err) - msg := &types.RecvMessage{ - SrcNID: relayerMessage.Src, - ConnSn: types.NewHexInt(relayerMessage.Sn.Int64()), - Msg: types.NewHexBytes(relayerMessage.Data), - } - iconProvider := &icon.Provider{} - - iconMessage := iconProvider.NewIconMessage(iconProvider.GetAddressByEventType(relayerMessage.EventType), msg, icon.MethodRecvMessage) - fmt.Println("iconMessage Method: ", iconMessage.Method) - fmt.Println("iconMessage Params: ", iconMessage.Params) } -func TestParseRuneMessageFromTx(t *testing.T) { - btcProvider, termpDir := initBtcProvider() +func TestDepositBitcoinToIconTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() defer os.Remove(termpDir) // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, btcProvider.chainParam) + decodedAddr, _ := btcutil.DecodeAddress(TESTNET_RELAYER_ADDRESS, btcProvider.chainParam) relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, btcProvider.chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletTestnet(btcProvider.chainParam) bridgeMsg := multisig.BridgeDecodedMsg{ Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "2904354:3119", + TokenAddress: "0:0", To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", - Amount: new(big.Int).SetUint64(200000).Bytes(), + From: TESTNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), }, ChainId: 1, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + Receiver: TESTNET_ASSET_MANAGER_ADDRESS, Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + TESTNET_CONNECTION_ADDRESS, }, } inputs := []*multisig.Input{ - // user rune UTXOs to spend { - TxHash: "69deba39f5a0700cc713f67fe8cb5ed1e35a9f0d4a3a437d839103c6e26cb947", - OutputIdx: 2, - OutputAmount: 546, - PkScript: userMultisigWallet.PKScript, - }, - // user bitcoin UTXOs to pay tx fee - { - TxHash: "073af76df4d7503446ccf704469926ba584ed6a85df1ffb702d3a148a083bd87", - OutputIdx: 2, - OutputAmount: 2874285, + TxHash: "e57619adbb62c2e8add13eb2694010f3ba337cf5007ca3674224c272feffb097", + OutputIdx: 6, + OutputAmount: 271530, PkScript: userMultisigWallet.PKScript, }, } // create tx - msgTx, err := multisig.CreateBridgeTxSendRune( + msgTx, err := multisig.CreateBridgeTxSendBitcoin( &bridgeMsg, inputs, userMultisigWallet.PKScript, relayerPkScript, - TX_FEE, + TESTNET_TX_FEE, ) - fmt.Println("err: ", err) + + // log hex of unsigned tx + // sign tx totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() - fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - // Decipher runestone - r := &runestone.Runestone{} - artifact, err := r.Decipher(signedMsgTx) - if err != nil { - fmt.Println(err) - return - } - a, _ := json.Marshal(artifact) - fmt.Printf("Artifact: %s\n", string(a)) - - bridgeMessage, err := multisig.ReadBridgeMessage(signedMsgTx) - fmt.Println("bridgeMessage: ", bridgeMessage) - fmt.Println("err: ", err) - txSearchRes := &TxSearchRes{ - Tx: signedMsgTx, - Height: 3181071, - TxIndex: 21, - BridgeMessage: bridgeMessage, - } - relayerMessage, err := btcProvider.parseMessageFromTx(txSearchRes) - fmt.Println("relayerMessage Src: ", relayerMessage) - // fmt.Println("relayerMessage Sn: ", relayerMessage.Sn) - // fmt.Println("relayerMessage Data: ", relayerMessage.Data) + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) fmt.Println("err: ", err) - - msg := &types.RecvMessage{ - SrcNID: relayerMessage.Src, - ConnSn: types.NewHexInt(relayerMessage.Sn.Int64()), - Msg: types.NewHexBytes(relayerMessage.Data), - } - iconProvider := &icon.Provider{} - - iconMessage := iconProvider.NewIconMessage(iconProvider.GetAddressByEventType(relayerMessage.EventType), msg, icon.MethodRecvMessage) - fmt.Println("iconMessage Method: ", iconMessage.Method) - fmt.Println("iconMessage Params: ", iconMessage.Params) - } - -// parse message from icon and build withdraw btc tx -func TestBuildWithdrawBtcTxMessage(t *testing.T) { - btcProvider, termpDir := initBtcProvider() +func TestDepositBitcoinToIconFailTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() defer os.Remove(termpDir) + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(TESTNET_RELAYER_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletTestnet(btcProvider.chainParam) - data, _ := base64.StdEncoding.DecodeString("+QEfAbkBG/kBGLMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5kAbhU+FKKV2l0aGRyYXdUb4MwOjG4PnRiMXBnZTh0aHUzdTBreXF3NXY1dmxoamd0eWR6MzJtbWtkeGRnanRsOTlqcjVmNTlxczB5YXhzNTZ3a3l6gicQ+Ei4RjB4Mi5idGMvdGIxcGd6eDg4MHlmcjdxOGRnejhkcWh3NTBzbmN1NGY0aG13NWNuMzgwMDM1NHR1emN5OWp4NXNodnY3c3U=") - message := &relayTypes.Message{ - Src: "0x2.icon", - Dst: "0x2.btc", - Sn: big.NewInt(11), - MessageHeight: 1000000, - EventType: events.EmitMessage, - Data: data, + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "0:0", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: TESTNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(3000).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: TESTNET_ASSET_MANAGER_ADDRESS_WRONG, + Connectors: []string{ + TESTNET_CONNECTION_ADDRESS, + }, } - msWallet, err := btcProvider.buildMultisigWallet() - if err != nil { - fmt.Println("err: ", err) - return + inputs := []*multisig.Input{ + { + TxHash: "37ba284f4664c517af1c7fbca8b6ce19b293fe5e4125ac42e35f8b6671968d64", + OutputIdx: 6, + OutputAmount: 234779, + PkScript: userMultisigWallet.PKScript, + }, } - inputs, tx, err := btcProvider.buildTxMessage(message, 10, msWallet) + // create tx + msgTx, err := multisig.CreateBridgeTxSendBitcoin( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + TESTNET_TX_FEE, + ) fmt.Println("err: ", err) - fmt.Println("inputs: ", inputs) - fmt.Println("tx: ", tx) - var signedTx bytes.Buffer - tx.Serialize(&signedTx) - hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - fmt.Println("hexSignedTx: ", hexSignedTx) -} - -// parse message from icon and build withdraw rune tx -func TestBuildWithdrawRunesTxMessage(t *testing.T) { - btcProvider, termpDir := initBtcProvider() - defer os.Remove(termpDir) - data, _ := base64.StdEncoding.DecodeString("+QEpAbkBJfkBIrMweDIuaWNvbi9jeGZjODZlZTc2ODdlMWJmNjgxYjU1NDhiMjY2Nzg0NDQ4NWMwZTcxOTK4PnRiMXBmMGF0cHQyZDN6ZWw2dWR3czM4cGtyaDJlNDl2cWQzYzVqY3VkM2E4MnNycGhubXBlNTVxMGVjcnprgi5uAbhe+FyKV2l0aGRyYXdUb4wyOTA0MzU0OjMxMTm4PnRiMXBneng8ODB5ZnI3cThkZ3o4ZHFodzUwc25jdTRmNGhtdzVjbjM4MDAzNTR0dXpjeTlqeDVzaHZ2N3N1") - message := &relayTypes.Message{ - Src: "0x2.icon", - Dst: "0x2.btc", - Sn: big.NewInt(11), - MessageHeight: 1000000, - EventType: events.EmitMessage, - Data: data, - } - - msWallet, err := btcProvider.buildMultisigWallet() - if err != nil { - fmt.Println("err: ", err) - return + // sign tx + totalSigs := [][][]byte{} + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) } + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - inputs, tx, err := btcProvider.buildTxMessage(message, 10, msWallet) - fmt.Println("err: ", err) - fmt.Println("inputs: ", inputs) - fmt.Println("tx: ", tx) var signedTx bytes.Buffer - tx.Serialize(&signedTx) + signedMsgTx.Serialize(&signedTx) hexSignedTx := hex.EncodeToString(signedTx.Bytes()) fmt.Println("hexSignedTx: ", hexSignedTx) + + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) + fmt.Println("err: ", err) } -func TestBuildRollbackBtcTxMessage(t *testing.T) { - // Create a mock Provider - btcProvider, termpDir := initBtcProvider() +func TestDepositRuneToIconTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() defer os.Remove(termpDir) - // Create a mock TxSearchRes // relayer multisig - decodedAddr, _ := btcutil.DecodeAddress(RELAYER_MULTISIG_ADDRESS, btcProvider.chainParam) + decodedAddr, _ := btcutil.DecodeAddress(TESTNET_RELAYER_ADDRESS, btcProvider.chainParam) relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) // user key - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, btcProvider.chainParam, []int{0, 3}, 1, 1) - userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletTestnet(btcProvider.chainParam) bridgeMsg := multisig.BridgeDecodedMsg{ Message: &multisig.XCallMessage{ - MessageType: 0, - Action: MethodDeposit, - TokenAddress: "0:1", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address - From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", // user bitcoin address - Amount: new(big.Int).SetUint64(15000).Bytes(), + MessageType: 1, + Action: "Deposit", + TokenAddress: "1:0", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: TESTNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(1).Bytes(), Data: []byte(""), }, - ChainId: 3, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", // asset manager + ChainId: 1, + Receiver: TESTNET_ASSET_MANAGER_ADDRESS, Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", // connector contract + TESTNET_CONNECTION_ADDRESS, }, } inputs := []*multisig.Input{ + // user rune UTXOs to spend { - TxHash: "0c95bf20150345ae6e726c986edb8c3019c325ea1049490755191085e3c453fa", + TxHash: "e6107730017b2b84e187add5c3fed5a71edcda0b85b982297282137fe0480234", + OutputIdx: 1, + OutputAmount: 546, + PkScript: userMultisigWallet.PKScript, + }, + // user bitcoin UTXOs to pay tx fee + { + TxHash: "9a9d955dff45c6cef6f4e41a12052dde21179069a2e17fe8f381f6c75e112b6a", OutputIdx: 6, - OutputAmount: 2607546, + OutputAmount: 261795, PkScript: userMultisigWallet.PKScript, }, } // create tx - msgTx, err := multisig.CreateBridgeTxSendBitcoin( + msgTx, err := multisig.CreateBridgeTxSendRune( &bridgeMsg, inputs, userMultisigWallet.PKScript, relayerPkScript, - TX_FEE, + TESTNET_TX_FEE, ) fmt.Println("err: ", err) // sign tx totalSigs := [][][]byte{} - // user key 1 sign tx - userSigs1, _ := multisig.SignTapMultisig(userPrivKeys[0], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs1) - // user key 2 sign tx - userSigs2, _ := multisig.SignTapMultisig(userPrivKeys[1], msgTx, inputs, userMultisigWallet, 0) - totalSigs = append(totalSigs, userSigs2) + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) + } // COMBINE SIGN signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) var signedTx bytes.Buffer signedMsgTx.Serialize(&signedTx) hexSignedTx := hex.EncodeToString(signedTx.Bytes()) - signedMsgTxID := signedMsgTx.TxHash().String() fmt.Println("hexSignedTx: ", hexSignedTx) - fmt.Println("signedMsgTxID: ", signedMsgTxID) - fmt.Println("err sign: ", err) - bridgeMessage, err := multisig.ReadBridgeMessage(signedMsgTx) - fmt.Println("bridgeMessage: ", bridgeMessage) + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.MempoolURL, []json.RawMessage{json.RawMessage(hexSignedTx)}) + fmt.Println("txHash: ", txHash) fmt.Println("err: ", err) - txSearchRes := &TxSearchRes{ - Tx: signedMsgTx, - Height: 3181075, - TxIndex: 21, - BridgeMessage: bridgeMessage, - } - relayerMessage, err := btcProvider.parseMessageFromTx(txSearchRes) - if err != nil { - fmt.Println("error: ", err) - } - inputs, msWallet, msgTx, relayerSigs, err := btcProvider.HandleBitcoinMessageTx(relayerMessage) - - if err != nil { - btcProvider.logger.Error("err combine tx: ", zap.Error(err)) - } - totalSigs = [][][]byte{relayerSigs} - // send unsigned raw tx and message sn to 2 slave relayers to get sign - // rsi := slaveRequestParams{ - // MsgSn: relayerMessage.Sn.String(), - // } +} - // slaveRequestData, _ := json.Marshal(rsi) - // slaveSigs := btcProvider.CallSlaves(slaveRequestData) +func TestDepositRuneToIconFailTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() + defer os.Remove(termpDir) + // relayer multisig + decodedAddr, _ := btcutil.DecodeAddress(TESTNET_RELAYER_ADDRESS, btcProvider.chainParam) + relayerPkScript, _ := txscript.PayToAddrScript(decodedAddr) + // user key + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletTestnet(btcProvider.chainParam) - // totalSigs = append(totalSigs, slaveSigs...) - // combine sigs - signedMsgTx, err = multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) + bridgeMsg := multisig.BridgeDecodedMsg{ + Message: &multisig.XCallMessage{ + MessageType: 1, + Action: "Deposit", + TokenAddress: "1:0", + To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + From: TESTNET_USER_WALLET_ADDRESS, + Amount: new(big.Int).SetUint64(1).Bytes(), + Data: []byte(""), + }, + ChainId: 1, + Receiver: TESTNET_ASSET_MANAGER_ADDRESS_WRONG, + Connectors: []string{ + TESTNET_CONNECTION_ADDRESS, + }, + } - if err != nil { - btcProvider.logger.Error("err combine tx: ", zap.Error(err)) + inputs := []*multisig.Input{ + // user rune UTXOs to spend + { + TxHash: "924c7c6bd13f465b0b50cb8ad883544b22bfe54fae42e2ecfc9f9609a1b616f7", + OutputIdx: 1, + OutputAmount: 546, + PkScript: userMultisigWallet.PKScript, + }, + // user bitcoin UTXOs to pay tx fee + { + TxHash: "b84060ce292dd61f8490bae54f8354caa8642de730e5f409b72d67b05617dcb0", + OutputIdx: 6, + OutputAmount: 226044, + PkScript: userMultisigWallet.PKScript, + }, } - btcProvider.logger.Info("signedMsgTx", zap.Any("transaction", signedMsgTx)) - var buf bytes.Buffer - err = signedMsgTx.Serialize(&buf) - if err != nil { - btcProvider.logger.Error("error", zap.Error(err)) + // create tx + msgTx, err := multisig.CreateBridgeTxSendRune( + &bridgeMsg, + inputs, + userMultisigWallet.PKScript, + relayerPkScript, + TESTNET_TX_FEE, + ) + fmt.Println("err: ", err) + // sign tx + totalSigs := [][][]byte{} + for _, privKey := range userPrivKeys { + // user key 1 sign tx + userSigs, _ := multisig.SignTapMultisig(privKey, msgTx, inputs, userMultisigWallet, 0) + totalSigs = append(totalSigs, userSigs) } + // COMBINE SIGN + signedMsgTx, _ := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, userMultisigWallet, 0) - txSize := len(buf.Bytes()) - btcProvider.logger.Info("--------------------txSize--------------------", zap.Int("size", txSize)) - signedMsgTxHex := hex.EncodeToString(buf.Bytes()) - btcProvider.logger.Info("signedMsgTxHex", zap.String("transaction_hex", signedMsgTxHex)) + var signedTx bytes.Buffer + signedMsgTx.Serialize(&signedTx) + hexSignedTx := hex.EncodeToString(signedTx.Bytes()) + fmt.Println("hexSignedTx: ", hexSignedTx) - txHash, err := btcProvider.client.SendRawTransactionV2(btcProvider.cfg.RPCUrl, signedMsgTxHex) + txHash, err := btcProvider.client.SendRawTransaction(btcProvider.cfg.RPCUrl, []json.RawMessage{json.RawMessage(`"` + hexSignedTx + `"`)}) fmt.Println("txHash: ", txHash) fmt.Println("err: ", err) } -func TestUint64ToBytes(t *testing.T) { - amount := uint64(15010) - bytesAmount := []byte(fmt.Sprintf("%d", amount)) - fmt.Println("bytesAmount: ", bytesAmount) - bigIntAmount := big.NewInt(0).SetBytes(bytesAmount) - fmt.Println("bigIntAmount: ", bigIntAmount.Uint64(), int64(bigIntAmount.Uint64())) +func TestBuildRelayerMultisigWalletTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() + defer os.Remove(termpDir) + msWallet, err := btcProvider.buildMultisigWallet() + fmt.Println("err: ", err) + fmt.Println("msWallet TapScriptTree: ", msWallet.TapScriptTree) + fmt.Println("msWallet TapLeaves: ", msWallet.TapLeaves) + fmt.Println("msWallet PKScript: ", hex.EncodeToString(msWallet.PKScript)) + fmt.Println("msWallet SharedPublicKey: ", msWallet.SharedPublicKey.ToECDSA()) + // log msWallet address + addr, err := multisig.AddressOnChain(btcProvider.chainParam, msWallet) + fmt.Println("msWallet Address: ", addr.String()) + fmt.Println("err: ", err) +} + +func TestBuildUserMultisigWalletTestnet(t *testing.T) { + btcProvider, termpDir := initBtcProviderTestnet() + defer os.Remove(termpDir) + userPrivKeys, userMultisigWallet, _ := buildUserMultisigWalletTestnet(btcProvider.chainParam) + fmt.Println("userPrivKeys: ", userPrivKeys) + fmt.Println("userMultisigWallet: ", userMultisigWallet) + addr, err := multisig.AddressOnChain(btcProvider.chainParam, userMultisigWallet) + fmt.Println("userMultisigWallet Address: ", addr.String()) + fmt.Println("err: ", err) } From d6314d28b3c7b731b4f0791d598fe935a1a8a3e2 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Sun, 17 Nov 2024 21:29:49 +0700 Subject: [PATCH 100/113] chore: clean code --- relayer/chains/bitcoin/helper.go | 8 +++++++ relayer/chains/bitcoin/master.go | 6 ----- relayer/chains/bitcoin/provider.go | 35 +++--------------------------- 3 files changed, 11 insertions(+), 38 deletions(-) diff --git a/relayer/chains/bitcoin/helper.go b/relayer/chains/bitcoin/helper.go index bb8f5bd8..9cd27382 100644 --- a/relayer/chains/bitcoin/helper.go +++ b/relayer/chains/bitcoin/helper.go @@ -43,3 +43,11 @@ func uint64ToBytes(amount uint64) []byte { binary.BigEndian.PutUint64(bytes, amount) return bytes } + +// Helper function to get minimum of two uint64 values +func min(a, b uint64) uint64 { + if a <= b { + return a + } + return b +} diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index 1dfd9476..b40456e6 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -20,11 +20,6 @@ func startMaster(c *Config) { } log.Printf("Master starting on port %s", port) - - // isProcess := os.Getenv("IS_PROCESS") - // if isProcess == "1" { - // callSlaves("test") - // } log.Fatal(server.ListenAndServe()) } @@ -60,7 +55,6 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { return } - // Process the message as needed fmt.Println("Received message: ", msg) // Send a response diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index b2bdb808..2730b991 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -36,8 +36,6 @@ import ( "go.uber.org/zap" ) -//var _ provider.ChainProvider = (*Provider)(nil) - var ( BTCToken = "0:0" MethodDeposit = "Deposit" @@ -245,8 +243,6 @@ func (p *Provider) QueryTransactionReceipt(ctx context.Context, txHash string) ( } return &relayTypes.Receipt{ TxHash: res.Txid, - // Height: uint64(res.TxResponse.Height), - // Status: types.CodeTypeOK == res.TxResponse.Code, }, nil } @@ -259,10 +255,6 @@ func (p *Provider) Name() string { } func (p *Provider) Init(ctx context.Context, homePath string, kms kms.KMS) error { - //if err := p.cfg.Contracts.Validate(); err != nil { - // return err - //} - //p.kms = kms return nil } @@ -380,7 +372,6 @@ func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired u break } if len(utxo.Runes) != 1 { - // return nil, fmt.Errorf("number of runes in the utxo is not 1, but: %v", err) continue } isSpent, _ := p.isSpentUTXO(utxo.TxId, utxo.Vout) @@ -650,8 +641,6 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 return inputs, nil } -// add tx fee the the required bitcoin amount - func (p *Provider) buildMultisigWallet() (*multisig.MultisigWallet, error) { masterPubKey, _ := hex.DecodeString(p.cfg.MasterPubKey) slave1PubKey, _ := hex.DecodeString(p.cfg.Slave1PubKey) @@ -907,7 +896,6 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms return inputs, msgTx, err } -// call the smart contract to send the message func (p *Provider) call(ctx context.Context, message *relayTypes.Message) (string, error) { return "", nil } @@ -919,7 +907,8 @@ func (p *Provider) sendTransaction(ctx context.Context, message *relayTypes.Mess return "", err } totalSigs := [][][]byte{relayerSigs} - // send unsigned raw tx and message sn to 2 slave relayers to get sign + + // send message sn and inputs to 2 slave relayers to get sign slaveInputs := []slaveRequestInput{} for _, input := range inputs { slaveInputs = append(slaveInputs, slaveRequestInput{ @@ -938,6 +927,7 @@ func (p *Provider) sendTransaction(ctx context.Context, message *relayTypes.Mess slaveSigs := p.CallSlaves(slaveRequestData, "") p.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) totalSigs = append(totalSigs, slaveSigs...) + // combine sigs signedMsgTx, err := multisig.CombineTapMultisig(totalSigs, msgTx, inputs, msWallet, 0) @@ -1018,7 +1008,6 @@ func (p *Provider) GenerateMessages(ctx context.Context, messageKey *relayTypes. } func (p *Provider) FinalityBlock(ctx context.Context) uint64 { - //return p.cfg.FinalityBlock return 0 } @@ -1052,8 +1041,6 @@ func (p *Provider) ClaimFee(ctx context.Context) error { return err } -// GetFee returns the fee for the given networkID -// responseFee is used to determine if the fee should be returned func (p *Provider) GetFee(ctx context.Context, networkID string, responseFee bool) (uint64, error) { return 0, nil } @@ -1108,14 +1095,6 @@ func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64 return heightChan } -// Helper function to get minimum of two uint64 values -func min(a, b uint64) uint64 { - if a <= b { - return a - } - return b -} - func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { var ( @@ -1174,16 +1153,11 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err } if messageInfo.Action == MethodDeposit && isValidConnector { - // maybe get this function name from cf file - // todo verify transfer amount match in calldata if it - // call 3rd to check rune amount tokenId := messageInfo.TokenAddress destContract := messageInfo.To p.logger.Info("tokenId", zap.String("tokenId", tokenId)) p.logger.Info("destContract", zap.String("destContract", destContract)) - // call api to verify the data - // https://docs.unisat.io/dev/unisat-developer-center/runes/get-utxo-runes-balance receiverAddresses = p.extractOutputReceiver(tx.Tx) _runeId, _runeAmount, _isMatchAmount, err := p.verifyBridgeTx(tx, messageInfo) if err != nil { @@ -1194,11 +1168,9 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err isMatchAmount = _isMatchAmount } - // TODO: call xcallformat and then replace to data sn := new(big.Int).SetUint64(tx.Height<<32 + tx.TxIndex) from := p.cfg.NID + "/" + p.cfg.Address - // Remove messageType from messageInfo before calling MarshalToBytes xCallMessage := XCallMessage{ Action: messageInfo.Action, @@ -1233,7 +1205,6 @@ func (p *Provider) parseMessageFromTx(tx *TxSearchRes) (*relayTypes.Message, err var senderAddress string // Find sender address to store in db - // todo: check if this is correct for _, address := range receiverAddresses { if address != p.cfg.Address { senderAddress = address From a6aa17724e6f836deed6d0774605fe684f3059b0 Mon Sep 17 00:00:00 2001 From: Shall Date: Mon, 18 Nov 2024 15:27:17 +0700 Subject: [PATCH 101/113] chore: update document --- docs/bitcoin-relayer.md | 131 +- relayer/chains/bitcoin/abi/bitcoin_state.go | 5177 ----------------- relayer/chains/bitcoin/abi/icall_service.go | 1814 ------ .../bitcoin/abi/icentralized_connection.go | 722 --- .../chains/bitcoin/abi/inonfungible_token.go | 2017 ------- relayer/chains/bitcoin/abi/iswap_router.go | 328 -- 6 files changed, 124 insertions(+), 10065 deletions(-) delete mode 100644 relayer/chains/bitcoin/abi/bitcoin_state.go delete mode 100644 relayer/chains/bitcoin/abi/icall_service.go delete mode 100644 relayer/chains/bitcoin/abi/icentralized_connection.go delete mode 100644 relayer/chains/bitcoin/abi/inonfungible_token.go delete mode 100644 relayer/chains/bitcoin/abi/iswap_router.go diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md index 1d3157d4..da906cf0 100644 --- a/docs/bitcoin-relayer.md +++ b/docs/bitcoin-relayer.md @@ -7,6 +7,8 @@ This is a relayer for Bitcoin that allows you to send or receive BTC/Rune from y - Understand the basics of Bitcoin transactions and Multisig taproot wallets - Understand about Bitcoin RPC and the related APIs (Unisat, Quicknode, etc.) +Note: At this implementation, We use 3rd party APIs such as Quicknode to crawl the Bitcoin transactions, and Unisat to get BTC/RUNE utxos or fee rate, so we need to prepare the API keys for these services. + ## Configuration config.yaml is the main configuration file for the Bitcoin relayer. It includes the following sections: @@ -21,11 +23,15 @@ bitcoin: address: # Bitcoin Taproot multisig address unisat-url: # Unisat API URL unisat-key: # Unisat API Key + unisat-wallet-url: # Unisat OPEN API URL (https://wallet-api.unisat.io for mainnet, https://wallet-api-testnet.unisat.io for testnet) + request-timeout: 1000 # Request Timeout (ms) network-id: # Bitcoin Network ID (1: Bitcoin Mainnet, 2: Bitcoin Testnet) op-code: # Bitcoin OP Code (0x5e: default) finality-block: # Bitcoin Finality Block (10: default) - nid: 0x2.btc # Bitcoin NID (0x1.btc: Bitcoin Mainnet, 0x2.btc: Bitcoin Testnet) + nid: 0x1.btc # Bitcoin NID (0x1.btc: Bitcoin Mainnet, 0x2.btc: Bitcoin Testnet) chain-name: bitcoin # Bitcoin Chain Name + recoveryLockTime: # Recovery Lock Time (recovery lock time of the master wallet) + start-height: # Start Height (start height) mode: master # master or slave slave-server-1: # Slave Server 1 URL (only used when mode is master) slave-server-2: # Slave Server 2 URL (only used when mode is master) @@ -35,8 +41,7 @@ bitcoin: slave1PubKey: # Slave 1 Public Key (public key of the slave wallet 1) slave2PubKey: # Slave 2 Public Key (public key of the slave wallet 2) relayerPrivKey: # Relayer Private Key (private key of the relayer it depends the deployed server that which start for master/slave1/slave2 server) - recoveryLockTime: # Recovery Lock Time (recovery lock time of the master wallet) - start-height: # Start Height (start height) + ``` # How it works @@ -57,7 +62,7 @@ The mechanism of the Bitcoin relayer is based on the master-slave architecture. ## Master Server -The master server will crawl Bitcoin transaction from the Bitcoin network and check if the transaction is a valid transaction with recipient is Relayer multigsig wallet address and the condition that contain value of OP_RETURN data is the same as the `op-code` (OP_RETURN OP_PUSHNUM_14) in the config.yaml file. +The master server will crawl Bitcoin transaction from the Bitcoin network and check if the transaction is a valid transaction with recipient is Relayer multigsig wallet address and the condition that contain value of OP_14 data is the same as the `op-code` in the config.yaml file. The master server is the main server that handles: - Requesting the slave servers to sign the transactions @@ -69,9 +74,9 @@ It works as the same with the master server, but the slave servers will not broa ## Data Structure -Based on the XCall message structure, The Bitcoin Relayer was designed and implemented to parse message with structure `OP_RETURN OP_PUSHNUM_14 YOUR _PAYLOAD`. +Based on the XCall message structure, The Bitcoin Relayer was designed and implemented to parse message with structure `OP_14 YOUR _PAYLOAD`. -Because OP_RETURN is only limited to 80 bytes by Bitcoin Core's default standardness rules, so the payload `(YOUR_PAYLOAD)` will be split into multiple parts with the maximum size of 76 bytes for each part and to grarentee . +Because we use leverage op code to send data so the limitation is 40 bytes by Bitcoin Core's default standardness rules, so the payload `(YOUR_PAYLOAD)` will be split into multiple utxos (output) with the maximum size of 40 bytes including a dust amount (547 sats) for each part. The Bitcoin Relayer will decode the message from the Bitcoin transaction and parse the payload to `BridgeDecodedMsg` data structure. @@ -117,4 +122,116 @@ bridgeMsg := BridgeDecodedMsg{ ### Deploy the Relayer -Since the Bitcoin relayer works based on the master-slave architecture, so we need to deploy seperate the master server and at least 2 slave servers, in totally there are 3 servers need to be run at the same time. +Since the Bitcoin relayer works based on the master-slave architecture, so we should deploy seperate the master server and at least 2 slave servers, in totally there are 3 servers need to be run at the same time for ideally, or deploy these servers in the same server for testing purpose. + +#### Master Server Configuration + +Here is some config difference between master and slave servers: + +```yaml +# ... config above +mode: master # master or slave +slave-server-1: # Slave Server 1 URL (only used when mode is master) +slave-server-2: # Slave Server 2 URL (only used when mode is master) +port: 8080 # Server Port (master server port) +api-key: key # Slave Server API Key (Using to authenticate between the master and slave servers) +masterPubKey: # Master Public Key (public key of the master wallet) +slave1PubKey: # Slave 1 Public Key (public key of the slave wallet 1) +slave2PubKey: # Slave 2 Public Key (public key of the slave wallet 2) +relayerPrivKey: # Relayer Private Key for master public key +``` + +#### Slave Server Configuration + +For slave, don't need to config `slave-server-1` and `slave-server-2` but `mode` will be `slave` + +```yaml +# ... config above +mode: slave +#slave-server-1 +#slave-server-2 +port: 8081 or 8082 # Slave Server Port, it depends the deployed server that which start for slave1/slave2 server +api-key: # Same with master server api-key (Using to authenticate between the master and slave servers) +relayerPrivKey: # Relayer Private Key for slave1 or slave2 public key, it depends the deployed server that which start for slave1/slave2 server +``` + +#### Start the Relayer + +```bash +RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start +``` + +### Implementation Details: + +- Deposit BTC/Runes from BTC to Icon +- Withdraw BTC/Runes from Icon to BTC +- Rollback BTC/Runes when deposit fail +- Refund BTC if the bridge message amount does not match the output to the relayer + +#### Testing Results: + +##### Deposit BTC Successfully + +- Bitcoin tx: https://mempool.space/tx/9a9d955dff45c6cef6f4e41a12052dde21179069a2e17fe8f381f6c75e112b6a +- Connection tx: + - https://tracker.icon.community/transaction/0x20f6364733a64882da22dcc06cc9086e0bbae6ec966197796aa53cdcfb419b26 +- Xcall execute: + - https://tracker.icon.community/transaction/0xc08aea4dde75f5624cf49dd00ba8ec8181f8d9c05db709a24d142e40f108c382 + +##### Deposit RUNE Successfully + +- Bitcoin tx: + - https://mempool.space/tx/924c7c6bd13f465b0b50cb8ad883544b22bfe54fae42e2ecfc9f9609a1b616f7 +- Connection tx: + - https://tracker.icon.community/transaction/0x72fba555202b3d0b45f70c6ba9ca9a00c162fd20d98e1c7fb93f6555ec7bd0ca +- Xcall execute: + - https://tracker.icon.community/transaction/0xc240279f1fdd590c18546777692c8821a3fdff795bd514bdd29fe67c3d540e7f + +##### Deposit BTC Failed + +- Bitcoin tx: + - https://mempool.space/tx/b84060ce292dd61f8490bae54f8354caa8642de730e5f409b72d67b05617dcb0 +- Connection tx: + - https://tracker.icon.community/transaction/0x09e3a5b9c8dcc3f3436eafcc6a01397e2353f81100aa79fdd4209deac5545b2b +- Xcall tx: + - https://tracker.icon.community/transaction/0x3f0ed85491f053177c7fb9e308d287137aa8bb97a17c1b5fee5f61ccd6eeaf25 +- Rollback tx: + - https://mempool.space/tx/da35fb5971ee045c35139a8c2a0388ec3a79f22045322a9ac76204728b0bb486 + +##### Deposit RUNE Failed + +- Bitcoin tx: + - https://mempool.space/tx/89095d016b50644a328667cd5543b0f29c0f2a81242094ea7318bded49cf30a8 +- Connection tx: + - https://tracker.icon.community/transaction/0x27a9f171531d828b3e57f2232cb19be01bbd4ab835511531a2936ea3ed63d3f7 +- Xcall tx: + - https://tracker.icon.community/transaction/0x74a447a1c06f4ebdbfe8ddb222a8e89c0ffddd1c098d9b484e2c7b6b05ce7d97 +- Rollback tx: + - https://mempool.space/address/bc1p2sdwgq7j32j250w8h47fe9v3hyc8fl2rdftwhxp0r7ww89mcwrns5reskh + +##### Deposit BTC with wrong amount, and got refund + +- Request tx: + - https://mempool.space/tx/50aa0c67d8a533d3766bd2076a2bc57bb67de7d61e9f503db271e915f0f75bae +- Refund tx: + - https://mempool.space/tx/6a976c2d6651020cce3c13f464128b19e7c318d825dda0d47a14025d94179c0a + +##### Withdraw BTC Successfully + +- Icon tx: + - https://tracker.icon.community/transaction/0x3854443002829635830e679c83d41303ace0093a78320846aa6f543835ecf751 +- Bitcoin tx: + - https://mempool.space/tx/cf671e0ecc434e2cb06152bae30d35114d7fef8c1c3ec7ae60aea45691edf75b + +##### Withdraw RUNE Successfully + +- Icon tx: + - https://tracker.icon.community/transaction/0x2fbb0aca1b99692b24baae68c2b451945db9eb829f09996eac01b5799bf35fc1 +- Bitcoin tx: + - https://mempool.space/tx/21f8ba718ba003e38ef291c1f8a6de7706fb49b2addfbb3eadf4bf1808d83a17 + +### Known Issues + +- With a tx send to the relayer multisig wallet, if the BTC amount of btc does not match with the BTC amount defined in the xcall message, and the relayer will refund the amount to the sender but minus the fee. +- To stress test the system, you need to prepare a lot of BTC/RUNE utxos for the relayer multisig wallet, to make sure the system has enough utxos to process the transactions and avoid the issue of insufficient utxos. +- In case Rollback transaction, the relayer will refund the same amount of BTC/RUNE that the user sent to the relayer multisig wallet. diff --git a/relayer/chains/bitcoin/abi/bitcoin_state.go b/relayer/chains/bitcoin/abi/bitcoin_state.go deleted file mode 100644 index 45792178..00000000 --- a/relayer/chains/bitcoin/abi/bitcoin_state.go +++ /dev/null @@ -1,5177 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package abi - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "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/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// IBitcoinStateTokenInfo is an auto generated low-level Go binding around an user-defined struct. -type IBitcoinStateTokenInfo struct { - Name string - Symbol string -} - -// StdInvariantFuzzArtifactSelector is an auto generated low-level Go binding around an user-defined struct. -type StdInvariantFuzzArtifactSelector struct { - Artifact string - Selectors [][4]byte -} - -// StdInvariantFuzzInterface is an auto generated low-level Go binding around an user-defined struct. -type StdInvariantFuzzInterface struct { - Addr common.Address - Artifacts []string -} - -// StdInvariantFuzzSelector is an auto generated low-level Go binding around an user-defined struct. -type StdInvariantFuzzSelector struct { - Addr common.Address - Selectors [][4]byte -} - -// BitcoinStateMetaData contains all meta data concerning the BitcoinState contract. -var BitcoinStateMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"IS_TEST\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"_PERMIT_TYPEHASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"accountBalances\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"addConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"bitcoinNid\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimTokens\",\"inputs\":[{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"computeTokenAddress\",\"inputs\":[{\"name\":\"tokenName\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"connections\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"connectionsEndpoints\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeArtifacts\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedArtifacts_\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeContracts\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedContracts_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeSelectors\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedSelectors_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzSelector[]\",\"components\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"selectors\",\"type\":\"bytes4[]\",\"internalType\":\"bytes4[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"excludeSenders\",\"inputs\":[],\"outputs\":[{\"name\":\"excludedSenders_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"failed\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getSignData\",\"inputs\":[{\"name\":\"requester_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"data_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleCallMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_protocols\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initPool\",\"inputs\":[{\"name\":\"data_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"xcall_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"uinswapV3Router_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"nonfungiblePositionManager_\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"connections\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"migrate\",\"inputs\":[{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"migrateComplete\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"nftOwners\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"nonFungibleManager\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"owner\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"params\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"tuple\",\"internalType\":\"structIBitcoinState.TokenInfo\",\"components\":[{\"name\":\"name\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"symbol\",\"type\":\"string\",\"internalType\":\"string\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"removeConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"removeLiquidity\",\"inputs\":[{\"name\":\"data_\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"renounceOwnership\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"routerV2\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetArtifactSelectors\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedArtifactSelectors_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzArtifactSelector[]\",\"components\":[{\"name\":\"artifact\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"selectors\",\"type\":\"bytes4[]\",\"internalType\":\"bytes4[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetArtifacts\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedArtifacts_\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetContracts\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedContracts_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetInterfaces\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedInterfaces_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzInterface[]\",\"components\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"artifacts\",\"type\":\"string[]\",\"internalType\":\"string[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetSelectors\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedSelectors_\",\"type\":\"tuple[]\",\"internalType\":\"structStdInvariant.FuzzSelector[]\",\"components\":[{\"name\":\"addr\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"selectors\",\"type\":\"bytes4[]\",\"internalType\":\"bytes4[]\"}]}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"targetSenders\",\"inputs\":[],\"outputs\":[{\"name\":\"targetedSenders_\",\"type\":\"address[]\",\"internalType\":\"address[]\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokens\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferOwnership\",\"inputs\":[{\"name\":\"newOwner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"xcallService\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"AddConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"AddSelector\",\"inputs\":[{\"name\":\"selector_\",\"type\":\"bytes4\",\"indexed\":false,\"internalType\":\"bytes4\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint8\",\"indexed\":false,\"internalType\":\"uint8\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"OwnershipTransferred\",\"inputs\":[{\"name\":\"previousOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"newOwner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemoveConnection\",\"inputs\":[{\"name\":\"connection_\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RemoveSelector\",\"inputs\":[{\"name\":\"selector_\",\"type\":\"bytes4\",\"indexed\":false,\"internalType\":\"bytes4\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RequestExecuted\",\"inputs\":[{\"name\":\"id\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"stateRoot\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"},{\"name\":\"data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log\",\"inputs\":[{\"name\":\"\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_address\",\"inputs\":[{\"name\":\"\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_array\",\"inputs\":[{\"name\":\"val\",\"type\":\"uint256[]\",\"indexed\":false,\"internalType\":\"uint256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_array\",\"inputs\":[{\"name\":\"val\",\"type\":\"int256[]\",\"indexed\":false,\"internalType\":\"int256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_array\",\"inputs\":[{\"name\":\"val\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_bytes\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_bytes32\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_int\",\"inputs\":[{\"name\":\"\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_address\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_array\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"uint256[]\",\"indexed\":false,\"internalType\":\"uint256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_array\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"int256[]\",\"indexed\":false,\"internalType\":\"int256[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_array\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"address[]\",\"indexed\":false,\"internalType\":\"address[]\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_bytes\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_bytes32\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"bytes32\",\"indexed\":false,\"internalType\":\"bytes32\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_decimal_int\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"},{\"name\":\"decimals\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_decimal_uint\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"decimals\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_int\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_string\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_named_uint\",\"inputs\":[{\"name\":\"key\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"val\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_string\",\"inputs\":[{\"name\":\"\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"log_uint\",\"inputs\":[{\"name\":\"\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"logs\",\"inputs\":[{\"name\":\"\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false}]", -} - -// BitcoinStateABI is the input ABI used to generate the binding from. -// Deprecated: Use BitcoinStateMetaData.ABI instead. -var BitcoinStateABI = BitcoinStateMetaData.ABI - -// BitcoinState is an auto generated Go binding around an Ethereum contract. -type BitcoinState struct { - BitcoinStateCaller // Read-only binding to the contract - BitcoinStateTransactor // Write-only binding to the contract - BitcoinStateFilterer // Log filterer for contract events -} - -// BitcoinStateCaller is an auto generated read-only Go binding around an Ethereum contract. -type BitcoinStateCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// BitcoinStateTransactor is an auto generated write-only Go binding around an Ethereum contract. -type BitcoinStateTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// BitcoinStateFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type BitcoinStateFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// BitcoinStateSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type BitcoinStateSession struct { - Contract *BitcoinState // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// BitcoinStateCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type BitcoinStateCallerSession struct { - Contract *BitcoinStateCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// BitcoinStateTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type BitcoinStateTransactorSession struct { - Contract *BitcoinStateTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// BitcoinStateRaw is an auto generated low-level Go binding around an Ethereum contract. -type BitcoinStateRaw struct { - Contract *BitcoinState // Generic contract binding to access the raw methods on -} - -// BitcoinStateCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type BitcoinStateCallerRaw struct { - Contract *BitcoinStateCaller // Generic read-only contract binding to access the raw methods on -} - -// BitcoinStateTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type BitcoinStateTransactorRaw struct { - Contract *BitcoinStateTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewBitcoinState creates a new instance of BitcoinState, bound to a specific deployed contract. -func NewBitcoinState(address common.Address, backend bind.ContractBackend) (*BitcoinState, error) { - contract, err := bindBitcoinState(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &BitcoinState{BitcoinStateCaller: BitcoinStateCaller{contract: contract}, BitcoinStateTransactor: BitcoinStateTransactor{contract: contract}, BitcoinStateFilterer: BitcoinStateFilterer{contract: contract}}, nil -} - -// NewBitcoinStateCaller creates a new read-only instance of BitcoinState, bound to a specific deployed contract. -func NewBitcoinStateCaller(address common.Address, caller bind.ContractCaller) (*BitcoinStateCaller, error) { - contract, err := bindBitcoinState(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &BitcoinStateCaller{contract: contract}, nil -} - -// NewBitcoinStateTransactor creates a new write-only instance of BitcoinState, bound to a specific deployed contract. -func NewBitcoinStateTransactor(address common.Address, transactor bind.ContractTransactor) (*BitcoinStateTransactor, error) { - contract, err := bindBitcoinState(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &BitcoinStateTransactor{contract: contract}, nil -} - -// NewBitcoinStateFilterer creates a new log filterer instance of BitcoinState, bound to a specific deployed contract. -func NewBitcoinStateFilterer(address common.Address, filterer bind.ContractFilterer) (*BitcoinStateFilterer, error) { - contract, err := bindBitcoinState(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &BitcoinStateFilterer{contract: contract}, nil -} - -// bindBitcoinState binds a generic wrapper to an already deployed contract. -func bindBitcoinState(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := BitcoinStateMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_BitcoinState *BitcoinStateRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _BitcoinState.Contract.BitcoinStateCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_BitcoinState *BitcoinStateRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BitcoinState.Contract.BitcoinStateTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_BitcoinState *BitcoinStateRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _BitcoinState.Contract.BitcoinStateTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_BitcoinState *BitcoinStateCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _BitcoinState.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_BitcoinState *BitcoinStateTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BitcoinState.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_BitcoinState *BitcoinStateTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _BitcoinState.Contract.contract.Transact(opts, method, params...) -} - -// ISTEST is a free data retrieval call binding the contract method 0xfa7626d4. -// -// Solidity: function IS_TEST() view returns(bool) -func (_BitcoinState *BitcoinStateCaller) ISTEST(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "IS_TEST") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// ISTEST is a free data retrieval call binding the contract method 0xfa7626d4. -// -// Solidity: function IS_TEST() view returns(bool) -func (_BitcoinState *BitcoinStateSession) ISTEST() (bool, error) { - return _BitcoinState.Contract.ISTEST(&_BitcoinState.CallOpts) -} - -// ISTEST is a free data retrieval call binding the contract method 0xfa7626d4. -// -// Solidity: function IS_TEST() view returns(bool) -func (_BitcoinState *BitcoinStateCallerSession) ISTEST() (bool, error) { - return _BitcoinState.Contract.ISTEST(&_BitcoinState.CallOpts) -} - -// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x982aaf6b. -// -// Solidity: function _PERMIT_TYPEHASH() view returns(bytes32) -func (_BitcoinState *BitcoinStateCaller) PERMITTYPEHASH(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "_PERMIT_TYPEHASH") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x982aaf6b. -// -// Solidity: function _PERMIT_TYPEHASH() view returns(bytes32) -func (_BitcoinState *BitcoinStateSession) PERMITTYPEHASH() ([32]byte, error) { - return _BitcoinState.Contract.PERMITTYPEHASH(&_BitcoinState.CallOpts) -} - -// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x982aaf6b. -// -// Solidity: function _PERMIT_TYPEHASH() view returns(bytes32) -func (_BitcoinState *BitcoinStateCallerSession) PERMITTYPEHASH() ([32]byte, error) { - return _BitcoinState.Contract.PERMITTYPEHASH(&_BitcoinState.CallOpts) -} - -// AccountBalances is a free data retrieval call binding the contract method 0x1242e5fd. -// -// Solidity: function accountBalances(address , address ) view returns(uint256) -func (_BitcoinState *BitcoinStateCaller) AccountBalances(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "accountBalances", arg0, arg1) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// AccountBalances is a free data retrieval call binding the contract method 0x1242e5fd. -// -// Solidity: function accountBalances(address , address ) view returns(uint256) -func (_BitcoinState *BitcoinStateSession) AccountBalances(arg0 common.Address, arg1 common.Address) (*big.Int, error) { - return _BitcoinState.Contract.AccountBalances(&_BitcoinState.CallOpts, arg0, arg1) -} - -// AccountBalances is a free data retrieval call binding the contract method 0x1242e5fd. -// -// Solidity: function accountBalances(address , address ) view returns(uint256) -func (_BitcoinState *BitcoinStateCallerSession) AccountBalances(arg0 common.Address, arg1 common.Address) (*big.Int, error) { - return _BitcoinState.Contract.AccountBalances(&_BitcoinState.CallOpts, arg0, arg1) -} - -// BitcoinNid is a free data retrieval call binding the contract method 0xf3cc4515. -// -// Solidity: function bitcoinNid() view returns(string) -func (_BitcoinState *BitcoinStateCaller) BitcoinNid(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "bitcoinNid") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// BitcoinNid is a free data retrieval call binding the contract method 0xf3cc4515. -// -// Solidity: function bitcoinNid() view returns(string) -func (_BitcoinState *BitcoinStateSession) BitcoinNid() (string, error) { - return _BitcoinState.Contract.BitcoinNid(&_BitcoinState.CallOpts) -} - -// BitcoinNid is a free data retrieval call binding the contract method 0xf3cc4515. -// -// Solidity: function bitcoinNid() view returns(string) -func (_BitcoinState *BitcoinStateCallerSession) BitcoinNid() (string, error) { - return _BitcoinState.Contract.BitcoinNid(&_BitcoinState.CallOpts) -} - -// ClaimTokens is a free data retrieval call binding the contract method 0x69ffa08a. -// -// Solidity: function claimTokens(address token0, address token1) pure returns() -func (_BitcoinState *BitcoinStateCaller) ClaimTokens(opts *bind.CallOpts, token0 common.Address, token1 common.Address) error { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "claimTokens", token0, token1) - - if err != nil { - return err - } - - return err - -} - -// ClaimTokens is a free data retrieval call binding the contract method 0x69ffa08a. -// -// Solidity: function claimTokens(address token0, address token1) pure returns() -func (_BitcoinState *BitcoinStateSession) ClaimTokens(token0 common.Address, token1 common.Address) error { - return _BitcoinState.Contract.ClaimTokens(&_BitcoinState.CallOpts, token0, token1) -} - -// ClaimTokens is a free data retrieval call binding the contract method 0x69ffa08a. -// -// Solidity: function claimTokens(address token0, address token1) pure returns() -func (_BitcoinState *BitcoinStateCallerSession) ClaimTokens(token0 common.Address, token1 common.Address) error { - return _BitcoinState.Contract.ClaimTokens(&_BitcoinState.CallOpts, token0, token1) -} - -// ComputeTokenAddress is a free data retrieval call binding the contract method 0x4aa6af7b. -// -// Solidity: function computeTokenAddress(string tokenName) view returns(address) -func (_BitcoinState *BitcoinStateCaller) ComputeTokenAddress(opts *bind.CallOpts, tokenName string) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "computeTokenAddress", tokenName) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// ComputeTokenAddress is a free data retrieval call binding the contract method 0x4aa6af7b. -// -// Solidity: function computeTokenAddress(string tokenName) view returns(address) -func (_BitcoinState *BitcoinStateSession) ComputeTokenAddress(tokenName string) (common.Address, error) { - return _BitcoinState.Contract.ComputeTokenAddress(&_BitcoinState.CallOpts, tokenName) -} - -// ComputeTokenAddress is a free data retrieval call binding the contract method 0x4aa6af7b. -// -// Solidity: function computeTokenAddress(string tokenName) view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) ComputeTokenAddress(tokenName string) (common.Address, error) { - return _BitcoinState.Contract.ComputeTokenAddress(&_BitcoinState.CallOpts, tokenName) -} - -// Connections is a free data retrieval call binding the contract method 0xc0896578. -// -// Solidity: function connections(address ) view returns(bool) -func (_BitcoinState *BitcoinStateCaller) Connections(opts *bind.CallOpts, arg0 common.Address) (bool, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "connections", arg0) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// Connections is a free data retrieval call binding the contract method 0xc0896578. -// -// Solidity: function connections(address ) view returns(bool) -func (_BitcoinState *BitcoinStateSession) Connections(arg0 common.Address) (bool, error) { - return _BitcoinState.Contract.Connections(&_BitcoinState.CallOpts, arg0) -} - -// Connections is a free data retrieval call binding the contract method 0xc0896578. -// -// Solidity: function connections(address ) view returns(bool) -func (_BitcoinState *BitcoinStateCallerSession) Connections(arg0 common.Address) (bool, error) { - return _BitcoinState.Contract.Connections(&_BitcoinState.CallOpts, arg0) -} - -// ConnectionsEndpoints is a free data retrieval call binding the contract method 0xb687db2e. -// -// Solidity: function connectionsEndpoints(uint256 ) view returns(address) -func (_BitcoinState *BitcoinStateCaller) ConnectionsEndpoints(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "connectionsEndpoints", arg0) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// ConnectionsEndpoints is a free data retrieval call binding the contract method 0xb687db2e. -// -// Solidity: function connectionsEndpoints(uint256 ) view returns(address) -func (_BitcoinState *BitcoinStateSession) ConnectionsEndpoints(arg0 *big.Int) (common.Address, error) { - return _BitcoinState.Contract.ConnectionsEndpoints(&_BitcoinState.CallOpts, arg0) -} - -// ConnectionsEndpoints is a free data retrieval call binding the contract method 0xb687db2e. -// -// Solidity: function connectionsEndpoints(uint256 ) view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) ConnectionsEndpoints(arg0 *big.Int) (common.Address, error) { - return _BitcoinState.Contract.ConnectionsEndpoints(&_BitcoinState.CallOpts, arg0) -} - -// ExcludeArtifacts is a free data retrieval call binding the contract method 0xb5508aa9. -// -// Solidity: function excludeArtifacts() view returns(string[] excludedArtifacts_) -func (_BitcoinState *BitcoinStateCaller) ExcludeArtifacts(opts *bind.CallOpts) ([]string, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "excludeArtifacts") - - if err != nil { - return *new([]string), err - } - - out0 := *abi.ConvertType(out[0], new([]string)).(*[]string) - - return out0, err - -} - -// ExcludeArtifacts is a free data retrieval call binding the contract method 0xb5508aa9. -// -// Solidity: function excludeArtifacts() view returns(string[] excludedArtifacts_) -func (_BitcoinState *BitcoinStateSession) ExcludeArtifacts() ([]string, error) { - return _BitcoinState.Contract.ExcludeArtifacts(&_BitcoinState.CallOpts) -} - -// ExcludeArtifacts is a free data retrieval call binding the contract method 0xb5508aa9. -// -// Solidity: function excludeArtifacts() view returns(string[] excludedArtifacts_) -func (_BitcoinState *BitcoinStateCallerSession) ExcludeArtifacts() ([]string, error) { - return _BitcoinState.Contract.ExcludeArtifacts(&_BitcoinState.CallOpts) -} - -// ExcludeContracts is a free data retrieval call binding the contract method 0xe20c9f71. -// -// Solidity: function excludeContracts() view returns(address[] excludedContracts_) -func (_BitcoinState *BitcoinStateCaller) ExcludeContracts(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "excludeContracts") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -// ExcludeContracts is a free data retrieval call binding the contract method 0xe20c9f71. -// -// Solidity: function excludeContracts() view returns(address[] excludedContracts_) -func (_BitcoinState *BitcoinStateSession) ExcludeContracts() ([]common.Address, error) { - return _BitcoinState.Contract.ExcludeContracts(&_BitcoinState.CallOpts) -} - -// ExcludeContracts is a free data retrieval call binding the contract method 0xe20c9f71. -// -// Solidity: function excludeContracts() view returns(address[] excludedContracts_) -func (_BitcoinState *BitcoinStateCallerSession) ExcludeContracts() ([]common.Address, error) { - return _BitcoinState.Contract.ExcludeContracts(&_BitcoinState.CallOpts) -} - -// ExcludeSelectors is a free data retrieval call binding the contract method 0xb0464fdc. -// -// Solidity: function excludeSelectors() view returns((address,bytes4[])[] excludedSelectors_) -func (_BitcoinState *BitcoinStateCaller) ExcludeSelectors(opts *bind.CallOpts) ([]StdInvariantFuzzSelector, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "excludeSelectors") - - if err != nil { - return *new([]StdInvariantFuzzSelector), err - } - - out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzSelector)).(*[]StdInvariantFuzzSelector) - - return out0, err - -} - -// ExcludeSelectors is a free data retrieval call binding the contract method 0xb0464fdc. -// -// Solidity: function excludeSelectors() view returns((address,bytes4[])[] excludedSelectors_) -func (_BitcoinState *BitcoinStateSession) ExcludeSelectors() ([]StdInvariantFuzzSelector, error) { - return _BitcoinState.Contract.ExcludeSelectors(&_BitcoinState.CallOpts) -} - -// ExcludeSelectors is a free data retrieval call binding the contract method 0xb0464fdc. -// -// Solidity: function excludeSelectors() view returns((address,bytes4[])[] excludedSelectors_) -func (_BitcoinState *BitcoinStateCallerSession) ExcludeSelectors() ([]StdInvariantFuzzSelector, error) { - return _BitcoinState.Contract.ExcludeSelectors(&_BitcoinState.CallOpts) -} - -// ExcludeSenders is a free data retrieval call binding the contract method 0x1ed7831c. -// -// Solidity: function excludeSenders() view returns(address[] excludedSenders_) -func (_BitcoinState *BitcoinStateCaller) ExcludeSenders(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "excludeSenders") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -// ExcludeSenders is a free data retrieval call binding the contract method 0x1ed7831c. -// -// Solidity: function excludeSenders() view returns(address[] excludedSenders_) -func (_BitcoinState *BitcoinStateSession) ExcludeSenders() ([]common.Address, error) { - return _BitcoinState.Contract.ExcludeSenders(&_BitcoinState.CallOpts) -} - -// ExcludeSenders is a free data retrieval call binding the contract method 0x1ed7831c. -// -// Solidity: function excludeSenders() view returns(address[] excludedSenders_) -func (_BitcoinState *BitcoinStateCallerSession) ExcludeSenders() ([]common.Address, error) { - return _BitcoinState.Contract.ExcludeSenders(&_BitcoinState.CallOpts) -} - -// Failed is a free data retrieval call binding the contract method 0xba414fa6. -// -// Solidity: function failed() view returns(bool) -func (_BitcoinState *BitcoinStateCaller) Failed(opts *bind.CallOpts) (bool, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "failed") - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// Failed is a free data retrieval call binding the contract method 0xba414fa6. -// -// Solidity: function failed() view returns(bool) -func (_BitcoinState *BitcoinStateSession) Failed() (bool, error) { - return _BitcoinState.Contract.Failed(&_BitcoinState.CallOpts) -} - -// Failed is a free data retrieval call binding the contract method 0xba414fa6. -// -// Solidity: function failed() view returns(bool) -func (_BitcoinState *BitcoinStateCallerSession) Failed() (bool, error) { - return _BitcoinState.Contract.Failed(&_BitcoinState.CallOpts) -} - -// InitPool is a free data retrieval call binding the contract method 0xca38b326. -// -// Solidity: function initPool(bytes data_) pure returns() -func (_BitcoinState *BitcoinStateCaller) InitPool(opts *bind.CallOpts, data_ []byte) error { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "initPool", data_) - - if err != nil { - return err - } - - return err - -} - -// InitPool is a free data retrieval call binding the contract method 0xca38b326. -// -// Solidity: function initPool(bytes data_) pure returns() -func (_BitcoinState *BitcoinStateSession) InitPool(data_ []byte) error { - return _BitcoinState.Contract.InitPool(&_BitcoinState.CallOpts, data_) -} - -// InitPool is a free data retrieval call binding the contract method 0xca38b326. -// -// Solidity: function initPool(bytes data_) pure returns() -func (_BitcoinState *BitcoinStateCallerSession) InitPool(data_ []byte) error { - return _BitcoinState.Contract.InitPool(&_BitcoinState.CallOpts, data_) -} - -// NftOwners is a free data retrieval call binding the contract method 0xbbd94c2f. -// -// Solidity: function nftOwners(uint256 ) view returns(address) -func (_BitcoinState *BitcoinStateCaller) NftOwners(opts *bind.CallOpts, arg0 *big.Int) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "nftOwners", arg0) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// NftOwners is a free data retrieval call binding the contract method 0xbbd94c2f. -// -// Solidity: function nftOwners(uint256 ) view returns(address) -func (_BitcoinState *BitcoinStateSession) NftOwners(arg0 *big.Int) (common.Address, error) { - return _BitcoinState.Contract.NftOwners(&_BitcoinState.CallOpts, arg0) -} - -// NftOwners is a free data retrieval call binding the contract method 0xbbd94c2f. -// -// Solidity: function nftOwners(uint256 ) view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) NftOwners(arg0 *big.Int) (common.Address, error) { - return _BitcoinState.Contract.NftOwners(&_BitcoinState.CallOpts, arg0) -} - -// NonFungibleManager is a free data retrieval call binding the contract method 0xecc28165. -// -// Solidity: function nonFungibleManager() view returns(address) -func (_BitcoinState *BitcoinStateCaller) NonFungibleManager(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "nonFungibleManager") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// NonFungibleManager is a free data retrieval call binding the contract method 0xecc28165. -// -// Solidity: function nonFungibleManager() view returns(address) -func (_BitcoinState *BitcoinStateSession) NonFungibleManager() (common.Address, error) { - return _BitcoinState.Contract.NonFungibleManager(&_BitcoinState.CallOpts) -} - -// NonFungibleManager is a free data retrieval call binding the contract method 0xecc28165. -// -// Solidity: function nonFungibleManager() view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) NonFungibleManager() (common.Address, error) { - return _BitcoinState.Contract.NonFungibleManager(&_BitcoinState.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_BitcoinState *BitcoinStateCaller) Owner(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "owner") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_BitcoinState *BitcoinStateSession) Owner() (common.Address, error) { - return _BitcoinState.Contract.Owner(&_BitcoinState.CallOpts) -} - -// Owner is a free data retrieval call binding the contract method 0x8da5cb5b. -// -// Solidity: function owner() view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) Owner() (common.Address, error) { - return _BitcoinState.Contract.Owner(&_BitcoinState.CallOpts) -} - -// Params is a free data retrieval call binding the contract method 0xcff0ab96. -// -// Solidity: function params() view returns((string,string)) -func (_BitcoinState *BitcoinStateCaller) Params(opts *bind.CallOpts) (IBitcoinStateTokenInfo, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "params") - - if err != nil { - return *new(IBitcoinStateTokenInfo), err - } - - out0 := *abi.ConvertType(out[0], new(IBitcoinStateTokenInfo)).(*IBitcoinStateTokenInfo) - - return out0, err - -} - -// Params is a free data retrieval call binding the contract method 0xcff0ab96. -// -// Solidity: function params() view returns((string,string)) -func (_BitcoinState *BitcoinStateSession) Params() (IBitcoinStateTokenInfo, error) { - return _BitcoinState.Contract.Params(&_BitcoinState.CallOpts) -} - -// Params is a free data retrieval call binding the contract method 0xcff0ab96. -// -// Solidity: function params() view returns((string,string)) -func (_BitcoinState *BitcoinStateCallerSession) Params() (IBitcoinStateTokenInfo, error) { - return _BitcoinState.Contract.Params(&_BitcoinState.CallOpts) -} - -// RemoveLiquidity is a free data retrieval call binding the contract method 0x028318cf. -// -// Solidity: function removeLiquidity(bytes data_) pure returns() -func (_BitcoinState *BitcoinStateCaller) RemoveLiquidity(opts *bind.CallOpts, data_ []byte) error { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "removeLiquidity", data_) - - if err != nil { - return err - } - - return err - -} - -// RemoveLiquidity is a free data retrieval call binding the contract method 0x028318cf. -// -// Solidity: function removeLiquidity(bytes data_) pure returns() -func (_BitcoinState *BitcoinStateSession) RemoveLiquidity(data_ []byte) error { - return _BitcoinState.Contract.RemoveLiquidity(&_BitcoinState.CallOpts, data_) -} - -// RemoveLiquidity is a free data retrieval call binding the contract method 0x028318cf. -// -// Solidity: function removeLiquidity(bytes data_) pure returns() -func (_BitcoinState *BitcoinStateCallerSession) RemoveLiquidity(data_ []byte) error { - return _BitcoinState.Contract.RemoveLiquidity(&_BitcoinState.CallOpts, data_) -} - -// RouterV2 is a free data retrieval call binding the contract method 0x502f7446. -// -// Solidity: function routerV2() view returns(address) -func (_BitcoinState *BitcoinStateCaller) RouterV2(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "routerV2") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// RouterV2 is a free data retrieval call binding the contract method 0x502f7446. -// -// Solidity: function routerV2() view returns(address) -func (_BitcoinState *BitcoinStateSession) RouterV2() (common.Address, error) { - return _BitcoinState.Contract.RouterV2(&_BitcoinState.CallOpts) -} - -// RouterV2 is a free data retrieval call binding the contract method 0x502f7446. -// -// Solidity: function routerV2() view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) RouterV2() (common.Address, error) { - return _BitcoinState.Contract.RouterV2(&_BitcoinState.CallOpts) -} - -// TargetArtifactSelectors is a free data retrieval call binding the contract method 0x66d9a9a0. -// -// Solidity: function targetArtifactSelectors() view returns((string,bytes4[])[] targetedArtifactSelectors_) -func (_BitcoinState *BitcoinStateCaller) TargetArtifactSelectors(opts *bind.CallOpts) ([]StdInvariantFuzzArtifactSelector, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "targetArtifactSelectors") - - if err != nil { - return *new([]StdInvariantFuzzArtifactSelector), err - } - - out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzArtifactSelector)).(*[]StdInvariantFuzzArtifactSelector) - - return out0, err - -} - -// TargetArtifactSelectors is a free data retrieval call binding the contract method 0x66d9a9a0. -// -// Solidity: function targetArtifactSelectors() view returns((string,bytes4[])[] targetedArtifactSelectors_) -func (_BitcoinState *BitcoinStateSession) TargetArtifactSelectors() ([]StdInvariantFuzzArtifactSelector, error) { - return _BitcoinState.Contract.TargetArtifactSelectors(&_BitcoinState.CallOpts) -} - -// TargetArtifactSelectors is a free data retrieval call binding the contract method 0x66d9a9a0. -// -// Solidity: function targetArtifactSelectors() view returns((string,bytes4[])[] targetedArtifactSelectors_) -func (_BitcoinState *BitcoinStateCallerSession) TargetArtifactSelectors() ([]StdInvariantFuzzArtifactSelector, error) { - return _BitcoinState.Contract.TargetArtifactSelectors(&_BitcoinState.CallOpts) -} - -// TargetArtifacts is a free data retrieval call binding the contract method 0x85226c81. -// -// Solidity: function targetArtifacts() view returns(string[] targetedArtifacts_) -func (_BitcoinState *BitcoinStateCaller) TargetArtifacts(opts *bind.CallOpts) ([]string, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "targetArtifacts") - - if err != nil { - return *new([]string), err - } - - out0 := *abi.ConvertType(out[0], new([]string)).(*[]string) - - return out0, err - -} - -// TargetArtifacts is a free data retrieval call binding the contract method 0x85226c81. -// -// Solidity: function targetArtifacts() view returns(string[] targetedArtifacts_) -func (_BitcoinState *BitcoinStateSession) TargetArtifacts() ([]string, error) { - return _BitcoinState.Contract.TargetArtifacts(&_BitcoinState.CallOpts) -} - -// TargetArtifacts is a free data retrieval call binding the contract method 0x85226c81. -// -// Solidity: function targetArtifacts() view returns(string[] targetedArtifacts_) -func (_BitcoinState *BitcoinStateCallerSession) TargetArtifacts() ([]string, error) { - return _BitcoinState.Contract.TargetArtifacts(&_BitcoinState.CallOpts) -} - -// TargetContracts is a free data retrieval call binding the contract method 0x3f7286f4. -// -// Solidity: function targetContracts() view returns(address[] targetedContracts_) -func (_BitcoinState *BitcoinStateCaller) TargetContracts(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "targetContracts") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -// TargetContracts is a free data retrieval call binding the contract method 0x3f7286f4. -// -// Solidity: function targetContracts() view returns(address[] targetedContracts_) -func (_BitcoinState *BitcoinStateSession) TargetContracts() ([]common.Address, error) { - return _BitcoinState.Contract.TargetContracts(&_BitcoinState.CallOpts) -} - -// TargetContracts is a free data retrieval call binding the contract method 0x3f7286f4. -// -// Solidity: function targetContracts() view returns(address[] targetedContracts_) -func (_BitcoinState *BitcoinStateCallerSession) TargetContracts() ([]common.Address, error) { - return _BitcoinState.Contract.TargetContracts(&_BitcoinState.CallOpts) -} - -// TargetInterfaces is a free data retrieval call binding the contract method 0x2ade3880. -// -// Solidity: function targetInterfaces() view returns((address,string[])[] targetedInterfaces_) -func (_BitcoinState *BitcoinStateCaller) TargetInterfaces(opts *bind.CallOpts) ([]StdInvariantFuzzInterface, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "targetInterfaces") - - if err != nil { - return *new([]StdInvariantFuzzInterface), err - } - - out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzInterface)).(*[]StdInvariantFuzzInterface) - - return out0, err - -} - -// TargetInterfaces is a free data retrieval call binding the contract method 0x2ade3880. -// -// Solidity: function targetInterfaces() view returns((address,string[])[] targetedInterfaces_) -func (_BitcoinState *BitcoinStateSession) TargetInterfaces() ([]StdInvariantFuzzInterface, error) { - return _BitcoinState.Contract.TargetInterfaces(&_BitcoinState.CallOpts) -} - -// TargetInterfaces is a free data retrieval call binding the contract method 0x2ade3880. -// -// Solidity: function targetInterfaces() view returns((address,string[])[] targetedInterfaces_) -func (_BitcoinState *BitcoinStateCallerSession) TargetInterfaces() ([]StdInvariantFuzzInterface, error) { - return _BitcoinState.Contract.TargetInterfaces(&_BitcoinState.CallOpts) -} - -// TargetSelectors is a free data retrieval call binding the contract method 0x916a17c6. -// -// Solidity: function targetSelectors() view returns((address,bytes4[])[] targetedSelectors_) -func (_BitcoinState *BitcoinStateCaller) TargetSelectors(opts *bind.CallOpts) ([]StdInvariantFuzzSelector, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "targetSelectors") - - if err != nil { - return *new([]StdInvariantFuzzSelector), err - } - - out0 := *abi.ConvertType(out[0], new([]StdInvariantFuzzSelector)).(*[]StdInvariantFuzzSelector) - - return out0, err - -} - -// TargetSelectors is a free data retrieval call binding the contract method 0x916a17c6. -// -// Solidity: function targetSelectors() view returns((address,bytes4[])[] targetedSelectors_) -func (_BitcoinState *BitcoinStateSession) TargetSelectors() ([]StdInvariantFuzzSelector, error) { - return _BitcoinState.Contract.TargetSelectors(&_BitcoinState.CallOpts) -} - -// TargetSelectors is a free data retrieval call binding the contract method 0x916a17c6. -// -// Solidity: function targetSelectors() view returns((address,bytes4[])[] targetedSelectors_) -func (_BitcoinState *BitcoinStateCallerSession) TargetSelectors() ([]StdInvariantFuzzSelector, error) { - return _BitcoinState.Contract.TargetSelectors(&_BitcoinState.CallOpts) -} - -// TargetSenders is a free data retrieval call binding the contract method 0x3e5e3c23. -// -// Solidity: function targetSenders() view returns(address[] targetedSenders_) -func (_BitcoinState *BitcoinStateCaller) TargetSenders(opts *bind.CallOpts) ([]common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "targetSenders") - - if err != nil { - return *new([]common.Address), err - } - - out0 := *abi.ConvertType(out[0], new([]common.Address)).(*[]common.Address) - - return out0, err - -} - -// TargetSenders is a free data retrieval call binding the contract method 0x3e5e3c23. -// -// Solidity: function targetSenders() view returns(address[] targetedSenders_) -func (_BitcoinState *BitcoinStateSession) TargetSenders() ([]common.Address, error) { - return _BitcoinState.Contract.TargetSenders(&_BitcoinState.CallOpts) -} - -// TargetSenders is a free data retrieval call binding the contract method 0x3e5e3c23. -// -// Solidity: function targetSenders() view returns(address[] targetedSenders_) -func (_BitcoinState *BitcoinStateCallerSession) TargetSenders() ([]common.Address, error) { - return _BitcoinState.Contract.TargetSenders(&_BitcoinState.CallOpts) -} - -// Tokens is a free data retrieval call binding the contract method 0x904194a3. -// -// Solidity: function tokens(bytes32 ) view returns(address) -func (_BitcoinState *BitcoinStateCaller) Tokens(opts *bind.CallOpts, arg0 [32]byte) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "tokens", arg0) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Tokens is a free data retrieval call binding the contract method 0x904194a3. -// -// Solidity: function tokens(bytes32 ) view returns(address) -func (_BitcoinState *BitcoinStateSession) Tokens(arg0 [32]byte) (common.Address, error) { - return _BitcoinState.Contract.Tokens(&_BitcoinState.CallOpts, arg0) -} - -// Tokens is a free data retrieval call binding the contract method 0x904194a3. -// -// Solidity: function tokens(bytes32 ) view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) Tokens(arg0 [32]byte) (common.Address, error) { - return _BitcoinState.Contract.Tokens(&_BitcoinState.CallOpts, arg0) -} - -// XcallService is a free data retrieval call binding the contract method 0x7bf07164. -// -// Solidity: function xcallService() view returns(address) -func (_BitcoinState *BitcoinStateCaller) XcallService(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _BitcoinState.contract.Call(opts, &out, "xcallService") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// XcallService is a free data retrieval call binding the contract method 0x7bf07164. -// -// Solidity: function xcallService() view returns(address) -func (_BitcoinState *BitcoinStateSession) XcallService() (common.Address, error) { - return _BitcoinState.Contract.XcallService(&_BitcoinState.CallOpts) -} - -// XcallService is a free data retrieval call binding the contract method 0x7bf07164. -// -// Solidity: function xcallService() view returns(address) -func (_BitcoinState *BitcoinStateCallerSession) XcallService() (common.Address, error) { - return _BitcoinState.Contract.XcallService(&_BitcoinState.CallOpts) -} - -// AddConnection is a paid mutator transaction binding the contract method 0x677dea1d. -// -// Solidity: function addConnection(address connection_) returns() -func (_BitcoinState *BitcoinStateTransactor) AddConnection(opts *bind.TransactOpts, connection_ common.Address) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "addConnection", connection_) -} - -// AddConnection is a paid mutator transaction binding the contract method 0x677dea1d. -// -// Solidity: function addConnection(address connection_) returns() -func (_BitcoinState *BitcoinStateSession) AddConnection(connection_ common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.AddConnection(&_BitcoinState.TransactOpts, connection_) -} - -// AddConnection is a paid mutator transaction binding the contract method 0x677dea1d. -// -// Solidity: function addConnection(address connection_) returns() -func (_BitcoinState *BitcoinStateTransactorSession) AddConnection(connection_ common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.AddConnection(&_BitcoinState.TransactOpts, connection_) -} - -// GetSignData is a paid mutator transaction binding the contract method 0xbcc2f19d. -// -// Solidity: function getSignData(address requester_, bytes data_) returns(bytes32) -func (_BitcoinState *BitcoinStateTransactor) GetSignData(opts *bind.TransactOpts, requester_ common.Address, data_ []byte) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "getSignData", requester_, data_) -} - -// GetSignData is a paid mutator transaction binding the contract method 0xbcc2f19d. -// -// Solidity: function getSignData(address requester_, bytes data_) returns(bytes32) -func (_BitcoinState *BitcoinStateSession) GetSignData(requester_ common.Address, data_ []byte) (*types.Transaction, error) { - return _BitcoinState.Contract.GetSignData(&_BitcoinState.TransactOpts, requester_, data_) -} - -// GetSignData is a paid mutator transaction binding the contract method 0xbcc2f19d. -// -// Solidity: function getSignData(address requester_, bytes data_) returns(bytes32) -func (_BitcoinState *BitcoinStateTransactorSession) GetSignData(requester_ common.Address, data_ []byte) (*types.Transaction, error) { - return _BitcoinState.Contract.GetSignData(&_BitcoinState.TransactOpts, requester_, data_) -} - -// HandleCallMessage is a paid mutator transaction binding the contract method 0x5d6a16f5. -// -// Solidity: function handleCallMessage(string _from, bytes _data, string[] _protocols) returns() -func (_BitcoinState *BitcoinStateTransactor) HandleCallMessage(opts *bind.TransactOpts, _from string, _data []byte, _protocols []string) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "handleCallMessage", _from, _data, _protocols) -} - -// HandleCallMessage is a paid mutator transaction binding the contract method 0x5d6a16f5. -// -// Solidity: function handleCallMessage(string _from, bytes _data, string[] _protocols) returns() -func (_BitcoinState *BitcoinStateSession) HandleCallMessage(_from string, _data []byte, _protocols []string) (*types.Transaction, error) { - return _BitcoinState.Contract.HandleCallMessage(&_BitcoinState.TransactOpts, _from, _data, _protocols) -} - -// HandleCallMessage is a paid mutator transaction binding the contract method 0x5d6a16f5. -// -// Solidity: function handleCallMessage(string _from, bytes _data, string[] _protocols) returns() -func (_BitcoinState *BitcoinStateTransactorSession) HandleCallMessage(_from string, _data []byte, _protocols []string) (*types.Transaction, error) { - return _BitcoinState.Contract.HandleCallMessage(&_BitcoinState.TransactOpts, _from, _data, _protocols) -} - -// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. -// -// Solidity: function initialize(address xcall_, address uinswapV3Router_, address nonfungiblePositionManager_, address[] connections) returns() -func (_BitcoinState *BitcoinStateTransactor) Initialize(opts *bind.TransactOpts, xcall_ common.Address, uinswapV3Router_ common.Address, nonfungiblePositionManager_ common.Address, connections []common.Address) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "initialize", xcall_, uinswapV3Router_, nonfungiblePositionManager_, connections) -} - -// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. -// -// Solidity: function initialize(address xcall_, address uinswapV3Router_, address nonfungiblePositionManager_, address[] connections) returns() -func (_BitcoinState *BitcoinStateSession) Initialize(xcall_ common.Address, uinswapV3Router_ common.Address, nonfungiblePositionManager_ common.Address, connections []common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.Initialize(&_BitcoinState.TransactOpts, xcall_, uinswapV3Router_, nonfungiblePositionManager_, connections) -} - -// Initialize is a paid mutator transaction binding the contract method 0xe6bfbfd8. -// -// Solidity: function initialize(address xcall_, address uinswapV3Router_, address nonfungiblePositionManager_, address[] connections) returns() -func (_BitcoinState *BitcoinStateTransactorSession) Initialize(xcall_ common.Address, uinswapV3Router_ common.Address, nonfungiblePositionManager_ common.Address, connections []common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.Initialize(&_BitcoinState.TransactOpts, xcall_, uinswapV3Router_, nonfungiblePositionManager_, connections) -} - -// Migrate is a paid mutator transaction binding the contract method 0x8932a90d. -// -// Solidity: function migrate(bytes _data) returns() -func (_BitcoinState *BitcoinStateTransactor) Migrate(opts *bind.TransactOpts, _data []byte) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "migrate", _data) -} - -// Migrate is a paid mutator transaction binding the contract method 0x8932a90d. -// -// Solidity: function migrate(bytes _data) returns() -func (_BitcoinState *BitcoinStateSession) Migrate(_data []byte) (*types.Transaction, error) { - return _BitcoinState.Contract.Migrate(&_BitcoinState.TransactOpts, _data) -} - -// Migrate is a paid mutator transaction binding the contract method 0x8932a90d. -// -// Solidity: function migrate(bytes _data) returns() -func (_BitcoinState *BitcoinStateTransactorSession) Migrate(_data []byte) (*types.Transaction, error) { - return _BitcoinState.Contract.Migrate(&_BitcoinState.TransactOpts, _data) -} - -// MigrateComplete is a paid mutator transaction binding the contract method 0xf0ad3762. -// -// Solidity: function migrateComplete() returns() -func (_BitcoinState *BitcoinStateTransactor) MigrateComplete(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "migrateComplete") -} - -// MigrateComplete is a paid mutator transaction binding the contract method 0xf0ad3762. -// -// Solidity: function migrateComplete() returns() -func (_BitcoinState *BitcoinStateSession) MigrateComplete() (*types.Transaction, error) { - return _BitcoinState.Contract.MigrateComplete(&_BitcoinState.TransactOpts) -} - -// MigrateComplete is a paid mutator transaction binding the contract method 0xf0ad3762. -// -// Solidity: function migrateComplete() returns() -func (_BitcoinState *BitcoinStateTransactorSession) MigrateComplete() (*types.Transaction, error) { - return _BitcoinState.Contract.MigrateComplete(&_BitcoinState.TransactOpts) -} - -// RemoveConnection is a paid mutator transaction binding the contract method 0x65301f0d. -// -// Solidity: function removeConnection(address connection_) returns() -func (_BitcoinState *BitcoinStateTransactor) RemoveConnection(opts *bind.TransactOpts, connection_ common.Address) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "removeConnection", connection_) -} - -// RemoveConnection is a paid mutator transaction binding the contract method 0x65301f0d. -// -// Solidity: function removeConnection(address connection_) returns() -func (_BitcoinState *BitcoinStateSession) RemoveConnection(connection_ common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.RemoveConnection(&_BitcoinState.TransactOpts, connection_) -} - -// RemoveConnection is a paid mutator transaction binding the contract method 0x65301f0d. -// -// Solidity: function removeConnection(address connection_) returns() -func (_BitcoinState *BitcoinStateTransactorSession) RemoveConnection(connection_ common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.RemoveConnection(&_BitcoinState.TransactOpts, connection_) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_BitcoinState *BitcoinStateTransactor) RenounceOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "renounceOwnership") -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_BitcoinState *BitcoinStateSession) RenounceOwnership() (*types.Transaction, error) { - return _BitcoinState.Contract.RenounceOwnership(&_BitcoinState.TransactOpts) -} - -// RenounceOwnership is a paid mutator transaction binding the contract method 0x715018a6. -// -// Solidity: function renounceOwnership() returns() -func (_BitcoinState *BitcoinStateTransactorSession) RenounceOwnership() (*types.Transaction, error) { - return _BitcoinState.Contract.RenounceOwnership(&_BitcoinState.TransactOpts) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_BitcoinState *BitcoinStateTransactor) TransferOwnership(opts *bind.TransactOpts, newOwner common.Address) (*types.Transaction, error) { - return _BitcoinState.contract.Transact(opts, "transferOwnership", newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_BitcoinState *BitcoinStateSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.TransferOwnership(&_BitcoinState.TransactOpts, newOwner) -} - -// TransferOwnership is a paid mutator transaction binding the contract method 0xf2fde38b. -// -// Solidity: function transferOwnership(address newOwner) returns() -func (_BitcoinState *BitcoinStateTransactorSession) TransferOwnership(newOwner common.Address) (*types.Transaction, error) { - return _BitcoinState.Contract.TransferOwnership(&_BitcoinState.TransactOpts, newOwner) -} - -// BitcoinStateAddConnectionIterator is returned from FilterAddConnection and is used to iterate over the raw logs and unpacked data for AddConnection events raised by the BitcoinState contract. -type BitcoinStateAddConnectionIterator struct { - Event *BitcoinStateAddConnection // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateAddConnectionIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateAddConnection) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateAddConnection) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateAddConnectionIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateAddConnectionIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateAddConnection represents a AddConnection event raised by the BitcoinState contract. -type BitcoinStateAddConnection struct { - Connection common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterAddConnection is a free log retrieval operation binding the contract event 0x5cd3d8da8ef00a8b5228348fe7683dae605751d4867ba7ea9fdc8260b9e2c7d3. -// -// Solidity: event AddConnection(address connection_) -func (_BitcoinState *BitcoinStateFilterer) FilterAddConnection(opts *bind.FilterOpts) (*BitcoinStateAddConnectionIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "AddConnection") - if err != nil { - return nil, err - } - return &BitcoinStateAddConnectionIterator{contract: _BitcoinState.contract, event: "AddConnection", logs: logs, sub: sub}, nil -} - -// WatchAddConnection is a free log subscription operation binding the contract event 0x5cd3d8da8ef00a8b5228348fe7683dae605751d4867ba7ea9fdc8260b9e2c7d3. -// -// Solidity: event AddConnection(address connection_) -func (_BitcoinState *BitcoinStateFilterer) WatchAddConnection(opts *bind.WatchOpts, sink chan<- *BitcoinStateAddConnection) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "AddConnection") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateAddConnection) - if err := _BitcoinState.contract.UnpackLog(event, "AddConnection", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseAddConnection is a log parse operation binding the contract event 0x5cd3d8da8ef00a8b5228348fe7683dae605751d4867ba7ea9fdc8260b9e2c7d3. -// -// Solidity: event AddConnection(address connection_) -func (_BitcoinState *BitcoinStateFilterer) ParseAddConnection(log types.Log) (*BitcoinStateAddConnection, error) { - event := new(BitcoinStateAddConnection) - if err := _BitcoinState.contract.UnpackLog(event, "AddConnection", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateAddSelectorIterator is returned from FilterAddSelector and is used to iterate over the raw logs and unpacked data for AddSelector events raised by the BitcoinState contract. -type BitcoinStateAddSelectorIterator struct { - Event *BitcoinStateAddSelector // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateAddSelectorIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateAddSelector) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateAddSelector) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateAddSelectorIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateAddSelectorIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateAddSelector represents a AddSelector event raised by the BitcoinState contract. -type BitcoinStateAddSelector struct { - Selector [4]byte - Recipient common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterAddSelector is a free log retrieval operation binding the contract event 0x95c0d09571a33725bdfaf52708354735c2650abb90fe193d20429e324a2b3696. -// -// Solidity: event AddSelector(bytes4 selector_, address recipient) -func (_BitcoinState *BitcoinStateFilterer) FilterAddSelector(opts *bind.FilterOpts) (*BitcoinStateAddSelectorIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "AddSelector") - if err != nil { - return nil, err - } - return &BitcoinStateAddSelectorIterator{contract: _BitcoinState.contract, event: "AddSelector", logs: logs, sub: sub}, nil -} - -// WatchAddSelector is a free log subscription operation binding the contract event 0x95c0d09571a33725bdfaf52708354735c2650abb90fe193d20429e324a2b3696. -// -// Solidity: event AddSelector(bytes4 selector_, address recipient) -func (_BitcoinState *BitcoinStateFilterer) WatchAddSelector(opts *bind.WatchOpts, sink chan<- *BitcoinStateAddSelector) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "AddSelector") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateAddSelector) - if err := _BitcoinState.contract.UnpackLog(event, "AddSelector", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseAddSelector is a log parse operation binding the contract event 0x95c0d09571a33725bdfaf52708354735c2650abb90fe193d20429e324a2b3696. -// -// Solidity: event AddSelector(bytes4 selector_, address recipient) -func (_BitcoinState *BitcoinStateFilterer) ParseAddSelector(log types.Log) (*BitcoinStateAddSelector, error) { - event := new(BitcoinStateAddSelector) - if err := _BitcoinState.contract.UnpackLog(event, "AddSelector", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the BitcoinState contract. -type BitcoinStateInitializedIterator struct { - Event *BitcoinStateInitialized // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateInitializedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateInitializedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateInitializedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateInitialized represents a Initialized event raised by the BitcoinState contract. -type BitcoinStateInitialized struct { - Version uint8 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInitialized is a free log retrieval operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_BitcoinState *BitcoinStateFilterer) FilterInitialized(opts *bind.FilterOpts) (*BitcoinStateInitializedIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return &BitcoinStateInitializedIterator{contract: _BitcoinState.contract, event: "Initialized", logs: logs, sub: sub}, nil -} - -// WatchInitialized is a free log subscription operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_BitcoinState *BitcoinStateFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *BitcoinStateInitialized) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateInitialized) - if err := _BitcoinState.contract.UnpackLog(event, "Initialized", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseInitialized is a log parse operation binding the contract event 0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498. -// -// Solidity: event Initialized(uint8 version) -func (_BitcoinState *BitcoinStateFilterer) ParseInitialized(log types.Log) (*BitcoinStateInitialized, error) { - event := new(BitcoinStateInitialized) - if err := _BitcoinState.contract.UnpackLog(event, "Initialized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateOwnershipTransferredIterator is returned from FilterOwnershipTransferred and is used to iterate over the raw logs and unpacked data for OwnershipTransferred events raised by the BitcoinState contract. -type BitcoinStateOwnershipTransferredIterator struct { - Event *BitcoinStateOwnershipTransferred // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateOwnershipTransferredIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateOwnershipTransferred) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateOwnershipTransferredIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateOwnershipTransferredIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateOwnershipTransferred represents a OwnershipTransferred event raised by the BitcoinState contract. -type BitcoinStateOwnershipTransferred struct { - PreviousOwner common.Address - NewOwner common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterOwnershipTransferred is a free log retrieval operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_BitcoinState *BitcoinStateFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, previousOwner []common.Address, newOwner []common.Address) (*BitcoinStateOwnershipTransferredIterator, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return &BitcoinStateOwnershipTransferredIterator{contract: _BitcoinState.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil -} - -// WatchOwnershipTransferred is a free log subscription operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_BitcoinState *BitcoinStateFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *BitcoinStateOwnershipTransferred, previousOwner []common.Address, newOwner []common.Address) (event.Subscription, error) { - - var previousOwnerRule []interface{} - for _, previousOwnerItem := range previousOwner { - previousOwnerRule = append(previousOwnerRule, previousOwnerItem) - } - var newOwnerRule []interface{} - for _, newOwnerItem := range newOwner { - newOwnerRule = append(newOwnerRule, newOwnerItem) - } - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "OwnershipTransferred", previousOwnerRule, newOwnerRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateOwnershipTransferred) - if err := _BitcoinState.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseOwnershipTransferred is a log parse operation binding the contract event 0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0. -// -// Solidity: event OwnershipTransferred(address indexed previousOwner, address indexed newOwner) -func (_BitcoinState *BitcoinStateFilterer) ParseOwnershipTransferred(log types.Log) (*BitcoinStateOwnershipTransferred, error) { - event := new(BitcoinStateOwnershipTransferred) - if err := _BitcoinState.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateRemoveConnectionIterator is returned from FilterRemoveConnection and is used to iterate over the raw logs and unpacked data for RemoveConnection events raised by the BitcoinState contract. -type BitcoinStateRemoveConnectionIterator struct { - Event *BitcoinStateRemoveConnection // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateRemoveConnectionIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateRemoveConnection) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateRemoveConnection) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateRemoveConnectionIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateRemoveConnectionIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateRemoveConnection represents a RemoveConnection event raised by the BitcoinState contract. -type BitcoinStateRemoveConnection struct { - Connection common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRemoveConnection is a free log retrieval operation binding the contract event 0xace8d11a44b7aa536cc46a77b519166c001adc485ba8cfa404e1aa252b07db38. -// -// Solidity: event RemoveConnection(address connection_) -func (_BitcoinState *BitcoinStateFilterer) FilterRemoveConnection(opts *bind.FilterOpts) (*BitcoinStateRemoveConnectionIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "RemoveConnection") - if err != nil { - return nil, err - } - return &BitcoinStateRemoveConnectionIterator{contract: _BitcoinState.contract, event: "RemoveConnection", logs: logs, sub: sub}, nil -} - -// WatchRemoveConnection is a free log subscription operation binding the contract event 0xace8d11a44b7aa536cc46a77b519166c001adc485ba8cfa404e1aa252b07db38. -// -// Solidity: event RemoveConnection(address connection_) -func (_BitcoinState *BitcoinStateFilterer) WatchRemoveConnection(opts *bind.WatchOpts, sink chan<- *BitcoinStateRemoveConnection) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "RemoveConnection") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateRemoveConnection) - if err := _BitcoinState.contract.UnpackLog(event, "RemoveConnection", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRemoveConnection is a log parse operation binding the contract event 0xace8d11a44b7aa536cc46a77b519166c001adc485ba8cfa404e1aa252b07db38. -// -// Solidity: event RemoveConnection(address connection_) -func (_BitcoinState *BitcoinStateFilterer) ParseRemoveConnection(log types.Log) (*BitcoinStateRemoveConnection, error) { - event := new(BitcoinStateRemoveConnection) - if err := _BitcoinState.contract.UnpackLog(event, "RemoveConnection", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateRemoveSelectorIterator is returned from FilterRemoveSelector and is used to iterate over the raw logs and unpacked data for RemoveSelector events raised by the BitcoinState contract. -type BitcoinStateRemoveSelectorIterator struct { - Event *BitcoinStateRemoveSelector // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateRemoveSelectorIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateRemoveSelector) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateRemoveSelector) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateRemoveSelectorIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateRemoveSelectorIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateRemoveSelector represents a RemoveSelector event raised by the BitcoinState contract. -type BitcoinStateRemoveSelector struct { - Selector [4]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRemoveSelector is a free log retrieval operation binding the contract event 0x85a48e474e38192938033da06ebe84a59fb194958d1be091ac2fa9a6630da31f. -// -// Solidity: event RemoveSelector(bytes4 selector_) -func (_BitcoinState *BitcoinStateFilterer) FilterRemoveSelector(opts *bind.FilterOpts) (*BitcoinStateRemoveSelectorIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "RemoveSelector") - if err != nil { - return nil, err - } - return &BitcoinStateRemoveSelectorIterator{contract: _BitcoinState.contract, event: "RemoveSelector", logs: logs, sub: sub}, nil -} - -// WatchRemoveSelector is a free log subscription operation binding the contract event 0x85a48e474e38192938033da06ebe84a59fb194958d1be091ac2fa9a6630da31f. -// -// Solidity: event RemoveSelector(bytes4 selector_) -func (_BitcoinState *BitcoinStateFilterer) WatchRemoveSelector(opts *bind.WatchOpts, sink chan<- *BitcoinStateRemoveSelector) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "RemoveSelector") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateRemoveSelector) - if err := _BitcoinState.contract.UnpackLog(event, "RemoveSelector", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRemoveSelector is a log parse operation binding the contract event 0x85a48e474e38192938033da06ebe84a59fb194958d1be091ac2fa9a6630da31f. -// -// Solidity: event RemoveSelector(bytes4 selector_) -func (_BitcoinState *BitcoinStateFilterer) ParseRemoveSelector(log types.Log) (*BitcoinStateRemoveSelector, error) { - event := new(BitcoinStateRemoveSelector) - if err := _BitcoinState.contract.UnpackLog(event, "RemoveSelector", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateRequestExecutedIterator is returned from FilterRequestExecuted and is used to iterate over the raw logs and unpacked data for RequestExecuted events raised by the BitcoinState contract. -type BitcoinStateRequestExecutedIterator struct { - Event *BitcoinStateRequestExecuted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateRequestExecutedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateRequestExecuted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateRequestExecuted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateRequestExecutedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateRequestExecutedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateRequestExecuted represents a RequestExecuted event raised by the BitcoinState contract. -type BitcoinStateRequestExecuted struct { - Id *big.Int - StateRoot [32]byte - Data []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRequestExecuted is a free log retrieval operation binding the contract event 0x9c343316d67a8e28446ef883ab491ece3ff70d3eeaa9fbd13a362a0afd690721. -// -// Solidity: event RequestExecuted(uint256 id, bytes32 stateRoot, bytes data) -func (_BitcoinState *BitcoinStateFilterer) FilterRequestExecuted(opts *bind.FilterOpts) (*BitcoinStateRequestExecutedIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "RequestExecuted") - if err != nil { - return nil, err - } - return &BitcoinStateRequestExecutedIterator{contract: _BitcoinState.contract, event: "RequestExecuted", logs: logs, sub: sub}, nil -} - -// WatchRequestExecuted is a free log subscription operation binding the contract event 0x9c343316d67a8e28446ef883ab491ece3ff70d3eeaa9fbd13a362a0afd690721. -// -// Solidity: event RequestExecuted(uint256 id, bytes32 stateRoot, bytes data) -func (_BitcoinState *BitcoinStateFilterer) WatchRequestExecuted(opts *bind.WatchOpts, sink chan<- *BitcoinStateRequestExecuted) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "RequestExecuted") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateRequestExecuted) - if err := _BitcoinState.contract.UnpackLog(event, "RequestExecuted", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRequestExecuted is a log parse operation binding the contract event 0x9c343316d67a8e28446ef883ab491ece3ff70d3eeaa9fbd13a362a0afd690721. -// -// Solidity: event RequestExecuted(uint256 id, bytes32 stateRoot, bytes data) -func (_BitcoinState *BitcoinStateFilterer) ParseRequestExecuted(log types.Log) (*BitcoinStateRequestExecuted, error) { - event := new(BitcoinStateRequestExecuted) - if err := _BitcoinState.contract.UnpackLog(event, "RequestExecuted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogIterator is returned from FilterLog and is used to iterate over the raw logs and unpacked data for Log events raised by the BitcoinState contract. -type BitcoinStateLogIterator struct { - Event *BitcoinStateLog // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLog) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLog) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLog represents a Log event raised by the BitcoinState contract. -type BitcoinStateLog struct { - Arg0 string - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLog is a free log retrieval operation binding the contract event 0x41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50. -// -// Solidity: event log(string arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLog(opts *bind.FilterOpts) (*BitcoinStateLogIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log") - if err != nil { - return nil, err - } - return &BitcoinStateLogIterator{contract: _BitcoinState.contract, event: "log", logs: logs, sub: sub}, nil -} - -// WatchLog is a free log subscription operation binding the contract event 0x41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50. -// -// Solidity: event log(string arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLog(opts *bind.WatchOpts, sink chan<- *BitcoinStateLog) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLog) - if err := _BitcoinState.contract.UnpackLog(event, "log", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLog is a log parse operation binding the contract event 0x41304facd9323d75b11bcdd609cb38effffdb05710f7caf0e9b16c6d9d709f50. -// -// Solidity: event log(string arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLog(log types.Log) (*BitcoinStateLog, error) { - event := new(BitcoinStateLog) - if err := _BitcoinState.contract.UnpackLog(event, "log", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogAddressIterator is returned from FilterLogAddress and is used to iterate over the raw logs and unpacked data for LogAddress events raised by the BitcoinState contract. -type BitcoinStateLogAddressIterator struct { - Event *BitcoinStateLogAddress // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogAddressIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogAddress) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogAddress) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogAddressIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogAddressIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogAddress represents a LogAddress event raised by the BitcoinState contract. -type BitcoinStateLogAddress struct { - Arg0 common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogAddress is a free log retrieval operation binding the contract event 0x7ae74c527414ae135fd97047b12921a5ec3911b804197855d67e25c7b75ee6f3. -// -// Solidity: event log_address(address arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLogAddress(opts *bind.FilterOpts) (*BitcoinStateLogAddressIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_address") - if err != nil { - return nil, err - } - return &BitcoinStateLogAddressIterator{contract: _BitcoinState.contract, event: "log_address", logs: logs, sub: sub}, nil -} - -// WatchLogAddress is a free log subscription operation binding the contract event 0x7ae74c527414ae135fd97047b12921a5ec3911b804197855d67e25c7b75ee6f3. -// -// Solidity: event log_address(address arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLogAddress(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogAddress) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_address") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogAddress) - if err := _BitcoinState.contract.UnpackLog(event, "log_address", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogAddress is a log parse operation binding the contract event 0x7ae74c527414ae135fd97047b12921a5ec3911b804197855d67e25c7b75ee6f3. -// -// Solidity: event log_address(address arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLogAddress(log types.Log) (*BitcoinStateLogAddress, error) { - event := new(BitcoinStateLogAddress) - if err := _BitcoinState.contract.UnpackLog(event, "log_address", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogArrayIterator is returned from FilterLogArray and is used to iterate over the raw logs and unpacked data for LogArray events raised by the BitcoinState contract. -type BitcoinStateLogArrayIterator struct { - Event *BitcoinStateLogArray // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogArrayIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogArray) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogArray) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogArrayIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogArrayIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogArray represents a LogArray event raised by the BitcoinState contract. -type BitcoinStateLogArray struct { - Val []*big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogArray is a free log retrieval operation binding the contract event 0xfb102865d50addddf69da9b5aa1bced66c80cf869a5c8d0471a467e18ce9cab1. -// -// Solidity: event log_array(uint256[] val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogArray(opts *bind.FilterOpts) (*BitcoinStateLogArrayIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_array") - if err != nil { - return nil, err - } - return &BitcoinStateLogArrayIterator{contract: _BitcoinState.contract, event: "log_array", logs: logs, sub: sub}, nil -} - -// WatchLogArray is a free log subscription operation binding the contract event 0xfb102865d50addddf69da9b5aa1bced66c80cf869a5c8d0471a467e18ce9cab1. -// -// Solidity: event log_array(uint256[] val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogArray(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogArray) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_array") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogArray) - if err := _BitcoinState.contract.UnpackLog(event, "log_array", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogArray is a log parse operation binding the contract event 0xfb102865d50addddf69da9b5aa1bced66c80cf869a5c8d0471a467e18ce9cab1. -// -// Solidity: event log_array(uint256[] val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogArray(log types.Log) (*BitcoinStateLogArray, error) { - event := new(BitcoinStateLogArray) - if err := _BitcoinState.contract.UnpackLog(event, "log_array", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogArray0Iterator is returned from FilterLogArray0 and is used to iterate over the raw logs and unpacked data for LogArray0 events raised by the BitcoinState contract. -type BitcoinStateLogArray0Iterator struct { - Event *BitcoinStateLogArray0 // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogArray0Iterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogArray0) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogArray0) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogArray0Iterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogArray0Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogArray0 represents a LogArray0 event raised by the BitcoinState contract. -type BitcoinStateLogArray0 struct { - Val []*big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogArray0 is a free log retrieval operation binding the contract event 0x890a82679b470f2bd82816ed9b161f97d8b967f37fa3647c21d5bf39749e2dd5. -// -// Solidity: event log_array(int256[] val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogArray0(opts *bind.FilterOpts) (*BitcoinStateLogArray0Iterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_array0") - if err != nil { - return nil, err - } - return &BitcoinStateLogArray0Iterator{contract: _BitcoinState.contract, event: "log_array0", logs: logs, sub: sub}, nil -} - -// WatchLogArray0 is a free log subscription operation binding the contract event 0x890a82679b470f2bd82816ed9b161f97d8b967f37fa3647c21d5bf39749e2dd5. -// -// Solidity: event log_array(int256[] val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogArray0(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogArray0) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_array0") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogArray0) - if err := _BitcoinState.contract.UnpackLog(event, "log_array0", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogArray0 is a log parse operation binding the contract event 0x890a82679b470f2bd82816ed9b161f97d8b967f37fa3647c21d5bf39749e2dd5. -// -// Solidity: event log_array(int256[] val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogArray0(log types.Log) (*BitcoinStateLogArray0, error) { - event := new(BitcoinStateLogArray0) - if err := _BitcoinState.contract.UnpackLog(event, "log_array0", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogArray1Iterator is returned from FilterLogArray1 and is used to iterate over the raw logs and unpacked data for LogArray1 events raised by the BitcoinState contract. -type BitcoinStateLogArray1Iterator struct { - Event *BitcoinStateLogArray1 // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogArray1Iterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogArray1) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogArray1) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogArray1Iterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogArray1Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogArray1 represents a LogArray1 event raised by the BitcoinState contract. -type BitcoinStateLogArray1 struct { - Val []common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogArray1 is a free log retrieval operation binding the contract event 0x40e1840f5769073d61bd01372d9b75baa9842d5629a0c99ff103be1178a8e9e2. -// -// Solidity: event log_array(address[] val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogArray1(opts *bind.FilterOpts) (*BitcoinStateLogArray1Iterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_array1") - if err != nil { - return nil, err - } - return &BitcoinStateLogArray1Iterator{contract: _BitcoinState.contract, event: "log_array1", logs: logs, sub: sub}, nil -} - -// WatchLogArray1 is a free log subscription operation binding the contract event 0x40e1840f5769073d61bd01372d9b75baa9842d5629a0c99ff103be1178a8e9e2. -// -// Solidity: event log_array(address[] val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogArray1(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogArray1) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_array1") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogArray1) - if err := _BitcoinState.contract.UnpackLog(event, "log_array1", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogArray1 is a log parse operation binding the contract event 0x40e1840f5769073d61bd01372d9b75baa9842d5629a0c99ff103be1178a8e9e2. -// -// Solidity: event log_array(address[] val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogArray1(log types.Log) (*BitcoinStateLogArray1, error) { - event := new(BitcoinStateLogArray1) - if err := _BitcoinState.contract.UnpackLog(event, "log_array1", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogBytesIterator is returned from FilterLogBytes and is used to iterate over the raw logs and unpacked data for LogBytes events raised by the BitcoinState contract. -type BitcoinStateLogBytesIterator struct { - Event *BitcoinStateLogBytes // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogBytesIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogBytes) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogBytes) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogBytesIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogBytesIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogBytes represents a LogBytes event raised by the BitcoinState contract. -type BitcoinStateLogBytes struct { - Arg0 []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogBytes is a free log retrieval operation binding the contract event 0x23b62ad0584d24a75f0bf3560391ef5659ec6db1269c56e11aa241d637f19b20. -// -// Solidity: event log_bytes(bytes arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLogBytes(opts *bind.FilterOpts) (*BitcoinStateLogBytesIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_bytes") - if err != nil { - return nil, err - } - return &BitcoinStateLogBytesIterator{contract: _BitcoinState.contract, event: "log_bytes", logs: logs, sub: sub}, nil -} - -// WatchLogBytes is a free log subscription operation binding the contract event 0x23b62ad0584d24a75f0bf3560391ef5659ec6db1269c56e11aa241d637f19b20. -// -// Solidity: event log_bytes(bytes arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLogBytes(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogBytes) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_bytes") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogBytes) - if err := _BitcoinState.contract.UnpackLog(event, "log_bytes", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogBytes is a log parse operation binding the contract event 0x23b62ad0584d24a75f0bf3560391ef5659ec6db1269c56e11aa241d637f19b20. -// -// Solidity: event log_bytes(bytes arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLogBytes(log types.Log) (*BitcoinStateLogBytes, error) { - event := new(BitcoinStateLogBytes) - if err := _BitcoinState.contract.UnpackLog(event, "log_bytes", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogBytes32Iterator is returned from FilterLogBytes32 and is used to iterate over the raw logs and unpacked data for LogBytes32 events raised by the BitcoinState contract. -type BitcoinStateLogBytes32Iterator struct { - Event *BitcoinStateLogBytes32 // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogBytes32Iterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogBytes32) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogBytes32) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogBytes32Iterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogBytes32Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogBytes32 represents a LogBytes32 event raised by the BitcoinState contract. -type BitcoinStateLogBytes32 struct { - Arg0 [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogBytes32 is a free log retrieval operation binding the contract event 0xe81699b85113eea1c73e10588b2b035e55893369632173afd43feb192fac64e3. -// -// Solidity: event log_bytes32(bytes32 arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLogBytes32(opts *bind.FilterOpts) (*BitcoinStateLogBytes32Iterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_bytes32") - if err != nil { - return nil, err - } - return &BitcoinStateLogBytes32Iterator{contract: _BitcoinState.contract, event: "log_bytes32", logs: logs, sub: sub}, nil -} - -// WatchLogBytes32 is a free log subscription operation binding the contract event 0xe81699b85113eea1c73e10588b2b035e55893369632173afd43feb192fac64e3. -// -// Solidity: event log_bytes32(bytes32 arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLogBytes32(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogBytes32) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_bytes32") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogBytes32) - if err := _BitcoinState.contract.UnpackLog(event, "log_bytes32", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogBytes32 is a log parse operation binding the contract event 0xe81699b85113eea1c73e10588b2b035e55893369632173afd43feb192fac64e3. -// -// Solidity: event log_bytes32(bytes32 arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLogBytes32(log types.Log) (*BitcoinStateLogBytes32, error) { - event := new(BitcoinStateLogBytes32) - if err := _BitcoinState.contract.UnpackLog(event, "log_bytes32", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogIntIterator is returned from FilterLogInt and is used to iterate over the raw logs and unpacked data for LogInt events raised by the BitcoinState contract. -type BitcoinStateLogIntIterator struct { - Event *BitcoinStateLogInt // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogIntIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogInt) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogInt) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogIntIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogIntIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogInt represents a LogInt event raised by the BitcoinState contract. -type BitcoinStateLogInt struct { - Arg0 *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogInt is a free log retrieval operation binding the contract event 0x0eb5d52624c8d28ada9fc55a8c502ed5aa3fbe2fb6e91b71b5f376882b1d2fb8. -// -// Solidity: event log_int(int256 arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLogInt(opts *bind.FilterOpts) (*BitcoinStateLogIntIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_int") - if err != nil { - return nil, err - } - return &BitcoinStateLogIntIterator{contract: _BitcoinState.contract, event: "log_int", logs: logs, sub: sub}, nil -} - -// WatchLogInt is a free log subscription operation binding the contract event 0x0eb5d52624c8d28ada9fc55a8c502ed5aa3fbe2fb6e91b71b5f376882b1d2fb8. -// -// Solidity: event log_int(int256 arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLogInt(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogInt) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_int") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogInt) - if err := _BitcoinState.contract.UnpackLog(event, "log_int", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogInt is a log parse operation binding the contract event 0x0eb5d52624c8d28ada9fc55a8c502ed5aa3fbe2fb6e91b71b5f376882b1d2fb8. -// -// Solidity: event log_int(int256 arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLogInt(log types.Log) (*BitcoinStateLogInt, error) { - event := new(BitcoinStateLogInt) - if err := _BitcoinState.contract.UnpackLog(event, "log_int", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedAddressIterator is returned from FilterLogNamedAddress and is used to iterate over the raw logs and unpacked data for LogNamedAddress events raised by the BitcoinState contract. -type BitcoinStateLogNamedAddressIterator struct { - Event *BitcoinStateLogNamedAddress // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedAddressIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedAddress) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedAddress) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedAddressIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedAddressIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedAddress represents a LogNamedAddress event raised by the BitcoinState contract. -type BitcoinStateLogNamedAddress struct { - Key string - Val common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedAddress is a free log retrieval operation binding the contract event 0x9c4e8541ca8f0dc1c413f9108f66d82d3cecb1bddbce437a61caa3175c4cc96f. -// -// Solidity: event log_named_address(string key, address val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedAddress(opts *bind.FilterOpts) (*BitcoinStateLogNamedAddressIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_address") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedAddressIterator{contract: _BitcoinState.contract, event: "log_named_address", logs: logs, sub: sub}, nil -} - -// WatchLogNamedAddress is a free log subscription operation binding the contract event 0x9c4e8541ca8f0dc1c413f9108f66d82d3cecb1bddbce437a61caa3175c4cc96f. -// -// Solidity: event log_named_address(string key, address val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedAddress(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedAddress) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_address") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedAddress) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_address", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedAddress is a log parse operation binding the contract event 0x9c4e8541ca8f0dc1c413f9108f66d82d3cecb1bddbce437a61caa3175c4cc96f. -// -// Solidity: event log_named_address(string key, address val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedAddress(log types.Log) (*BitcoinStateLogNamedAddress, error) { - event := new(BitcoinStateLogNamedAddress) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_address", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedArrayIterator is returned from FilterLogNamedArray and is used to iterate over the raw logs and unpacked data for LogNamedArray events raised by the BitcoinState contract. -type BitcoinStateLogNamedArrayIterator struct { - Event *BitcoinStateLogNamedArray // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedArrayIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedArray) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedArray) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedArrayIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedArrayIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedArray represents a LogNamedArray event raised by the BitcoinState contract. -type BitcoinStateLogNamedArray struct { - Key string - Val []*big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedArray is a free log retrieval operation binding the contract event 0x00aaa39c9ffb5f567a4534380c737075702e1f7f14107fc95328e3b56c0325fb. -// -// Solidity: event log_named_array(string key, uint256[] val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedArray(opts *bind.FilterOpts) (*BitcoinStateLogNamedArrayIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_array") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedArrayIterator{contract: _BitcoinState.contract, event: "log_named_array", logs: logs, sub: sub}, nil -} - -// WatchLogNamedArray is a free log subscription operation binding the contract event 0x00aaa39c9ffb5f567a4534380c737075702e1f7f14107fc95328e3b56c0325fb. -// -// Solidity: event log_named_array(string key, uint256[] val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedArray(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedArray) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_array") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedArray) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_array", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedArray is a log parse operation binding the contract event 0x00aaa39c9ffb5f567a4534380c737075702e1f7f14107fc95328e3b56c0325fb. -// -// Solidity: event log_named_array(string key, uint256[] val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedArray(log types.Log) (*BitcoinStateLogNamedArray, error) { - event := new(BitcoinStateLogNamedArray) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_array", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedArray0Iterator is returned from FilterLogNamedArray0 and is used to iterate over the raw logs and unpacked data for LogNamedArray0 events raised by the BitcoinState contract. -type BitcoinStateLogNamedArray0Iterator struct { - Event *BitcoinStateLogNamedArray0 // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedArray0Iterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedArray0) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedArray0) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedArray0Iterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedArray0Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedArray0 represents a LogNamedArray0 event raised by the BitcoinState contract. -type BitcoinStateLogNamedArray0 struct { - Key string - Val []*big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedArray0 is a free log retrieval operation binding the contract event 0xa73eda09662f46dde729be4611385ff34fe6c44fbbc6f7e17b042b59a3445b57. -// -// Solidity: event log_named_array(string key, int256[] val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedArray0(opts *bind.FilterOpts) (*BitcoinStateLogNamedArray0Iterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_array0") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedArray0Iterator{contract: _BitcoinState.contract, event: "log_named_array0", logs: logs, sub: sub}, nil -} - -// WatchLogNamedArray0 is a free log subscription operation binding the contract event 0xa73eda09662f46dde729be4611385ff34fe6c44fbbc6f7e17b042b59a3445b57. -// -// Solidity: event log_named_array(string key, int256[] val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedArray0(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedArray0) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_array0") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedArray0) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_array0", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedArray0 is a log parse operation binding the contract event 0xa73eda09662f46dde729be4611385ff34fe6c44fbbc6f7e17b042b59a3445b57. -// -// Solidity: event log_named_array(string key, int256[] val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedArray0(log types.Log) (*BitcoinStateLogNamedArray0, error) { - event := new(BitcoinStateLogNamedArray0) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_array0", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedArray1Iterator is returned from FilterLogNamedArray1 and is used to iterate over the raw logs and unpacked data for LogNamedArray1 events raised by the BitcoinState contract. -type BitcoinStateLogNamedArray1Iterator struct { - Event *BitcoinStateLogNamedArray1 // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedArray1Iterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedArray1) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedArray1) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedArray1Iterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedArray1Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedArray1 represents a LogNamedArray1 event raised by the BitcoinState contract. -type BitcoinStateLogNamedArray1 struct { - Key string - Val []common.Address - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedArray1 is a free log retrieval operation binding the contract event 0x3bcfb2ae2e8d132dd1fce7cf278a9a19756a9fceabe470df3bdabb4bc577d1bd. -// -// Solidity: event log_named_array(string key, address[] val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedArray1(opts *bind.FilterOpts) (*BitcoinStateLogNamedArray1Iterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_array1") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedArray1Iterator{contract: _BitcoinState.contract, event: "log_named_array1", logs: logs, sub: sub}, nil -} - -// WatchLogNamedArray1 is a free log subscription operation binding the contract event 0x3bcfb2ae2e8d132dd1fce7cf278a9a19756a9fceabe470df3bdabb4bc577d1bd. -// -// Solidity: event log_named_array(string key, address[] val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedArray1(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedArray1) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_array1") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedArray1) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_array1", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedArray1 is a log parse operation binding the contract event 0x3bcfb2ae2e8d132dd1fce7cf278a9a19756a9fceabe470df3bdabb4bc577d1bd. -// -// Solidity: event log_named_array(string key, address[] val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedArray1(log types.Log) (*BitcoinStateLogNamedArray1, error) { - event := new(BitcoinStateLogNamedArray1) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_array1", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedBytesIterator is returned from FilterLogNamedBytes and is used to iterate over the raw logs and unpacked data for LogNamedBytes events raised by the BitcoinState contract. -type BitcoinStateLogNamedBytesIterator struct { - Event *BitcoinStateLogNamedBytes // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedBytesIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedBytes) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedBytes) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedBytesIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedBytesIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedBytes represents a LogNamedBytes event raised by the BitcoinState contract. -type BitcoinStateLogNamedBytes struct { - Key string - Val []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedBytes is a free log retrieval operation binding the contract event 0xd26e16cad4548705e4c9e2d94f98ee91c289085ee425594fd5635fa2964ccf18. -// -// Solidity: event log_named_bytes(string key, bytes val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedBytes(opts *bind.FilterOpts) (*BitcoinStateLogNamedBytesIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_bytes") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedBytesIterator{contract: _BitcoinState.contract, event: "log_named_bytes", logs: logs, sub: sub}, nil -} - -// WatchLogNamedBytes is a free log subscription operation binding the contract event 0xd26e16cad4548705e4c9e2d94f98ee91c289085ee425594fd5635fa2964ccf18. -// -// Solidity: event log_named_bytes(string key, bytes val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedBytes(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedBytes) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_bytes") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedBytes) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedBytes is a log parse operation binding the contract event 0xd26e16cad4548705e4c9e2d94f98ee91c289085ee425594fd5635fa2964ccf18. -// -// Solidity: event log_named_bytes(string key, bytes val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedBytes(log types.Log) (*BitcoinStateLogNamedBytes, error) { - event := new(BitcoinStateLogNamedBytes) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedBytes32Iterator is returned from FilterLogNamedBytes32 and is used to iterate over the raw logs and unpacked data for LogNamedBytes32 events raised by the BitcoinState contract. -type BitcoinStateLogNamedBytes32Iterator struct { - Event *BitcoinStateLogNamedBytes32 // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedBytes32Iterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedBytes32) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedBytes32) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedBytes32Iterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedBytes32Iterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedBytes32 represents a LogNamedBytes32 event raised by the BitcoinState contract. -type BitcoinStateLogNamedBytes32 struct { - Key string - Val [32]byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedBytes32 is a free log retrieval operation binding the contract event 0xafb795c9c61e4fe7468c386f925d7a5429ecad9c0495ddb8d38d690614d32f99. -// -// Solidity: event log_named_bytes32(string key, bytes32 val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedBytes32(opts *bind.FilterOpts) (*BitcoinStateLogNamedBytes32Iterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_bytes32") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedBytes32Iterator{contract: _BitcoinState.contract, event: "log_named_bytes32", logs: logs, sub: sub}, nil -} - -// WatchLogNamedBytes32 is a free log subscription operation binding the contract event 0xafb795c9c61e4fe7468c386f925d7a5429ecad9c0495ddb8d38d690614d32f99. -// -// Solidity: event log_named_bytes32(string key, bytes32 val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedBytes32(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedBytes32) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_bytes32") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedBytes32) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes32", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedBytes32 is a log parse operation binding the contract event 0xafb795c9c61e4fe7468c386f925d7a5429ecad9c0495ddb8d38d690614d32f99. -// -// Solidity: event log_named_bytes32(string key, bytes32 val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedBytes32(log types.Log) (*BitcoinStateLogNamedBytes32, error) { - event := new(BitcoinStateLogNamedBytes32) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_bytes32", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedDecimalIntIterator is returned from FilterLogNamedDecimalInt and is used to iterate over the raw logs and unpacked data for LogNamedDecimalInt events raised by the BitcoinState contract. -type BitcoinStateLogNamedDecimalIntIterator struct { - Event *BitcoinStateLogNamedDecimalInt // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedDecimalIntIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedDecimalInt) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedDecimalInt) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedDecimalIntIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedDecimalIntIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedDecimalInt represents a LogNamedDecimalInt event raised by the BitcoinState contract. -type BitcoinStateLogNamedDecimalInt struct { - Key string - Val *big.Int - Decimals *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedDecimalInt is a free log retrieval operation binding the contract event 0x5da6ce9d51151ba10c09a559ef24d520b9dac5c5b8810ae8434e4d0d86411a95. -// -// Solidity: event log_named_decimal_int(string key, int256 val, uint256 decimals) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedDecimalInt(opts *bind.FilterOpts) (*BitcoinStateLogNamedDecimalIntIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_decimal_int") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedDecimalIntIterator{contract: _BitcoinState.contract, event: "log_named_decimal_int", logs: logs, sub: sub}, nil -} - -// WatchLogNamedDecimalInt is a free log subscription operation binding the contract event 0x5da6ce9d51151ba10c09a559ef24d520b9dac5c5b8810ae8434e4d0d86411a95. -// -// Solidity: event log_named_decimal_int(string key, int256 val, uint256 decimals) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedDecimalInt(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedDecimalInt) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_decimal_int") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedDecimalInt) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_int", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedDecimalInt is a log parse operation binding the contract event 0x5da6ce9d51151ba10c09a559ef24d520b9dac5c5b8810ae8434e4d0d86411a95. -// -// Solidity: event log_named_decimal_int(string key, int256 val, uint256 decimals) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedDecimalInt(log types.Log) (*BitcoinStateLogNamedDecimalInt, error) { - event := new(BitcoinStateLogNamedDecimalInt) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_int", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedDecimalUintIterator is returned from FilterLogNamedDecimalUint and is used to iterate over the raw logs and unpacked data for LogNamedDecimalUint events raised by the BitcoinState contract. -type BitcoinStateLogNamedDecimalUintIterator struct { - Event *BitcoinStateLogNamedDecimalUint // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedDecimalUintIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedDecimalUint) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedDecimalUint) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedDecimalUintIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedDecimalUintIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedDecimalUint represents a LogNamedDecimalUint event raised by the BitcoinState contract. -type BitcoinStateLogNamedDecimalUint struct { - Key string - Val *big.Int - Decimals *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedDecimalUint is a free log retrieval operation binding the contract event 0xeb8ba43ced7537421946bd43e828b8b2b8428927aa8f801c13d934bf11aca57b. -// -// Solidity: event log_named_decimal_uint(string key, uint256 val, uint256 decimals) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedDecimalUint(opts *bind.FilterOpts) (*BitcoinStateLogNamedDecimalUintIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_decimal_uint") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedDecimalUintIterator{contract: _BitcoinState.contract, event: "log_named_decimal_uint", logs: logs, sub: sub}, nil -} - -// WatchLogNamedDecimalUint is a free log subscription operation binding the contract event 0xeb8ba43ced7537421946bd43e828b8b2b8428927aa8f801c13d934bf11aca57b. -// -// Solidity: event log_named_decimal_uint(string key, uint256 val, uint256 decimals) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedDecimalUint(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedDecimalUint) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_decimal_uint") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedDecimalUint) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_uint", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedDecimalUint is a log parse operation binding the contract event 0xeb8ba43ced7537421946bd43e828b8b2b8428927aa8f801c13d934bf11aca57b. -// -// Solidity: event log_named_decimal_uint(string key, uint256 val, uint256 decimals) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedDecimalUint(log types.Log) (*BitcoinStateLogNamedDecimalUint, error) { - event := new(BitcoinStateLogNamedDecimalUint) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_decimal_uint", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedIntIterator is returned from FilterLogNamedInt and is used to iterate over the raw logs and unpacked data for LogNamedInt events raised by the BitcoinState contract. -type BitcoinStateLogNamedIntIterator struct { - Event *BitcoinStateLogNamedInt // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedIntIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedInt) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedInt) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedIntIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedIntIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedInt represents a LogNamedInt event raised by the BitcoinState contract. -type BitcoinStateLogNamedInt struct { - Key string - Val *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedInt is a free log retrieval operation binding the contract event 0x2fe632779174374378442a8e978bccfbdcc1d6b2b0d81f7e8eb776ab2286f168. -// -// Solidity: event log_named_int(string key, int256 val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedInt(opts *bind.FilterOpts) (*BitcoinStateLogNamedIntIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_int") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedIntIterator{contract: _BitcoinState.contract, event: "log_named_int", logs: logs, sub: sub}, nil -} - -// WatchLogNamedInt is a free log subscription operation binding the contract event 0x2fe632779174374378442a8e978bccfbdcc1d6b2b0d81f7e8eb776ab2286f168. -// -// Solidity: event log_named_int(string key, int256 val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedInt(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedInt) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_int") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedInt) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_int", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedInt is a log parse operation binding the contract event 0x2fe632779174374378442a8e978bccfbdcc1d6b2b0d81f7e8eb776ab2286f168. -// -// Solidity: event log_named_int(string key, int256 val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedInt(log types.Log) (*BitcoinStateLogNamedInt, error) { - event := new(BitcoinStateLogNamedInt) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_int", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedStringIterator is returned from FilterLogNamedString and is used to iterate over the raw logs and unpacked data for LogNamedString events raised by the BitcoinState contract. -type BitcoinStateLogNamedStringIterator struct { - Event *BitcoinStateLogNamedString // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedStringIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedString) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedString) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedStringIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedStringIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedString represents a LogNamedString event raised by the BitcoinState contract. -type BitcoinStateLogNamedString struct { - Key string - Val string - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedString is a free log retrieval operation binding the contract event 0x280f4446b28a1372417dda658d30b95b2992b12ac9c7f378535f29a97acf3583. -// -// Solidity: event log_named_string(string key, string val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedString(opts *bind.FilterOpts) (*BitcoinStateLogNamedStringIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_string") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedStringIterator{contract: _BitcoinState.contract, event: "log_named_string", logs: logs, sub: sub}, nil -} - -// WatchLogNamedString is a free log subscription operation binding the contract event 0x280f4446b28a1372417dda658d30b95b2992b12ac9c7f378535f29a97acf3583. -// -// Solidity: event log_named_string(string key, string val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedString(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedString) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_string") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedString) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_string", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedString is a log parse operation binding the contract event 0x280f4446b28a1372417dda658d30b95b2992b12ac9c7f378535f29a97acf3583. -// -// Solidity: event log_named_string(string key, string val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedString(log types.Log) (*BitcoinStateLogNamedString, error) { - event := new(BitcoinStateLogNamedString) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_string", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogNamedUintIterator is returned from FilterLogNamedUint and is used to iterate over the raw logs and unpacked data for LogNamedUint events raised by the BitcoinState contract. -type BitcoinStateLogNamedUintIterator struct { - Event *BitcoinStateLogNamedUint // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogNamedUintIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedUint) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogNamedUint) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogNamedUintIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogNamedUintIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogNamedUint represents a LogNamedUint event raised by the BitcoinState contract. -type BitcoinStateLogNamedUint struct { - Key string - Val *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogNamedUint is a free log retrieval operation binding the contract event 0xb2de2fbe801a0df6c0cbddfd448ba3c41d48a040ca35c56c8196ef0fcae721a8. -// -// Solidity: event log_named_uint(string key, uint256 val) -func (_BitcoinState *BitcoinStateFilterer) FilterLogNamedUint(opts *bind.FilterOpts) (*BitcoinStateLogNamedUintIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_named_uint") - if err != nil { - return nil, err - } - return &BitcoinStateLogNamedUintIterator{contract: _BitcoinState.contract, event: "log_named_uint", logs: logs, sub: sub}, nil -} - -// WatchLogNamedUint is a free log subscription operation binding the contract event 0xb2de2fbe801a0df6c0cbddfd448ba3c41d48a040ca35c56c8196ef0fcae721a8. -// -// Solidity: event log_named_uint(string key, uint256 val) -func (_BitcoinState *BitcoinStateFilterer) WatchLogNamedUint(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogNamedUint) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_named_uint") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogNamedUint) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_uint", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogNamedUint is a log parse operation binding the contract event 0xb2de2fbe801a0df6c0cbddfd448ba3c41d48a040ca35c56c8196ef0fcae721a8. -// -// Solidity: event log_named_uint(string key, uint256 val) -func (_BitcoinState *BitcoinStateFilterer) ParseLogNamedUint(log types.Log) (*BitcoinStateLogNamedUint, error) { - event := new(BitcoinStateLogNamedUint) - if err := _BitcoinState.contract.UnpackLog(event, "log_named_uint", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogStringIterator is returned from FilterLogString and is used to iterate over the raw logs and unpacked data for LogString events raised by the BitcoinState contract. -type BitcoinStateLogStringIterator struct { - Event *BitcoinStateLogString // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogStringIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogString) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogString) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogStringIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogStringIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogString represents a LogString event raised by the BitcoinState contract. -type BitcoinStateLogString struct { - Arg0 string - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogString is a free log retrieval operation binding the contract event 0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b. -// -// Solidity: event log_string(string arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLogString(opts *bind.FilterOpts) (*BitcoinStateLogStringIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_string") - if err != nil { - return nil, err - } - return &BitcoinStateLogStringIterator{contract: _BitcoinState.contract, event: "log_string", logs: logs, sub: sub}, nil -} - -// WatchLogString is a free log subscription operation binding the contract event 0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b. -// -// Solidity: event log_string(string arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLogString(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogString) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_string") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogString) - if err := _BitcoinState.contract.UnpackLog(event, "log_string", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogString is a log parse operation binding the contract event 0x0b2e13ff20ac7b474198655583edf70dedd2c1dc980e329c4fbb2fc0748b796b. -// -// Solidity: event log_string(string arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLogString(log types.Log) (*BitcoinStateLogString, error) { - event := new(BitcoinStateLogString) - if err := _BitcoinState.contract.UnpackLog(event, "log_string", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogUintIterator is returned from FilterLogUint and is used to iterate over the raw logs and unpacked data for LogUint events raised by the BitcoinState contract. -type BitcoinStateLogUintIterator struct { - Event *BitcoinStateLogUint // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogUintIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogUint) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogUint) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogUintIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogUintIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogUint represents a LogUint event raised by the BitcoinState contract. -type BitcoinStateLogUint struct { - Arg0 *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogUint is a free log retrieval operation binding the contract event 0x2cab9790510fd8bdfbd2115288db33fec66691d476efc5427cfd4c0969301755. -// -// Solidity: event log_uint(uint256 arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLogUint(opts *bind.FilterOpts) (*BitcoinStateLogUintIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "log_uint") - if err != nil { - return nil, err - } - return &BitcoinStateLogUintIterator{contract: _BitcoinState.contract, event: "log_uint", logs: logs, sub: sub}, nil -} - -// WatchLogUint is a free log subscription operation binding the contract event 0x2cab9790510fd8bdfbd2115288db33fec66691d476efc5427cfd4c0969301755. -// -// Solidity: event log_uint(uint256 arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLogUint(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogUint) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "log_uint") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogUint) - if err := _BitcoinState.contract.UnpackLog(event, "log_uint", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogUint is a log parse operation binding the contract event 0x2cab9790510fd8bdfbd2115288db33fec66691d476efc5427cfd4c0969301755. -// -// Solidity: event log_uint(uint256 arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLogUint(log types.Log) (*BitcoinStateLogUint, error) { - event := new(BitcoinStateLogUint) - if err := _BitcoinState.contract.UnpackLog(event, "log_uint", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// BitcoinStateLogsIterator is returned from FilterLogs and is used to iterate over the raw logs and unpacked data for Logs events raised by the BitcoinState contract. -type BitcoinStateLogsIterator struct { - Event *BitcoinStateLogs // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *BitcoinStateLogsIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogs) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(BitcoinStateLogs) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *BitcoinStateLogsIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *BitcoinStateLogsIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// BitcoinStateLogs represents a Logs event raised by the BitcoinState contract. -type BitcoinStateLogs struct { - Arg0 []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterLogs is a free log retrieval operation binding the contract event 0xe7950ede0394b9f2ce4a5a1bf5a7e1852411f7e6661b4308c913c4bfd11027e4. -// -// Solidity: event logs(bytes arg0) -func (_BitcoinState *BitcoinStateFilterer) FilterLogs(opts *bind.FilterOpts) (*BitcoinStateLogsIterator, error) { - - logs, sub, err := _BitcoinState.contract.FilterLogs(opts, "logs") - if err != nil { - return nil, err - } - return &BitcoinStateLogsIterator{contract: _BitcoinState.contract, event: "logs", logs: logs, sub: sub}, nil -} - -// WatchLogs is a free log subscription operation binding the contract event 0xe7950ede0394b9f2ce4a5a1bf5a7e1852411f7e6661b4308c913c4bfd11027e4. -// -// Solidity: event logs(bytes arg0) -func (_BitcoinState *BitcoinStateFilterer) WatchLogs(opts *bind.WatchOpts, sink chan<- *BitcoinStateLogs) (event.Subscription, error) { - - logs, sub, err := _BitcoinState.contract.WatchLogs(opts, "logs") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(BitcoinStateLogs) - if err := _BitcoinState.contract.UnpackLog(event, "logs", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseLogs is a log parse operation binding the contract event 0xe7950ede0394b9f2ce4a5a1bf5a7e1852411f7e6661b4308c913c4bfd11027e4. -// -// Solidity: event logs(bytes arg0) -func (_BitcoinState *BitcoinStateFilterer) ParseLogs(log types.Log) (*BitcoinStateLogs, error) { - event := new(BitcoinStateLogs) - if err := _BitcoinState.contract.UnpackLog(event, "logs", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/chains/bitcoin/abi/icall_service.go b/relayer/chains/bitcoin/abi/icall_service.go deleted file mode 100644 index 13735784..00000000 --- a/relayer/chains/bitcoin/abi/icall_service.go +++ /dev/null @@ -1,1814 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package abi - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "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/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// CallServiceMetaData contains all meta data concerning the CallService contract. -var CallServiceMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"admin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"executeCall\",\"inputs\":[{\"name\":\"_reqId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executeMessage\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"protocols\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"executeRollback\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"getDefaultConnection\",\"inputs\":[{\"name\":\"_nid\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"_net\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_rollback\",\"type\":\"bool\",\"internalType\":\"bool\"},{\"name\":\"_sources\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"_net\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_rollback\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNetworkAddress\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getNetworkId\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getProtocolFee\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getProtocolFeeHandler\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"handleBTPError\",\"inputs\":[{\"name\":\"_src\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_svc\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_code\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleBTPMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_svc\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleError\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"handleMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_nid\",\"type\":\"string\",\"internalType\":\"string\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendCall\",\"inputs\":[{\"name\":\"_to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"sendCallMessage\",\"inputs\":[{\"name\":\"_to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_rollback\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"sendCallMessage\",\"inputs\":[{\"name\":\"_to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_data\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"_rollback\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"sources\",\"type\":\"string[]\",\"internalType\":\"string[]\"},{\"name\":\"destinations\",\"type\":\"string[]\",\"internalType\":\"string[]\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"setAdmin\",\"inputs\":[{\"name\":\"_address\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setDefaultConnection\",\"inputs\":[{\"name\":\"_nid\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"connection\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setProtocolFee\",\"inputs\":[{\"name\":\"_value\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setProtocolFeeHandler\",\"inputs\":[{\"name\":\"_addr\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"verifySuccess\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"event\",\"name\":\"CallExecuted\",\"inputs\":[{\"name\":\"_reqId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"_code\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"},{\"name\":\"_msg\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CallMessage\",\"inputs\":[{\"name\":\"_from\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"_to\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"_reqId\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"_data\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"CallMessageSent\",\"inputs\":[{\"name\":\"_from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"_to\",\"type\":\"string\",\"indexed\":true,\"internalType\":\"string\"},{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ResponseMessage\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"_code\",\"type\":\"int256\",\"indexed\":false,\"internalType\":\"int256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RollbackExecuted\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"RollbackMessage\",\"inputs\":[{\"name\":\"_sn\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]}]", -} - -// CallServiceABI is the input ABI used to generate the binding from. -// Deprecated: Use CallServiceMetaData.ABI instead. -var CallServiceABI = CallServiceMetaData.ABI - -// CallService is an auto generated Go binding around an Ethereum contract. -type CallService struct { - CallServiceCaller // Read-only binding to the contract - CallServiceTransactor // Write-only binding to the contract - CallServiceFilterer // Log filterer for contract events -} - -// CallServiceCaller is an auto generated read-only Go binding around an Ethereum contract. -type CallServiceCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// CallServiceTransactor is an auto generated write-only Go binding around an Ethereum contract. -type CallServiceTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// CallServiceFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type CallServiceFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// CallServiceSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type CallServiceSession struct { - Contract *CallService // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// CallServiceCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type CallServiceCallerSession struct { - Contract *CallServiceCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// CallServiceTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type CallServiceTransactorSession struct { - Contract *CallServiceTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// CallServiceRaw is an auto generated low-level Go binding around an Ethereum contract. -type CallServiceRaw struct { - Contract *CallService // Generic contract binding to access the raw methods on -} - -// CallServiceCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type CallServiceCallerRaw struct { - Contract *CallServiceCaller // Generic read-only contract binding to access the raw methods on -} - -// CallServiceTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type CallServiceTransactorRaw struct { - Contract *CallServiceTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewCallService creates a new instance of CallService, bound to a specific deployed contract. -func NewCallService(address common.Address, backend bind.ContractBackend) (*CallService, error) { - contract, err := bindCallService(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &CallService{CallServiceCaller: CallServiceCaller{contract: contract}, CallServiceTransactor: CallServiceTransactor{contract: contract}, CallServiceFilterer: CallServiceFilterer{contract: contract}}, nil -} - -// NewCallServiceCaller creates a new read-only instance of CallService, bound to a specific deployed contract. -func NewCallServiceCaller(address common.Address, caller bind.ContractCaller) (*CallServiceCaller, error) { - contract, err := bindCallService(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &CallServiceCaller{contract: contract}, nil -} - -// NewCallServiceTransactor creates a new write-only instance of CallService, bound to a specific deployed contract. -func NewCallServiceTransactor(address common.Address, transactor bind.ContractTransactor) (*CallServiceTransactor, error) { - contract, err := bindCallService(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &CallServiceTransactor{contract: contract}, nil -} - -// NewCallServiceFilterer creates a new log filterer instance of CallService, bound to a specific deployed contract. -func NewCallServiceFilterer(address common.Address, filterer bind.ContractFilterer) (*CallServiceFilterer, error) { - contract, err := bindCallService(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &CallServiceFilterer{contract: contract}, nil -} - -// bindCallService binds a generic wrapper to an already deployed contract. -func bindCallService(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := CallServiceMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_CallService *CallServiceRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CallService.Contract.CallServiceCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_CallService *CallServiceRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CallService.Contract.CallServiceTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_CallService *CallServiceRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CallService.Contract.CallServiceTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_CallService *CallServiceCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CallService.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_CallService *CallServiceTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CallService.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_CallService *CallServiceTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CallService.Contract.contract.Transact(opts, method, params...) -} - -// Admin is a free data retrieval call binding the contract method 0xf851a440. -// -// Solidity: function admin() view returns(address) -func (_CallService *CallServiceCaller) Admin(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "admin") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Admin is a free data retrieval call binding the contract method 0xf851a440. -// -// Solidity: function admin() view returns(address) -func (_CallService *CallServiceSession) Admin() (common.Address, error) { - return _CallService.Contract.Admin(&_CallService.CallOpts) -} - -// Admin is a free data retrieval call binding the contract method 0xf851a440. -// -// Solidity: function admin() view returns(address) -func (_CallService *CallServiceCallerSession) Admin() (common.Address, error) { - return _CallService.Contract.Admin(&_CallService.CallOpts) -} - -// GetDefaultConnection is a free data retrieval call binding the contract method 0x9e553a4f. -// -// Solidity: function getDefaultConnection(string _nid) view returns(address) -func (_CallService *CallServiceCaller) GetDefaultConnection(opts *bind.CallOpts, _nid string) (common.Address, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "getDefaultConnection", _nid) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GetDefaultConnection is a free data retrieval call binding the contract method 0x9e553a4f. -// -// Solidity: function getDefaultConnection(string _nid) view returns(address) -func (_CallService *CallServiceSession) GetDefaultConnection(_nid string) (common.Address, error) { - return _CallService.Contract.GetDefaultConnection(&_CallService.CallOpts, _nid) -} - -// GetDefaultConnection is a free data retrieval call binding the contract method 0x9e553a4f. -// -// Solidity: function getDefaultConnection(string _nid) view returns(address) -func (_CallService *CallServiceCallerSession) GetDefaultConnection(_nid string) (common.Address, error) { - return _CallService.Contract.GetDefaultConnection(&_CallService.CallOpts, _nid) -} - -// GetFee is a free data retrieval call binding the contract method 0x304a70b5. -// -// Solidity: function getFee(string _net, bool _rollback, string[] _sources) view returns(uint256) -func (_CallService *CallServiceCaller) GetFee(opts *bind.CallOpts, _net string, _rollback bool, _sources []string) (*big.Int, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "getFee", _net, _rollback, _sources) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetFee is a free data retrieval call binding the contract method 0x304a70b5. -// -// Solidity: function getFee(string _net, bool _rollback, string[] _sources) view returns(uint256) -func (_CallService *CallServiceSession) GetFee(_net string, _rollback bool, _sources []string) (*big.Int, error) { - return _CallService.Contract.GetFee(&_CallService.CallOpts, _net, _rollback, _sources) -} - -// GetFee is a free data retrieval call binding the contract method 0x304a70b5. -// -// Solidity: function getFee(string _net, bool _rollback, string[] _sources) view returns(uint256) -func (_CallService *CallServiceCallerSession) GetFee(_net string, _rollback bool, _sources []string) (*big.Int, error) { - return _CallService.Contract.GetFee(&_CallService.CallOpts, _net, _rollback, _sources) -} - -// GetFee0 is a free data retrieval call binding the contract method 0x7d4c4f4a. -// -// Solidity: function getFee(string _net, bool _rollback) view returns(uint256) -func (_CallService *CallServiceCaller) GetFee0(opts *bind.CallOpts, _net string, _rollback bool) (*big.Int, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "getFee0", _net, _rollback) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetFee0 is a free data retrieval call binding the contract method 0x7d4c4f4a. -// -// Solidity: function getFee(string _net, bool _rollback) view returns(uint256) -func (_CallService *CallServiceSession) GetFee0(_net string, _rollback bool) (*big.Int, error) { - return _CallService.Contract.GetFee0(&_CallService.CallOpts, _net, _rollback) -} - -// GetFee0 is a free data retrieval call binding the contract method 0x7d4c4f4a. -// -// Solidity: function getFee(string _net, bool _rollback) view returns(uint256) -func (_CallService *CallServiceCallerSession) GetFee0(_net string, _rollback bool) (*big.Int, error) { - return _CallService.Contract.GetFee0(&_CallService.CallOpts, _net, _rollback) -} - -// GetNetworkAddress is a free data retrieval call binding the contract method 0x6bf459cb. -// -// Solidity: function getNetworkAddress() view returns(string) -func (_CallService *CallServiceCaller) GetNetworkAddress(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "getNetworkAddress") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// GetNetworkAddress is a free data retrieval call binding the contract method 0x6bf459cb. -// -// Solidity: function getNetworkAddress() view returns(string) -func (_CallService *CallServiceSession) GetNetworkAddress() (string, error) { - return _CallService.Contract.GetNetworkAddress(&_CallService.CallOpts) -} - -// GetNetworkAddress is a free data retrieval call binding the contract method 0x6bf459cb. -// -// Solidity: function getNetworkAddress() view returns(string) -func (_CallService *CallServiceCallerSession) GetNetworkAddress() (string, error) { - return _CallService.Contract.GetNetworkAddress(&_CallService.CallOpts) -} - -// GetNetworkId is a free data retrieval call binding the contract method 0x39c5f3fc. -// -// Solidity: function getNetworkId() view returns(string) -func (_CallService *CallServiceCaller) GetNetworkId(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "getNetworkId") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// GetNetworkId is a free data retrieval call binding the contract method 0x39c5f3fc. -// -// Solidity: function getNetworkId() view returns(string) -func (_CallService *CallServiceSession) GetNetworkId() (string, error) { - return _CallService.Contract.GetNetworkId(&_CallService.CallOpts) -} - -// GetNetworkId is a free data retrieval call binding the contract method 0x39c5f3fc. -// -// Solidity: function getNetworkId() view returns(string) -func (_CallService *CallServiceCallerSession) GetNetworkId() (string, error) { - return _CallService.Contract.GetNetworkId(&_CallService.CallOpts) -} - -// GetProtocolFee is a free data retrieval call binding the contract method 0xa5a41031. -// -// Solidity: function getProtocolFee() view returns(uint256) -func (_CallService *CallServiceCaller) GetProtocolFee(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "getProtocolFee") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetProtocolFee is a free data retrieval call binding the contract method 0xa5a41031. -// -// Solidity: function getProtocolFee() view returns(uint256) -func (_CallService *CallServiceSession) GetProtocolFee() (*big.Int, error) { - return _CallService.Contract.GetProtocolFee(&_CallService.CallOpts) -} - -// GetProtocolFee is a free data retrieval call binding the contract method 0xa5a41031. -// -// Solidity: function getProtocolFee() view returns(uint256) -func (_CallService *CallServiceCallerSession) GetProtocolFee() (*big.Int, error) { - return _CallService.Contract.GetProtocolFee(&_CallService.CallOpts) -} - -// GetProtocolFeeHandler is a free data retrieval call binding the contract method 0x2eb71414. -// -// Solidity: function getProtocolFeeHandler() view returns(address) -func (_CallService *CallServiceCaller) GetProtocolFeeHandler(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "getProtocolFeeHandler") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GetProtocolFeeHandler is a free data retrieval call binding the contract method 0x2eb71414. -// -// Solidity: function getProtocolFeeHandler() view returns(address) -func (_CallService *CallServiceSession) GetProtocolFeeHandler() (common.Address, error) { - return _CallService.Contract.GetProtocolFeeHandler(&_CallService.CallOpts) -} - -// GetProtocolFeeHandler is a free data retrieval call binding the contract method 0x2eb71414. -// -// Solidity: function getProtocolFeeHandler() view returns(address) -func (_CallService *CallServiceCallerSession) GetProtocolFeeHandler() (common.Address, error) { - return _CallService.Contract.GetProtocolFeeHandler(&_CallService.CallOpts) -} - -// VerifySuccess is a free data retrieval call binding the contract method 0xec05386b. -// -// Solidity: function verifySuccess(uint256 _sn) view returns(bool) -func (_CallService *CallServiceCaller) VerifySuccess(opts *bind.CallOpts, _sn *big.Int) (bool, error) { - var out []interface{} - err := _CallService.contract.Call(opts, &out, "verifySuccess", _sn) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// VerifySuccess is a free data retrieval call binding the contract method 0xec05386b. -// -// Solidity: function verifySuccess(uint256 _sn) view returns(bool) -func (_CallService *CallServiceSession) VerifySuccess(_sn *big.Int) (bool, error) { - return _CallService.Contract.VerifySuccess(&_CallService.CallOpts, _sn) -} - -// VerifySuccess is a free data retrieval call binding the contract method 0xec05386b. -// -// Solidity: function verifySuccess(uint256 _sn) view returns(bool) -func (_CallService *CallServiceCallerSession) VerifySuccess(_sn *big.Int) (bool, error) { - return _CallService.Contract.VerifySuccess(&_CallService.CallOpts, _sn) -} - -// ExecuteCall is a paid mutator transaction binding the contract method 0xbda8ce21. -// -// Solidity: function executeCall(uint256 _reqId, bytes _data) returns() -func (_CallService *CallServiceTransactor) ExecuteCall(opts *bind.TransactOpts, _reqId *big.Int, _data []byte) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "executeCall", _reqId, _data) -} - -// ExecuteCall is a paid mutator transaction binding the contract method 0xbda8ce21. -// -// Solidity: function executeCall(uint256 _reqId, bytes _data) returns() -func (_CallService *CallServiceSession) ExecuteCall(_reqId *big.Int, _data []byte) (*types.Transaction, error) { - return _CallService.Contract.ExecuteCall(&_CallService.TransactOpts, _reqId, _data) -} - -// ExecuteCall is a paid mutator transaction binding the contract method 0xbda8ce21. -// -// Solidity: function executeCall(uint256 _reqId, bytes _data) returns() -func (_CallService *CallServiceTransactorSession) ExecuteCall(_reqId *big.Int, _data []byte) (*types.Transaction, error) { - return _CallService.Contract.ExecuteCall(&_CallService.TransactOpts, _reqId, _data) -} - -// ExecuteMessage is a paid mutator transaction binding the contract method 0x313bf398. -// -// Solidity: function executeMessage(address to, string from, bytes data, string[] protocols) returns() -func (_CallService *CallServiceTransactor) ExecuteMessage(opts *bind.TransactOpts, to common.Address, from string, data []byte, protocols []string) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "executeMessage", to, from, data, protocols) -} - -// ExecuteMessage is a paid mutator transaction binding the contract method 0x313bf398. -// -// Solidity: function executeMessage(address to, string from, bytes data, string[] protocols) returns() -func (_CallService *CallServiceSession) ExecuteMessage(to common.Address, from string, data []byte, protocols []string) (*types.Transaction, error) { - return _CallService.Contract.ExecuteMessage(&_CallService.TransactOpts, to, from, data, protocols) -} - -// ExecuteMessage is a paid mutator transaction binding the contract method 0x313bf398. -// -// Solidity: function executeMessage(address to, string from, bytes data, string[] protocols) returns() -func (_CallService *CallServiceTransactorSession) ExecuteMessage(to common.Address, from string, data []byte, protocols []string) (*types.Transaction, error) { - return _CallService.Contract.ExecuteMessage(&_CallService.TransactOpts, to, from, data, protocols) -} - -// ExecuteRollback is a paid mutator transaction binding the contract method 0x2a84e1b0. -// -// Solidity: function executeRollback(uint256 _sn) returns() -func (_CallService *CallServiceTransactor) ExecuteRollback(opts *bind.TransactOpts, _sn *big.Int) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "executeRollback", _sn) -} - -// ExecuteRollback is a paid mutator transaction binding the contract method 0x2a84e1b0. -// -// Solidity: function executeRollback(uint256 _sn) returns() -func (_CallService *CallServiceSession) ExecuteRollback(_sn *big.Int) (*types.Transaction, error) { - return _CallService.Contract.ExecuteRollback(&_CallService.TransactOpts, _sn) -} - -// ExecuteRollback is a paid mutator transaction binding the contract method 0x2a84e1b0. -// -// Solidity: function executeRollback(uint256 _sn) returns() -func (_CallService *CallServiceTransactorSession) ExecuteRollback(_sn *big.Int) (*types.Transaction, error) { - return _CallService.Contract.ExecuteRollback(&_CallService.TransactOpts, _sn) -} - -// HandleBTPError is a paid mutator transaction binding the contract method 0x0a823dea. -// -// Solidity: function handleBTPError(string _src, string _svc, uint256 _sn, uint256 _code, string _msg) returns() -func (_CallService *CallServiceTransactor) HandleBTPError(opts *bind.TransactOpts, _src string, _svc string, _sn *big.Int, _code *big.Int, _msg string) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "handleBTPError", _src, _svc, _sn, _code, _msg) -} - -// HandleBTPError is a paid mutator transaction binding the contract method 0x0a823dea. -// -// Solidity: function handleBTPError(string _src, string _svc, uint256 _sn, uint256 _code, string _msg) returns() -func (_CallService *CallServiceSession) HandleBTPError(_src string, _svc string, _sn *big.Int, _code *big.Int, _msg string) (*types.Transaction, error) { - return _CallService.Contract.HandleBTPError(&_CallService.TransactOpts, _src, _svc, _sn, _code, _msg) -} - -// HandleBTPError is a paid mutator transaction binding the contract method 0x0a823dea. -// -// Solidity: function handleBTPError(string _src, string _svc, uint256 _sn, uint256 _code, string _msg) returns() -func (_CallService *CallServiceTransactorSession) HandleBTPError(_src string, _svc string, _sn *big.Int, _code *big.Int, _msg string) (*types.Transaction, error) { - return _CallService.Contract.HandleBTPError(&_CallService.TransactOpts, _src, _svc, _sn, _code, _msg) -} - -// HandleBTPMessage is a paid mutator transaction binding the contract method 0xb70eeb8d. -// -// Solidity: function handleBTPMessage(string _from, string _svc, uint256 _sn, bytes _msg) returns() -func (_CallService *CallServiceTransactor) HandleBTPMessage(opts *bind.TransactOpts, _from string, _svc string, _sn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "handleBTPMessage", _from, _svc, _sn, _msg) -} - -// HandleBTPMessage is a paid mutator transaction binding the contract method 0xb70eeb8d. -// -// Solidity: function handleBTPMessage(string _from, string _svc, uint256 _sn, bytes _msg) returns() -func (_CallService *CallServiceSession) HandleBTPMessage(_from string, _svc string, _sn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CallService.Contract.HandleBTPMessage(&_CallService.TransactOpts, _from, _svc, _sn, _msg) -} - -// HandleBTPMessage is a paid mutator transaction binding the contract method 0xb70eeb8d. -// -// Solidity: function handleBTPMessage(string _from, string _svc, uint256 _sn, bytes _msg) returns() -func (_CallService *CallServiceTransactorSession) HandleBTPMessage(_from string, _svc string, _sn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CallService.Contract.HandleBTPMessage(&_CallService.TransactOpts, _from, _svc, _sn, _msg) -} - -// HandleError is a paid mutator transaction binding the contract method 0xb070f9e5. -// -// Solidity: function handleError(uint256 _sn) returns() -func (_CallService *CallServiceTransactor) HandleError(opts *bind.TransactOpts, _sn *big.Int) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "handleError", _sn) -} - -// HandleError is a paid mutator transaction binding the contract method 0xb070f9e5. -// -// Solidity: function handleError(uint256 _sn) returns() -func (_CallService *CallServiceSession) HandleError(_sn *big.Int) (*types.Transaction, error) { - return _CallService.Contract.HandleError(&_CallService.TransactOpts, _sn) -} - -// HandleError is a paid mutator transaction binding the contract method 0xb070f9e5. -// -// Solidity: function handleError(uint256 _sn) returns() -func (_CallService *CallServiceTransactorSession) HandleError(_sn *big.Int) (*types.Transaction, error) { - return _CallService.Contract.HandleError(&_CallService.TransactOpts, _sn) -} - -// HandleMessage is a paid mutator transaction binding the contract method 0xbbc22efd. -// -// Solidity: function handleMessage(string _from, bytes _msg) returns() -func (_CallService *CallServiceTransactor) HandleMessage(opts *bind.TransactOpts, _from string, _msg []byte) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "handleMessage", _from, _msg) -} - -// HandleMessage is a paid mutator transaction binding the contract method 0xbbc22efd. -// -// Solidity: function handleMessage(string _from, bytes _msg) returns() -func (_CallService *CallServiceSession) HandleMessage(_from string, _msg []byte) (*types.Transaction, error) { - return _CallService.Contract.HandleMessage(&_CallService.TransactOpts, _from, _msg) -} - -// HandleMessage is a paid mutator transaction binding the contract method 0xbbc22efd. -// -// Solidity: function handleMessage(string _from, bytes _msg) returns() -func (_CallService *CallServiceTransactorSession) HandleMessage(_from string, _msg []byte) (*types.Transaction, error) { - return _CallService.Contract.HandleMessage(&_CallService.TransactOpts, _from, _msg) -} - -// Initialize is a paid mutator transaction binding the contract method 0xf62d1888. -// -// Solidity: function initialize(string _nid) returns() -func (_CallService *CallServiceTransactor) Initialize(opts *bind.TransactOpts, _nid string) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "initialize", _nid) -} - -// Initialize is a paid mutator transaction binding the contract method 0xf62d1888. -// -// Solidity: function initialize(string _nid) returns() -func (_CallService *CallServiceSession) Initialize(_nid string) (*types.Transaction, error) { - return _CallService.Contract.Initialize(&_CallService.TransactOpts, _nid) -} - -// Initialize is a paid mutator transaction binding the contract method 0xf62d1888. -// -// Solidity: function initialize(string _nid) returns() -func (_CallService *CallServiceTransactorSession) Initialize(_nid string) (*types.Transaction, error) { - return _CallService.Contract.Initialize(&_CallService.TransactOpts, _nid) -} - -// SendCall is a paid mutator transaction binding the contract method 0x17fd7a33. -// -// Solidity: function sendCall(string _to, bytes _data) payable returns(uint256) -func (_CallService *CallServiceTransactor) SendCall(opts *bind.TransactOpts, _to string, _data []byte) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "sendCall", _to, _data) -} - -// SendCall is a paid mutator transaction binding the contract method 0x17fd7a33. -// -// Solidity: function sendCall(string _to, bytes _data) payable returns(uint256) -func (_CallService *CallServiceSession) SendCall(_to string, _data []byte) (*types.Transaction, error) { - return _CallService.Contract.SendCall(&_CallService.TransactOpts, _to, _data) -} - -// SendCall is a paid mutator transaction binding the contract method 0x17fd7a33. -// -// Solidity: function sendCall(string _to, bytes _data) payable returns(uint256) -func (_CallService *CallServiceTransactorSession) SendCall(_to string, _data []byte) (*types.Transaction, error) { - return _CallService.Contract.SendCall(&_CallService.TransactOpts, _to, _data) -} - -// SendCallMessage is a paid mutator transaction binding the contract method 0x8ef378b8. -// -// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback) payable returns(uint256) -func (_CallService *CallServiceTransactor) SendCallMessage(opts *bind.TransactOpts, _to string, _data []byte, _rollback []byte) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "sendCallMessage", _to, _data, _rollback) -} - -// SendCallMessage is a paid mutator transaction binding the contract method 0x8ef378b8. -// -// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback) payable returns(uint256) -func (_CallService *CallServiceSession) SendCallMessage(_to string, _data []byte, _rollback []byte) (*types.Transaction, error) { - return _CallService.Contract.SendCallMessage(&_CallService.TransactOpts, _to, _data, _rollback) -} - -// SendCallMessage is a paid mutator transaction binding the contract method 0x8ef378b8. -// -// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback) payable returns(uint256) -func (_CallService *CallServiceTransactorSession) SendCallMessage(_to string, _data []byte, _rollback []byte) (*types.Transaction, error) { - return _CallService.Contract.SendCallMessage(&_CallService.TransactOpts, _to, _data, _rollback) -} - -// SendCallMessage0 is a paid mutator transaction binding the contract method 0xedc6afff. -// -// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback, string[] sources, string[] destinations) payable returns(uint256) -func (_CallService *CallServiceTransactor) SendCallMessage0(opts *bind.TransactOpts, _to string, _data []byte, _rollback []byte, sources []string, destinations []string) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "sendCallMessage0", _to, _data, _rollback, sources, destinations) -} - -// SendCallMessage0 is a paid mutator transaction binding the contract method 0xedc6afff. -// -// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback, string[] sources, string[] destinations) payable returns(uint256) -func (_CallService *CallServiceSession) SendCallMessage0(_to string, _data []byte, _rollback []byte, sources []string, destinations []string) (*types.Transaction, error) { - return _CallService.Contract.SendCallMessage0(&_CallService.TransactOpts, _to, _data, _rollback, sources, destinations) -} - -// SendCallMessage0 is a paid mutator transaction binding the contract method 0xedc6afff. -// -// Solidity: function sendCallMessage(string _to, bytes _data, bytes _rollback, string[] sources, string[] destinations) payable returns(uint256) -func (_CallService *CallServiceTransactorSession) SendCallMessage0(_to string, _data []byte, _rollback []byte, sources []string, destinations []string) (*types.Transaction, error) { - return _CallService.Contract.SendCallMessage0(&_CallService.TransactOpts, _to, _data, _rollback, sources, destinations) -} - -// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. -// -// Solidity: function setAdmin(address _address) returns() -func (_CallService *CallServiceTransactor) SetAdmin(opts *bind.TransactOpts, _address common.Address) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "setAdmin", _address) -} - -// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. -// -// Solidity: function setAdmin(address _address) returns() -func (_CallService *CallServiceSession) SetAdmin(_address common.Address) (*types.Transaction, error) { - return _CallService.Contract.SetAdmin(&_CallService.TransactOpts, _address) -} - -// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. -// -// Solidity: function setAdmin(address _address) returns() -func (_CallService *CallServiceTransactorSession) SetAdmin(_address common.Address) (*types.Transaction, error) { - return _CallService.Contract.SetAdmin(&_CallService.TransactOpts, _address) -} - -// SetDefaultConnection is a paid mutator transaction binding the contract method 0x64f03757. -// -// Solidity: function setDefaultConnection(string _nid, address connection) returns() -func (_CallService *CallServiceTransactor) SetDefaultConnection(opts *bind.TransactOpts, _nid string, connection common.Address) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "setDefaultConnection", _nid, connection) -} - -// SetDefaultConnection is a paid mutator transaction binding the contract method 0x64f03757. -// -// Solidity: function setDefaultConnection(string _nid, address connection) returns() -func (_CallService *CallServiceSession) SetDefaultConnection(_nid string, connection common.Address) (*types.Transaction, error) { - return _CallService.Contract.SetDefaultConnection(&_CallService.TransactOpts, _nid, connection) -} - -// SetDefaultConnection is a paid mutator transaction binding the contract method 0x64f03757. -// -// Solidity: function setDefaultConnection(string _nid, address connection) returns() -func (_CallService *CallServiceTransactorSession) SetDefaultConnection(_nid string, connection common.Address) (*types.Transaction, error) { - return _CallService.Contract.SetDefaultConnection(&_CallService.TransactOpts, _nid, connection) -} - -// SetProtocolFee is a paid mutator transaction binding the contract method 0x787dce3d. -// -// Solidity: function setProtocolFee(uint256 _value) returns() -func (_CallService *CallServiceTransactor) SetProtocolFee(opts *bind.TransactOpts, _value *big.Int) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "setProtocolFee", _value) -} - -// SetProtocolFee is a paid mutator transaction binding the contract method 0x787dce3d. -// -// Solidity: function setProtocolFee(uint256 _value) returns() -func (_CallService *CallServiceSession) SetProtocolFee(_value *big.Int) (*types.Transaction, error) { - return _CallService.Contract.SetProtocolFee(&_CallService.TransactOpts, _value) -} - -// SetProtocolFee is a paid mutator transaction binding the contract method 0x787dce3d. -// -// Solidity: function setProtocolFee(uint256 _value) returns() -func (_CallService *CallServiceTransactorSession) SetProtocolFee(_value *big.Int) (*types.Transaction, error) { - return _CallService.Contract.SetProtocolFee(&_CallService.TransactOpts, _value) -} - -// SetProtocolFeeHandler is a paid mutator transaction binding the contract method 0x502bf8e0. -// -// Solidity: function setProtocolFeeHandler(address _addr) returns() -func (_CallService *CallServiceTransactor) SetProtocolFeeHandler(opts *bind.TransactOpts, _addr common.Address) (*types.Transaction, error) { - return _CallService.contract.Transact(opts, "setProtocolFeeHandler", _addr) -} - -// SetProtocolFeeHandler is a paid mutator transaction binding the contract method 0x502bf8e0. -// -// Solidity: function setProtocolFeeHandler(address _addr) returns() -func (_CallService *CallServiceSession) SetProtocolFeeHandler(_addr common.Address) (*types.Transaction, error) { - return _CallService.Contract.SetProtocolFeeHandler(&_CallService.TransactOpts, _addr) -} - -// SetProtocolFeeHandler is a paid mutator transaction binding the contract method 0x502bf8e0. -// -// Solidity: function setProtocolFeeHandler(address _addr) returns() -func (_CallService *CallServiceTransactorSession) SetProtocolFeeHandler(_addr common.Address) (*types.Transaction, error) { - return _CallService.Contract.SetProtocolFeeHandler(&_CallService.TransactOpts, _addr) -} - -// CallServiceCallExecutedIterator is returned from FilterCallExecuted and is used to iterate over the raw logs and unpacked data for CallExecuted events raised by the CallService contract. -type CallServiceCallExecutedIterator struct { - Event *CallServiceCallExecuted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CallServiceCallExecutedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CallServiceCallExecuted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CallServiceCallExecuted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CallServiceCallExecutedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CallServiceCallExecutedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CallServiceCallExecuted represents a CallExecuted event raised by the CallService contract. -type CallServiceCallExecuted struct { - ReqId *big.Int - Code *big.Int - Msg string - Raw types.Log // Blockchain specific contextual infos -} - -// FilterCallExecuted is a free log retrieval operation binding the contract event 0xc7391e04887f8b3c16fa20877e028e8163139a478c8447e7d449eba1905caa51. -// -// Solidity: event CallExecuted(uint256 indexed _reqId, int256 _code, string _msg) -func (_CallService *CallServiceFilterer) FilterCallExecuted(opts *bind.FilterOpts, _reqId []*big.Int) (*CallServiceCallExecutedIterator, error) { - - var _reqIdRule []interface{} - for _, _reqIdItem := range _reqId { - _reqIdRule = append(_reqIdRule, _reqIdItem) - } - - logs, sub, err := _CallService.contract.FilterLogs(opts, "CallExecuted", _reqIdRule) - if err != nil { - return nil, err - } - return &CallServiceCallExecutedIterator{contract: _CallService.contract, event: "CallExecuted", logs: logs, sub: sub}, nil -} - -// WatchCallExecuted is a free log subscription operation binding the contract event 0xc7391e04887f8b3c16fa20877e028e8163139a478c8447e7d449eba1905caa51. -// -// Solidity: event CallExecuted(uint256 indexed _reqId, int256 _code, string _msg) -func (_CallService *CallServiceFilterer) WatchCallExecuted(opts *bind.WatchOpts, sink chan<- *CallServiceCallExecuted, _reqId []*big.Int) (event.Subscription, error) { - - var _reqIdRule []interface{} - for _, _reqIdItem := range _reqId { - _reqIdRule = append(_reqIdRule, _reqIdItem) - } - - logs, sub, err := _CallService.contract.WatchLogs(opts, "CallExecuted", _reqIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CallServiceCallExecuted) - if err := _CallService.contract.UnpackLog(event, "CallExecuted", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseCallExecuted is a log parse operation binding the contract event 0xc7391e04887f8b3c16fa20877e028e8163139a478c8447e7d449eba1905caa51. -// -// Solidity: event CallExecuted(uint256 indexed _reqId, int256 _code, string _msg) -func (_CallService *CallServiceFilterer) ParseCallExecuted(log types.Log) (*CallServiceCallExecuted, error) { - event := new(CallServiceCallExecuted) - if err := _CallService.contract.UnpackLog(event, "CallExecuted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// CallServiceCallMessageIterator is returned from FilterCallMessage and is used to iterate over the raw logs and unpacked data for CallMessage events raised by the CallService contract. -type CallServiceCallMessageIterator struct { - Event *CallServiceCallMessage // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CallServiceCallMessageIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CallServiceCallMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CallServiceCallMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CallServiceCallMessageIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CallServiceCallMessageIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CallServiceCallMessage represents a CallMessage event raised by the CallService contract. -type CallServiceCallMessage struct { - From common.Hash - To common.Hash - Sn *big.Int - ReqId *big.Int - Data []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterCallMessage is a free log retrieval operation binding the contract event 0x2cbc78425621c181f9f8a25fc06e44a0ac2b67cd6a31f8ed7918934187f8cc59. -// -// Solidity: event CallMessage(string indexed _from, string indexed _to, uint256 indexed _sn, uint256 _reqId, bytes _data) -func (_CallService *CallServiceFilterer) FilterCallMessage(opts *bind.FilterOpts, _from []string, _to []string, _sn []*big.Int) (*CallServiceCallMessageIterator, error) { - - var _fromRule []interface{} - for _, _fromItem := range _from { - _fromRule = append(_fromRule, _fromItem) - } - var _toRule []interface{} - for _, _toItem := range _to { - _toRule = append(_toRule, _toItem) - } - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.FilterLogs(opts, "CallMessage", _fromRule, _toRule, _snRule) - if err != nil { - return nil, err - } - return &CallServiceCallMessageIterator{contract: _CallService.contract, event: "CallMessage", logs: logs, sub: sub}, nil -} - -// WatchCallMessage is a free log subscription operation binding the contract event 0x2cbc78425621c181f9f8a25fc06e44a0ac2b67cd6a31f8ed7918934187f8cc59. -// -// Solidity: event CallMessage(string indexed _from, string indexed _to, uint256 indexed _sn, uint256 _reqId, bytes _data) -func (_CallService *CallServiceFilterer) WatchCallMessage(opts *bind.WatchOpts, sink chan<- *CallServiceCallMessage, _from []string, _to []string, _sn []*big.Int) (event.Subscription, error) { - - var _fromRule []interface{} - for _, _fromItem := range _from { - _fromRule = append(_fromRule, _fromItem) - } - var _toRule []interface{} - for _, _toItem := range _to { - _toRule = append(_toRule, _toItem) - } - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.WatchLogs(opts, "CallMessage", _fromRule, _toRule, _snRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CallServiceCallMessage) - if err := _CallService.contract.UnpackLog(event, "CallMessage", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseCallMessage is a log parse operation binding the contract event 0x2cbc78425621c181f9f8a25fc06e44a0ac2b67cd6a31f8ed7918934187f8cc59. -// -// Solidity: event CallMessage(string indexed _from, string indexed _to, uint256 indexed _sn, uint256 _reqId, bytes _data) -func (_CallService *CallServiceFilterer) ParseCallMessage(log types.Log) (*CallServiceCallMessage, error) { - event := new(CallServiceCallMessage) - if err := _CallService.contract.UnpackLog(event, "CallMessage", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// CallServiceCallMessageSentIterator is returned from FilterCallMessageSent and is used to iterate over the raw logs and unpacked data for CallMessageSent events raised by the CallService contract. -type CallServiceCallMessageSentIterator struct { - Event *CallServiceCallMessageSent // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CallServiceCallMessageSentIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CallServiceCallMessageSent) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CallServiceCallMessageSent) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CallServiceCallMessageSentIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CallServiceCallMessageSentIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CallServiceCallMessageSent represents a CallMessageSent event raised by the CallService contract. -type CallServiceCallMessageSent struct { - From common.Address - To common.Hash - Sn *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterCallMessageSent is a free log retrieval operation binding the contract event 0x69e53ea70fdf945f6d035b3979748bc999151691fb1dc69d66f8017f8840ae28. -// -// Solidity: event CallMessageSent(address indexed _from, string indexed _to, uint256 indexed _sn) -func (_CallService *CallServiceFilterer) FilterCallMessageSent(opts *bind.FilterOpts, _from []common.Address, _to []string, _sn []*big.Int) (*CallServiceCallMessageSentIterator, error) { - - var _fromRule []interface{} - for _, _fromItem := range _from { - _fromRule = append(_fromRule, _fromItem) - } - var _toRule []interface{} - for _, _toItem := range _to { - _toRule = append(_toRule, _toItem) - } - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.FilterLogs(opts, "CallMessageSent", _fromRule, _toRule, _snRule) - if err != nil { - return nil, err - } - return &CallServiceCallMessageSentIterator{contract: _CallService.contract, event: "CallMessageSent", logs: logs, sub: sub}, nil -} - -// WatchCallMessageSent is a free log subscription operation binding the contract event 0x69e53ea70fdf945f6d035b3979748bc999151691fb1dc69d66f8017f8840ae28. -// -// Solidity: event CallMessageSent(address indexed _from, string indexed _to, uint256 indexed _sn) -func (_CallService *CallServiceFilterer) WatchCallMessageSent(opts *bind.WatchOpts, sink chan<- *CallServiceCallMessageSent, _from []common.Address, _to []string, _sn []*big.Int) (event.Subscription, error) { - - var _fromRule []interface{} - for _, _fromItem := range _from { - _fromRule = append(_fromRule, _fromItem) - } - var _toRule []interface{} - for _, _toItem := range _to { - _toRule = append(_toRule, _toItem) - } - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.WatchLogs(opts, "CallMessageSent", _fromRule, _toRule, _snRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CallServiceCallMessageSent) - if err := _CallService.contract.UnpackLog(event, "CallMessageSent", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseCallMessageSent is a log parse operation binding the contract event 0x69e53ea70fdf945f6d035b3979748bc999151691fb1dc69d66f8017f8840ae28. -// -// Solidity: event CallMessageSent(address indexed _from, string indexed _to, uint256 indexed _sn) -func (_CallService *CallServiceFilterer) ParseCallMessageSent(log types.Log) (*CallServiceCallMessageSent, error) { - event := new(CallServiceCallMessageSent) - if err := _CallService.contract.UnpackLog(event, "CallMessageSent", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// CallServiceInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the CallService contract. -type CallServiceInitializedIterator struct { - Event *CallServiceInitialized // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CallServiceInitializedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CallServiceInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CallServiceInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CallServiceInitializedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CallServiceInitializedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CallServiceInitialized represents a Initialized event raised by the CallService contract. -type CallServiceInitialized struct { - Version uint64 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. -// -// Solidity: event Initialized(uint64 version) -func (_CallService *CallServiceFilterer) FilterInitialized(opts *bind.FilterOpts) (*CallServiceInitializedIterator, error) { - - logs, sub, err := _CallService.contract.FilterLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return &CallServiceInitializedIterator{contract: _CallService.contract, event: "Initialized", logs: logs, sub: sub}, nil -} - -// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. -// -// Solidity: event Initialized(uint64 version) -func (_CallService *CallServiceFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *CallServiceInitialized) (event.Subscription, error) { - - logs, sub, err := _CallService.contract.WatchLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CallServiceInitialized) - if err := _CallService.contract.UnpackLog(event, "Initialized", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. -// -// Solidity: event Initialized(uint64 version) -func (_CallService *CallServiceFilterer) ParseInitialized(log types.Log) (*CallServiceInitialized, error) { - event := new(CallServiceInitialized) - if err := _CallService.contract.UnpackLog(event, "Initialized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// CallServiceResponseMessageIterator is returned from FilterResponseMessage and is used to iterate over the raw logs and unpacked data for ResponseMessage events raised by the CallService contract. -type CallServiceResponseMessageIterator struct { - Event *CallServiceResponseMessage // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CallServiceResponseMessageIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CallServiceResponseMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CallServiceResponseMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CallServiceResponseMessageIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CallServiceResponseMessageIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CallServiceResponseMessage represents a ResponseMessage event raised by the CallService contract. -type CallServiceResponseMessage struct { - Sn *big.Int - Code *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterResponseMessage is a free log retrieval operation binding the contract event 0xbeacafd006c5e60667f6f04aec3a498f81c8e94142b4e95b5a5a763de43ca0ab. -// -// Solidity: event ResponseMessage(uint256 indexed _sn, int256 _code) -func (_CallService *CallServiceFilterer) FilterResponseMessage(opts *bind.FilterOpts, _sn []*big.Int) (*CallServiceResponseMessageIterator, error) { - - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.FilterLogs(opts, "ResponseMessage", _snRule) - if err != nil { - return nil, err - } - return &CallServiceResponseMessageIterator{contract: _CallService.contract, event: "ResponseMessage", logs: logs, sub: sub}, nil -} - -// WatchResponseMessage is a free log subscription operation binding the contract event 0xbeacafd006c5e60667f6f04aec3a498f81c8e94142b4e95b5a5a763de43ca0ab. -// -// Solidity: event ResponseMessage(uint256 indexed _sn, int256 _code) -func (_CallService *CallServiceFilterer) WatchResponseMessage(opts *bind.WatchOpts, sink chan<- *CallServiceResponseMessage, _sn []*big.Int) (event.Subscription, error) { - - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.WatchLogs(opts, "ResponseMessage", _snRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CallServiceResponseMessage) - if err := _CallService.contract.UnpackLog(event, "ResponseMessage", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseResponseMessage is a log parse operation binding the contract event 0xbeacafd006c5e60667f6f04aec3a498f81c8e94142b4e95b5a5a763de43ca0ab. -// -// Solidity: event ResponseMessage(uint256 indexed _sn, int256 _code) -func (_CallService *CallServiceFilterer) ParseResponseMessage(log types.Log) (*CallServiceResponseMessage, error) { - event := new(CallServiceResponseMessage) - if err := _CallService.contract.UnpackLog(event, "ResponseMessage", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// CallServiceRollbackExecutedIterator is returned from FilterRollbackExecuted and is used to iterate over the raw logs and unpacked data for RollbackExecuted events raised by the CallService contract. -type CallServiceRollbackExecutedIterator struct { - Event *CallServiceRollbackExecuted // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CallServiceRollbackExecutedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CallServiceRollbackExecuted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CallServiceRollbackExecuted) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CallServiceRollbackExecutedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CallServiceRollbackExecutedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CallServiceRollbackExecuted represents a RollbackExecuted event raised by the CallService contract. -type CallServiceRollbackExecuted struct { - Sn *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRollbackExecuted is a free log retrieval operation binding the contract event 0x08f0ac7aef6da8bbe43bee8b1444a1883f1359566618bc379ce5abba44883837. -// -// Solidity: event RollbackExecuted(uint256 indexed _sn) -func (_CallService *CallServiceFilterer) FilterRollbackExecuted(opts *bind.FilterOpts, _sn []*big.Int) (*CallServiceRollbackExecutedIterator, error) { - - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.FilterLogs(opts, "RollbackExecuted", _snRule) - if err != nil { - return nil, err - } - return &CallServiceRollbackExecutedIterator{contract: _CallService.contract, event: "RollbackExecuted", logs: logs, sub: sub}, nil -} - -// WatchRollbackExecuted is a free log subscription operation binding the contract event 0x08f0ac7aef6da8bbe43bee8b1444a1883f1359566618bc379ce5abba44883837. -// -// Solidity: event RollbackExecuted(uint256 indexed _sn) -func (_CallService *CallServiceFilterer) WatchRollbackExecuted(opts *bind.WatchOpts, sink chan<- *CallServiceRollbackExecuted, _sn []*big.Int) (event.Subscription, error) { - - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.WatchLogs(opts, "RollbackExecuted", _snRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CallServiceRollbackExecuted) - if err := _CallService.contract.UnpackLog(event, "RollbackExecuted", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRollbackExecuted is a log parse operation binding the contract event 0x08f0ac7aef6da8bbe43bee8b1444a1883f1359566618bc379ce5abba44883837. -// -// Solidity: event RollbackExecuted(uint256 indexed _sn) -func (_CallService *CallServiceFilterer) ParseRollbackExecuted(log types.Log) (*CallServiceRollbackExecuted, error) { - event := new(CallServiceRollbackExecuted) - if err := _CallService.contract.UnpackLog(event, "RollbackExecuted", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// CallServiceRollbackMessageIterator is returned from FilterRollbackMessage and is used to iterate over the raw logs and unpacked data for RollbackMessage events raised by the CallService contract. -type CallServiceRollbackMessageIterator struct { - Event *CallServiceRollbackMessage // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CallServiceRollbackMessageIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CallServiceRollbackMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CallServiceRollbackMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CallServiceRollbackMessageIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CallServiceRollbackMessageIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CallServiceRollbackMessage represents a RollbackMessage event raised by the CallService contract. -type CallServiceRollbackMessage struct { - Sn *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterRollbackMessage is a free log retrieval operation binding the contract event 0x38934ab923f985814047679ba041577b8203ddd15fe9910d3fc6a7aa6001e9c7. -// -// Solidity: event RollbackMessage(uint256 indexed _sn) -func (_CallService *CallServiceFilterer) FilterRollbackMessage(opts *bind.FilterOpts, _sn []*big.Int) (*CallServiceRollbackMessageIterator, error) { - - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.FilterLogs(opts, "RollbackMessage", _snRule) - if err != nil { - return nil, err - } - return &CallServiceRollbackMessageIterator{contract: _CallService.contract, event: "RollbackMessage", logs: logs, sub: sub}, nil -} - -// WatchRollbackMessage is a free log subscription operation binding the contract event 0x38934ab923f985814047679ba041577b8203ddd15fe9910d3fc6a7aa6001e9c7. -// -// Solidity: event RollbackMessage(uint256 indexed _sn) -func (_CallService *CallServiceFilterer) WatchRollbackMessage(opts *bind.WatchOpts, sink chan<- *CallServiceRollbackMessage, _sn []*big.Int) (event.Subscription, error) { - - var _snRule []interface{} - for _, _snItem := range _sn { - _snRule = append(_snRule, _snItem) - } - - logs, sub, err := _CallService.contract.WatchLogs(opts, "RollbackMessage", _snRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CallServiceRollbackMessage) - if err := _CallService.contract.UnpackLog(event, "RollbackMessage", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseRollbackMessage is a log parse operation binding the contract event 0x38934ab923f985814047679ba041577b8203ddd15fe9910d3fc6a7aa6001e9c7. -// -// Solidity: event RollbackMessage(uint256 indexed _sn) -func (_CallService *CallServiceFilterer) ParseRollbackMessage(log types.Log) (*CallServiceRollbackMessage, error) { - event := new(CallServiceRollbackMessage) - if err := _CallService.contract.UnpackLog(event, "RollbackMessage", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/chains/bitcoin/abi/icentralized_connection.go b/relayer/chains/bitcoin/abi/icentralized_connection.go deleted file mode 100644 index 9842ab51..00000000 --- a/relayer/chains/bitcoin/abi/icentralized_connection.go +++ /dev/null @@ -1,722 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package abi - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "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/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// CentralizedConnectionMetaData contains all meta data concerning the CentralizedConnection contract. -var CentralizedConnectionMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"admin\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"claimFees\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"connSn\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getFee\",\"inputs\":[{\"name\":\"to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"response\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[{\"name\":\"fee\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getReceipt\",\"inputs\":[{\"name\":\"srcNetwork\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_connSn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"initialize\",\"inputs\":[{\"name\":\"_relayer\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_xCall\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"recvMessage\",\"inputs\":[{\"name\":\"srcNetwork\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"_connSn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"revertMessage\",\"inputs\":[{\"name\":\"sn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"sendMessage\",\"inputs\":[{\"name\":\"to\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"svc\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"sn\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"setAdmin\",\"inputs\":[{\"name\":\"_address\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setFee\",\"inputs\":[{\"name\":\"networkId\",\"type\":\"string\",\"internalType\":\"string\"},{\"name\":\"messageFee\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"responseFee\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"event\",\"name\":\"Initialized\",\"inputs\":[{\"name\":\"version\",\"type\":\"uint64\",\"indexed\":false,\"internalType\":\"uint64\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Message\",\"inputs\":[{\"name\":\"targetNetwork\",\"type\":\"string\",\"indexed\":false,\"internalType\":\"string\"},{\"name\":\"sn\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"_msg\",\"type\":\"bytes\",\"indexed\":false,\"internalType\":\"bytes\"}],\"anonymous\":false},{\"type\":\"error\",\"name\":\"InvalidInitialization\",\"inputs\":[]},{\"type\":\"error\",\"name\":\"NotInitializing\",\"inputs\":[]}]", -} - -// CentralizedConnectionABI is the input ABI used to generate the binding from. -// Deprecated: Use CentralizedConnectionMetaData.ABI instead. -var CentralizedConnectionABI = CentralizedConnectionMetaData.ABI - -// CentralizedConnection is an auto generated Go binding around an Ethereum contract. -type CentralizedConnection struct { - CentralizedConnectionCaller // Read-only binding to the contract - CentralizedConnectionTransactor // Write-only binding to the contract - CentralizedConnectionFilterer // Log filterer for contract events -} - -// CentralizedConnectionCaller is an auto generated read-only Go binding around an Ethereum contract. -type CentralizedConnectionCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// CentralizedConnectionTransactor is an auto generated write-only Go binding around an Ethereum contract. -type CentralizedConnectionTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// CentralizedConnectionFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type CentralizedConnectionFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// CentralizedConnectionSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type CentralizedConnectionSession struct { - Contract *CentralizedConnection // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// CentralizedConnectionCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type CentralizedConnectionCallerSession struct { - Contract *CentralizedConnectionCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// CentralizedConnectionTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type CentralizedConnectionTransactorSession struct { - Contract *CentralizedConnectionTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// CentralizedConnectionRaw is an auto generated low-level Go binding around an Ethereum contract. -type CentralizedConnectionRaw struct { - Contract *CentralizedConnection // Generic contract binding to access the raw methods on -} - -// CentralizedConnectionCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type CentralizedConnectionCallerRaw struct { - Contract *CentralizedConnectionCaller // Generic read-only contract binding to access the raw methods on -} - -// CentralizedConnectionTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type CentralizedConnectionTransactorRaw struct { - Contract *CentralizedConnectionTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewCentralizedConnection creates a new instance of CentralizedConnection, bound to a specific deployed contract. -func NewCentralizedConnection(address common.Address, backend bind.ContractBackend) (*CentralizedConnection, error) { - contract, err := bindCentralizedConnection(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &CentralizedConnection{CentralizedConnectionCaller: CentralizedConnectionCaller{contract: contract}, CentralizedConnectionTransactor: CentralizedConnectionTransactor{contract: contract}, CentralizedConnectionFilterer: CentralizedConnectionFilterer{contract: contract}}, nil -} - -// NewCentralizedConnectionCaller creates a new read-only instance of CentralizedConnection, bound to a specific deployed contract. -func NewCentralizedConnectionCaller(address common.Address, caller bind.ContractCaller) (*CentralizedConnectionCaller, error) { - contract, err := bindCentralizedConnection(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &CentralizedConnectionCaller{contract: contract}, nil -} - -// NewCentralizedConnectionTransactor creates a new write-only instance of CentralizedConnection, bound to a specific deployed contract. -func NewCentralizedConnectionTransactor(address common.Address, transactor bind.ContractTransactor) (*CentralizedConnectionTransactor, error) { - contract, err := bindCentralizedConnection(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &CentralizedConnectionTransactor{contract: contract}, nil -} - -// NewCentralizedConnectionFilterer creates a new log filterer instance of CentralizedConnection, bound to a specific deployed contract. -func NewCentralizedConnectionFilterer(address common.Address, filterer bind.ContractFilterer) (*CentralizedConnectionFilterer, error) { - contract, err := bindCentralizedConnection(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &CentralizedConnectionFilterer{contract: contract}, nil -} - -// bindCentralizedConnection binds a generic wrapper to an already deployed contract. -func bindCentralizedConnection(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := CentralizedConnectionMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_CentralizedConnection *CentralizedConnectionRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CentralizedConnection.Contract.CentralizedConnectionCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_CentralizedConnection *CentralizedConnectionRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CentralizedConnection.Contract.CentralizedConnectionTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_CentralizedConnection *CentralizedConnectionRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CentralizedConnection.Contract.CentralizedConnectionTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_CentralizedConnection *CentralizedConnectionCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _CentralizedConnection.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_CentralizedConnection *CentralizedConnectionTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CentralizedConnection.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_CentralizedConnection *CentralizedConnectionTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _CentralizedConnection.Contract.contract.Transact(opts, method, params...) -} - -// Admin is a free data retrieval call binding the contract method 0xf851a440. -// -// Solidity: function admin() view returns(address) -func (_CentralizedConnection *CentralizedConnectionCaller) Admin(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _CentralizedConnection.contract.Call(opts, &out, "admin") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Admin is a free data retrieval call binding the contract method 0xf851a440. -// -// Solidity: function admin() view returns(address) -func (_CentralizedConnection *CentralizedConnectionSession) Admin() (common.Address, error) { - return _CentralizedConnection.Contract.Admin(&_CentralizedConnection.CallOpts) -} - -// Admin is a free data retrieval call binding the contract method 0xf851a440. -// -// Solidity: function admin() view returns(address) -func (_CentralizedConnection *CentralizedConnectionCallerSession) Admin() (common.Address, error) { - return _CentralizedConnection.Contract.Admin(&_CentralizedConnection.CallOpts) -} - -// ConnSn is a free data retrieval call binding the contract method 0x99f1fca7. -// -// Solidity: function connSn() view returns(uint256) -func (_CentralizedConnection *CentralizedConnectionCaller) ConnSn(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _CentralizedConnection.contract.Call(opts, &out, "connSn") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// ConnSn is a free data retrieval call binding the contract method 0x99f1fca7. -// -// Solidity: function connSn() view returns(uint256) -func (_CentralizedConnection *CentralizedConnectionSession) ConnSn() (*big.Int, error) { - return _CentralizedConnection.Contract.ConnSn(&_CentralizedConnection.CallOpts) -} - -// ConnSn is a free data retrieval call binding the contract method 0x99f1fca7. -// -// Solidity: function connSn() view returns(uint256) -func (_CentralizedConnection *CentralizedConnectionCallerSession) ConnSn() (*big.Int, error) { - return _CentralizedConnection.Contract.ConnSn(&_CentralizedConnection.CallOpts) -} - -// GetFee is a free data retrieval call binding the contract method 0x7d4c4f4a. -// -// Solidity: function getFee(string to, bool response) view returns(uint256 fee) -func (_CentralizedConnection *CentralizedConnectionCaller) GetFee(opts *bind.CallOpts, to string, response bool) (*big.Int, error) { - var out []interface{} - err := _CentralizedConnection.contract.Call(opts, &out, "getFee", to, response) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// GetFee is a free data retrieval call binding the contract method 0x7d4c4f4a. -// -// Solidity: function getFee(string to, bool response) view returns(uint256 fee) -func (_CentralizedConnection *CentralizedConnectionSession) GetFee(to string, response bool) (*big.Int, error) { - return _CentralizedConnection.Contract.GetFee(&_CentralizedConnection.CallOpts, to, response) -} - -// GetFee is a free data retrieval call binding the contract method 0x7d4c4f4a. -// -// Solidity: function getFee(string to, bool response) view returns(uint256 fee) -func (_CentralizedConnection *CentralizedConnectionCallerSession) GetFee(to string, response bool) (*big.Int, error) { - return _CentralizedConnection.Contract.GetFee(&_CentralizedConnection.CallOpts, to, response) -} - -// GetReceipt is a free data retrieval call binding the contract method 0x9664da0e. -// -// Solidity: function getReceipt(string srcNetwork, uint256 _connSn) view returns(bool) -func (_CentralizedConnection *CentralizedConnectionCaller) GetReceipt(opts *bind.CallOpts, srcNetwork string, _connSn *big.Int) (bool, error) { - var out []interface{} - err := _CentralizedConnection.contract.Call(opts, &out, "getReceipt", srcNetwork, _connSn) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// GetReceipt is a free data retrieval call binding the contract method 0x9664da0e. -// -// Solidity: function getReceipt(string srcNetwork, uint256 _connSn) view returns(bool) -func (_CentralizedConnection *CentralizedConnectionSession) GetReceipt(srcNetwork string, _connSn *big.Int) (bool, error) { - return _CentralizedConnection.Contract.GetReceipt(&_CentralizedConnection.CallOpts, srcNetwork, _connSn) -} - -// GetReceipt is a free data retrieval call binding the contract method 0x9664da0e. -// -// Solidity: function getReceipt(string srcNetwork, uint256 _connSn) view returns(bool) -func (_CentralizedConnection *CentralizedConnectionCallerSession) GetReceipt(srcNetwork string, _connSn *big.Int) (bool, error) { - return _CentralizedConnection.Contract.GetReceipt(&_CentralizedConnection.CallOpts, srcNetwork, _connSn) -} - -// ClaimFees is a paid mutator transaction binding the contract method 0xd294f093. -// -// Solidity: function claimFees() returns() -func (_CentralizedConnection *CentralizedConnectionTransactor) ClaimFees(opts *bind.TransactOpts) (*types.Transaction, error) { - return _CentralizedConnection.contract.Transact(opts, "claimFees") -} - -// ClaimFees is a paid mutator transaction binding the contract method 0xd294f093. -// -// Solidity: function claimFees() returns() -func (_CentralizedConnection *CentralizedConnectionSession) ClaimFees() (*types.Transaction, error) { - return _CentralizedConnection.Contract.ClaimFees(&_CentralizedConnection.TransactOpts) -} - -// ClaimFees is a paid mutator transaction binding the contract method 0xd294f093. -// -// Solidity: function claimFees() returns() -func (_CentralizedConnection *CentralizedConnectionTransactorSession) ClaimFees() (*types.Transaction, error) { - return _CentralizedConnection.Contract.ClaimFees(&_CentralizedConnection.TransactOpts) -} - -// Initialize is a paid mutator transaction binding the contract method 0x485cc955. -// -// Solidity: function initialize(address _relayer, address _xCall) returns() -func (_CentralizedConnection *CentralizedConnectionTransactor) Initialize(opts *bind.TransactOpts, _relayer common.Address, _xCall common.Address) (*types.Transaction, error) { - return _CentralizedConnection.contract.Transact(opts, "initialize", _relayer, _xCall) -} - -// Initialize is a paid mutator transaction binding the contract method 0x485cc955. -// -// Solidity: function initialize(address _relayer, address _xCall) returns() -func (_CentralizedConnection *CentralizedConnectionSession) Initialize(_relayer common.Address, _xCall common.Address) (*types.Transaction, error) { - return _CentralizedConnection.Contract.Initialize(&_CentralizedConnection.TransactOpts, _relayer, _xCall) -} - -// Initialize is a paid mutator transaction binding the contract method 0x485cc955. -// -// Solidity: function initialize(address _relayer, address _xCall) returns() -func (_CentralizedConnection *CentralizedConnectionTransactorSession) Initialize(_relayer common.Address, _xCall common.Address) (*types.Transaction, error) { - return _CentralizedConnection.Contract.Initialize(&_CentralizedConnection.TransactOpts, _relayer, _xCall) -} - -// RecvMessage is a paid mutator transaction binding the contract method 0xb58b4cec. -// -// Solidity: function recvMessage(string srcNetwork, uint256 _connSn, bytes _msg) returns() -func (_CentralizedConnection *CentralizedConnectionTransactor) RecvMessage(opts *bind.TransactOpts, srcNetwork string, _connSn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CentralizedConnection.contract.Transact(opts, "recvMessage", srcNetwork, _connSn, _msg) -} - -// RecvMessage is a paid mutator transaction binding the contract method 0xb58b4cec. -// -// Solidity: function recvMessage(string srcNetwork, uint256 _connSn, bytes _msg) returns() -func (_CentralizedConnection *CentralizedConnectionSession) RecvMessage(srcNetwork string, _connSn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CentralizedConnection.Contract.RecvMessage(&_CentralizedConnection.TransactOpts, srcNetwork, _connSn, _msg) -} - -// RecvMessage is a paid mutator transaction binding the contract method 0xb58b4cec. -// -// Solidity: function recvMessage(string srcNetwork, uint256 _connSn, bytes _msg) returns() -func (_CentralizedConnection *CentralizedConnectionTransactorSession) RecvMessage(srcNetwork string, _connSn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CentralizedConnection.Contract.RecvMessage(&_CentralizedConnection.TransactOpts, srcNetwork, _connSn, _msg) -} - -// RevertMessage is a paid mutator transaction binding the contract method 0x2d3fb823. -// -// Solidity: function revertMessage(uint256 sn) returns() -func (_CentralizedConnection *CentralizedConnectionTransactor) RevertMessage(opts *bind.TransactOpts, sn *big.Int) (*types.Transaction, error) { - return _CentralizedConnection.contract.Transact(opts, "revertMessage", sn) -} - -// RevertMessage is a paid mutator transaction binding the contract method 0x2d3fb823. -// -// Solidity: function revertMessage(uint256 sn) returns() -func (_CentralizedConnection *CentralizedConnectionSession) RevertMessage(sn *big.Int) (*types.Transaction, error) { - return _CentralizedConnection.Contract.RevertMessage(&_CentralizedConnection.TransactOpts, sn) -} - -// RevertMessage is a paid mutator transaction binding the contract method 0x2d3fb823. -// -// Solidity: function revertMessage(uint256 sn) returns() -func (_CentralizedConnection *CentralizedConnectionTransactorSession) RevertMessage(sn *big.Int) (*types.Transaction, error) { - return _CentralizedConnection.Contract.RevertMessage(&_CentralizedConnection.TransactOpts, sn) -} - -// SendMessage is a paid mutator transaction binding the contract method 0x522a901e. -// -// Solidity: function sendMessage(string to, string svc, int256 sn, bytes _msg) payable returns() -func (_CentralizedConnection *CentralizedConnectionTransactor) SendMessage(opts *bind.TransactOpts, to string, svc string, sn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CentralizedConnection.contract.Transact(opts, "sendMessage", to, svc, sn, _msg) -} - -// SendMessage is a paid mutator transaction binding the contract method 0x522a901e. -// -// Solidity: function sendMessage(string to, string svc, int256 sn, bytes _msg) payable returns() -func (_CentralizedConnection *CentralizedConnectionSession) SendMessage(to string, svc string, sn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CentralizedConnection.Contract.SendMessage(&_CentralizedConnection.TransactOpts, to, svc, sn, _msg) -} - -// SendMessage is a paid mutator transaction binding the contract method 0x522a901e. -// -// Solidity: function sendMessage(string to, string svc, int256 sn, bytes _msg) payable returns() -func (_CentralizedConnection *CentralizedConnectionTransactorSession) SendMessage(to string, svc string, sn *big.Int, _msg []byte) (*types.Transaction, error) { - return _CentralizedConnection.Contract.SendMessage(&_CentralizedConnection.TransactOpts, to, svc, sn, _msg) -} - -// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. -// -// Solidity: function setAdmin(address _address) returns() -func (_CentralizedConnection *CentralizedConnectionTransactor) SetAdmin(opts *bind.TransactOpts, _address common.Address) (*types.Transaction, error) { - return _CentralizedConnection.contract.Transact(opts, "setAdmin", _address) -} - -// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. -// -// Solidity: function setAdmin(address _address) returns() -func (_CentralizedConnection *CentralizedConnectionSession) SetAdmin(_address common.Address) (*types.Transaction, error) { - return _CentralizedConnection.Contract.SetAdmin(&_CentralizedConnection.TransactOpts, _address) -} - -// SetAdmin is a paid mutator transaction binding the contract method 0x704b6c02. -// -// Solidity: function setAdmin(address _address) returns() -func (_CentralizedConnection *CentralizedConnectionTransactorSession) SetAdmin(_address common.Address) (*types.Transaction, error) { - return _CentralizedConnection.Contract.SetAdmin(&_CentralizedConnection.TransactOpts, _address) -} - -// SetFee is a paid mutator transaction binding the contract method 0x43f08a89. -// -// Solidity: function setFee(string networkId, uint256 messageFee, uint256 responseFee) returns() -func (_CentralizedConnection *CentralizedConnectionTransactor) SetFee(opts *bind.TransactOpts, networkId string, messageFee *big.Int, responseFee *big.Int) (*types.Transaction, error) { - return _CentralizedConnection.contract.Transact(opts, "setFee", networkId, messageFee, responseFee) -} - -// SetFee is a paid mutator transaction binding the contract method 0x43f08a89. -// -// Solidity: function setFee(string networkId, uint256 messageFee, uint256 responseFee) returns() -func (_CentralizedConnection *CentralizedConnectionSession) SetFee(networkId string, messageFee *big.Int, responseFee *big.Int) (*types.Transaction, error) { - return _CentralizedConnection.Contract.SetFee(&_CentralizedConnection.TransactOpts, networkId, messageFee, responseFee) -} - -// SetFee is a paid mutator transaction binding the contract method 0x43f08a89. -// -// Solidity: function setFee(string networkId, uint256 messageFee, uint256 responseFee) returns() -func (_CentralizedConnection *CentralizedConnectionTransactorSession) SetFee(networkId string, messageFee *big.Int, responseFee *big.Int) (*types.Transaction, error) { - return _CentralizedConnection.Contract.SetFee(&_CentralizedConnection.TransactOpts, networkId, messageFee, responseFee) -} - -// CentralizedConnectionInitializedIterator is returned from FilterInitialized and is used to iterate over the raw logs and unpacked data for Initialized events raised by the CentralizedConnection contract. -type CentralizedConnectionInitializedIterator struct { - Event *CentralizedConnectionInitialized // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CentralizedConnectionInitializedIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CentralizedConnectionInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CentralizedConnectionInitialized) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CentralizedConnectionInitializedIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CentralizedConnectionInitializedIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CentralizedConnectionInitialized represents a Initialized event raised by the CentralizedConnection contract. -type CentralizedConnectionInitialized struct { - Version uint64 - Raw types.Log // Blockchain specific contextual infos -} - -// FilterInitialized is a free log retrieval operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. -// -// Solidity: event Initialized(uint64 version) -func (_CentralizedConnection *CentralizedConnectionFilterer) FilterInitialized(opts *bind.FilterOpts) (*CentralizedConnectionInitializedIterator, error) { - - logs, sub, err := _CentralizedConnection.contract.FilterLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return &CentralizedConnectionInitializedIterator{contract: _CentralizedConnection.contract, event: "Initialized", logs: logs, sub: sub}, nil -} - -// WatchInitialized is a free log subscription operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. -// -// Solidity: event Initialized(uint64 version) -func (_CentralizedConnection *CentralizedConnectionFilterer) WatchInitialized(opts *bind.WatchOpts, sink chan<- *CentralizedConnectionInitialized) (event.Subscription, error) { - - logs, sub, err := _CentralizedConnection.contract.WatchLogs(opts, "Initialized") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CentralizedConnectionInitialized) - if err := _CentralizedConnection.contract.UnpackLog(event, "Initialized", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseInitialized is a log parse operation binding the contract event 0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2. -// -// Solidity: event Initialized(uint64 version) -func (_CentralizedConnection *CentralizedConnectionFilterer) ParseInitialized(log types.Log) (*CentralizedConnectionInitialized, error) { - event := new(CentralizedConnectionInitialized) - if err := _CentralizedConnection.contract.UnpackLog(event, "Initialized", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// CentralizedConnectionMessageIterator is returned from FilterMessage and is used to iterate over the raw logs and unpacked data for Message events raised by the CentralizedConnection contract. -type CentralizedConnectionMessageIterator struct { - Event *CentralizedConnectionMessage // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *CentralizedConnectionMessageIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(CentralizedConnectionMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(CentralizedConnectionMessage) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *CentralizedConnectionMessageIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *CentralizedConnectionMessageIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// CentralizedConnectionMessage represents a Message event raised by the CentralizedConnection contract. -type CentralizedConnectionMessage struct { - TargetNetwork string - Sn *big.Int - Msg []byte - Raw types.Log // Blockchain specific contextual infos -} - -// FilterMessage is a free log retrieval operation binding the contract event 0x37be353f216cf7e33639101fd610c542e6a0c0109173fa1c1d8b04d34edb7c1b. -// -// Solidity: event Message(string targetNetwork, uint256 sn, bytes _msg) -func (_CentralizedConnection *CentralizedConnectionFilterer) FilterMessage(opts *bind.FilterOpts) (*CentralizedConnectionMessageIterator, error) { - - logs, sub, err := _CentralizedConnection.contract.FilterLogs(opts, "Message") - if err != nil { - return nil, err - } - return &CentralizedConnectionMessageIterator{contract: _CentralizedConnection.contract, event: "Message", logs: logs, sub: sub}, nil -} - -// WatchMessage is a free log subscription operation binding the contract event 0x37be353f216cf7e33639101fd610c542e6a0c0109173fa1c1d8b04d34edb7c1b. -// -// Solidity: event Message(string targetNetwork, uint256 sn, bytes _msg) -func (_CentralizedConnection *CentralizedConnectionFilterer) WatchMessage(opts *bind.WatchOpts, sink chan<- *CentralizedConnectionMessage) (event.Subscription, error) { - - logs, sub, err := _CentralizedConnection.contract.WatchLogs(opts, "Message") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(CentralizedConnectionMessage) - if err := _CentralizedConnection.contract.UnpackLog(event, "Message", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseMessage is a log parse operation binding the contract event 0x37be353f216cf7e33639101fd610c542e6a0c0109173fa1c1d8b04d34edb7c1b. -// -// Solidity: event Message(string targetNetwork, uint256 sn, bytes _msg) -func (_CentralizedConnection *CentralizedConnectionFilterer) ParseMessage(log types.Log) (*CentralizedConnectionMessage, error) { - event := new(CentralizedConnectionMessage) - if err := _CentralizedConnection.contract.UnpackLog(event, "Message", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/chains/bitcoin/abi/inonfungible_token.go b/relayer/chains/bitcoin/abi/inonfungible_token.go deleted file mode 100644 index b4d22c64..00000000 --- a/relayer/chains/bitcoin/abi/inonfungible_token.go +++ /dev/null @@ -1,2017 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package abi - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "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/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// INonfungiblePositionManagerCollectParams is an auto generated low-level Go binding around an user-defined struct. -type INonfungiblePositionManagerCollectParams struct { - TokenId *big.Int - Recipient common.Address - Amount0Max *big.Int - Amount1Max *big.Int -} - -// INonfungiblePositionManagerDecreaseLiquidityParams is an auto generated low-level Go binding around an user-defined struct. -type INonfungiblePositionManagerDecreaseLiquidityParams struct { - TokenId *big.Int - Liquidity *big.Int - Amount0Min *big.Int - Amount1Min *big.Int - Deadline *big.Int -} - -// INonfungiblePositionManagerIncreaseLiquidityParams is an auto generated low-level Go binding around an user-defined struct. -type INonfungiblePositionManagerIncreaseLiquidityParams struct { - TokenId *big.Int - Amount0Desired *big.Int - Amount1Desired *big.Int - Amount0Min *big.Int - Amount1Min *big.Int - Deadline *big.Int -} - -// INonfungiblePositionManagerMintParams is an auto generated low-level Go binding around an user-defined struct. -type INonfungiblePositionManagerMintParams struct { - Token0 common.Address - Token1 common.Address - Fee *big.Int - TickLower *big.Int - TickUpper *big.Int - Amount0Desired *big.Int - Amount1Desired *big.Int - Amount0Min *big.Int - Amount1Min *big.Int - Recipient common.Address - Deadline *big.Int -} - -// InonfungibleTokenMetaData contains all meta data concerning the InonfungibleToken contract. -var InonfungibleTokenMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"DOMAIN_SEPARATOR\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"PERMIT_TYPEHASH\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"stateMutability\":\"pure\"},{\"type\":\"function\",\"name\":\"WETH9\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"approve\",\"inputs\":[{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"balanceOf\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"burn\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"collect\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.CollectParams\",\"components\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amount0Max\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount1Max\",\"type\":\"uint128\",\"internalType\":\"uint128\"}]}],\"outputs\":[{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"createAndInitializePoolIfNecessary\",\"inputs\":[{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"sqrtPriceX96\",\"type\":\"uint160\",\"internalType\":\"uint160\"}],\"outputs\":[{\"name\":\"pool\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"decreaseLiquidity\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.DecreaseLiquidityParams\",\"components\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount0Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"factory\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"getApproved\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"increaseLiquidity\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.IncreaseLiquidityParams\",\"components\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount0Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount0Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"isApprovedForAll\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"mint\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structINonfungiblePositionManager.MintParams\",\"components\":[{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"tickLower\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"tickUpper\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"amount0Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Desired\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount0Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1Min\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"name\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"ownerOf\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"permit\",\"inputs\":[{\"name\":\"spender\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"v\",\"type\":\"uint8\",\"internalType\":\"uint8\"},{\"name\":\"r\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"},{\"name\":\"s\",\"type\":\"bytes32\",\"internalType\":\"bytes32\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"positions\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"nonce\",\"type\":\"uint96\",\"internalType\":\"uint96\"},{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token0\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"token1\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"tickLower\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"tickUpper\",\"type\":\"int24\",\"internalType\":\"int24\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"feeGrowthInside0LastX128\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"feeGrowthInside1LastX128\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"tokensOwed0\",\"type\":\"uint128\",\"internalType\":\"uint128\"},{\"name\":\"tokensOwed1\",\"type\":\"uint128\",\"internalType\":\"uint128\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"refundETH\",\"inputs\":[],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"safeTransferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"safeTransferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"setApprovalForAll\",\"inputs\":[{\"name\":\"operator\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"_approved\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"supportsInterface\",\"inputs\":[{\"name\":\"interfaceId\",\"type\":\"bytes4\",\"internalType\":\"bytes4\"}],\"outputs\":[{\"name\":\"\",\"type\":\"bool\",\"internalType\":\"bool\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"sweepToken\",\"inputs\":[{\"name\":\"token\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"amountMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"symbol\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokenByIndex\",\"inputs\":[{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokenOfOwnerByIndex\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"index\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"tokenURI\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[{\"name\":\"\",\"type\":\"string\",\"internalType\":\"string\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"totalSupply\",\"inputs\":[],\"outputs\":[{\"name\":\"\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"view\"},{\"type\":\"function\",\"name\":\"transferFrom\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"},{\"type\":\"function\",\"name\":\"unwrapWETH9\",\"inputs\":[{\"name\":\"amountMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"}],\"outputs\":[],\"stateMutability\":\"payable\"},{\"type\":\"event\",\"name\":\"Approval\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"approved\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"ApprovalForAll\",\"inputs\":[{\"name\":\"owner\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"operator\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"approved\",\"type\":\"bool\",\"indexed\":false,\"internalType\":\"bool\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Collect\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"recipient\",\"type\":\"address\",\"indexed\":false,\"internalType\":\"address\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"DecreaseLiquidity\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"IncreaseLiquidity\",\"inputs\":[{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"},{\"name\":\"liquidity\",\"type\":\"uint128\",\"indexed\":false,\"internalType\":\"uint128\"},{\"name\":\"amount0\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"},{\"name\":\"amount1\",\"type\":\"uint256\",\"indexed\":false,\"internalType\":\"uint256\"}],\"anonymous\":false},{\"type\":\"event\",\"name\":\"Transfer\",\"inputs\":[{\"name\":\"from\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"to\",\"type\":\"address\",\"indexed\":true,\"internalType\":\"address\"},{\"name\":\"tokenId\",\"type\":\"uint256\",\"indexed\":true,\"internalType\":\"uint256\"}],\"anonymous\":false}]", -} - -// InonfungibleTokenABI is the input ABI used to generate the binding from. -// Deprecated: Use InonfungibleTokenMetaData.ABI instead. -var InonfungibleTokenABI = InonfungibleTokenMetaData.ABI - -// InonfungibleToken is an auto generated Go binding around an Ethereum contract. -type InonfungibleToken struct { - InonfungibleTokenCaller // Read-only binding to the contract - InonfungibleTokenTransactor // Write-only binding to the contract - InonfungibleTokenFilterer // Log filterer for contract events -} - -// InonfungibleTokenCaller is an auto generated read-only Go binding around an Ethereum contract. -type InonfungibleTokenCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// InonfungibleTokenTransactor is an auto generated write-only Go binding around an Ethereum contract. -type InonfungibleTokenTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// InonfungibleTokenFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type InonfungibleTokenFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// InonfungibleTokenSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type InonfungibleTokenSession struct { - Contract *InonfungibleToken // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// InonfungibleTokenCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type InonfungibleTokenCallerSession struct { - Contract *InonfungibleTokenCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// InonfungibleTokenTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type InonfungibleTokenTransactorSession struct { - Contract *InonfungibleTokenTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// InonfungibleTokenRaw is an auto generated low-level Go binding around an Ethereum contract. -type InonfungibleTokenRaw struct { - Contract *InonfungibleToken // Generic contract binding to access the raw methods on -} - -// InonfungibleTokenCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type InonfungibleTokenCallerRaw struct { - Contract *InonfungibleTokenCaller // Generic read-only contract binding to access the raw methods on -} - -// InonfungibleTokenTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type InonfungibleTokenTransactorRaw struct { - Contract *InonfungibleTokenTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewInonfungibleToken creates a new instance of InonfungibleToken, bound to a specific deployed contract. -func NewInonfungibleToken(address common.Address, backend bind.ContractBackend) (*InonfungibleToken, error) { - contract, err := bindInonfungibleToken(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &InonfungibleToken{InonfungibleTokenCaller: InonfungibleTokenCaller{contract: contract}, InonfungibleTokenTransactor: InonfungibleTokenTransactor{contract: contract}, InonfungibleTokenFilterer: InonfungibleTokenFilterer{contract: contract}}, nil -} - -// NewInonfungibleTokenCaller creates a new read-only instance of InonfungibleToken, bound to a specific deployed contract. -func NewInonfungibleTokenCaller(address common.Address, caller bind.ContractCaller) (*InonfungibleTokenCaller, error) { - contract, err := bindInonfungibleToken(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &InonfungibleTokenCaller{contract: contract}, nil -} - -// NewInonfungibleTokenTransactor creates a new write-only instance of InonfungibleToken, bound to a specific deployed contract. -func NewInonfungibleTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*InonfungibleTokenTransactor, error) { - contract, err := bindInonfungibleToken(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &InonfungibleTokenTransactor{contract: contract}, nil -} - -// NewInonfungibleTokenFilterer creates a new log filterer instance of InonfungibleToken, bound to a specific deployed contract. -func NewInonfungibleTokenFilterer(address common.Address, filterer bind.ContractFilterer) (*InonfungibleTokenFilterer, error) { - contract, err := bindInonfungibleToken(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &InonfungibleTokenFilterer{contract: contract}, nil -} - -// bindInonfungibleToken binds a generic wrapper to an already deployed contract. -func bindInonfungibleToken(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := InonfungibleTokenMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_InonfungibleToken *InonfungibleTokenRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _InonfungibleToken.Contract.InonfungibleTokenCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_InonfungibleToken *InonfungibleTokenRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _InonfungibleToken.Contract.InonfungibleTokenTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_InonfungibleToken *InonfungibleTokenRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _InonfungibleToken.Contract.InonfungibleTokenTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_InonfungibleToken *InonfungibleTokenCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _InonfungibleToken.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_InonfungibleToken *InonfungibleTokenTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _InonfungibleToken.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_InonfungibleToken *InonfungibleTokenTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _InonfungibleToken.Contract.contract.Transact(opts, method, params...) -} - -// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. -// -// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) -func (_InonfungibleToken *InonfungibleTokenCaller) DOMAINSEPARATOR(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "DOMAIN_SEPARATOR") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. -// -// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) -func (_InonfungibleToken *InonfungibleTokenSession) DOMAINSEPARATOR() ([32]byte, error) { - return _InonfungibleToken.Contract.DOMAINSEPARATOR(&_InonfungibleToken.CallOpts) -} - -// DOMAINSEPARATOR is a free data retrieval call binding the contract method 0x3644e515. -// -// Solidity: function DOMAIN_SEPARATOR() view returns(bytes32) -func (_InonfungibleToken *InonfungibleTokenCallerSession) DOMAINSEPARATOR() ([32]byte, error) { - return _InonfungibleToken.Contract.DOMAINSEPARATOR(&_InonfungibleToken.CallOpts) -} - -// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x30adf81f. -// -// Solidity: function PERMIT_TYPEHASH() pure returns(bytes32) -func (_InonfungibleToken *InonfungibleTokenCaller) PERMITTYPEHASH(opts *bind.CallOpts) ([32]byte, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "PERMIT_TYPEHASH") - - if err != nil { - return *new([32]byte), err - } - - out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) - - return out0, err - -} - -// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x30adf81f. -// -// Solidity: function PERMIT_TYPEHASH() pure returns(bytes32) -func (_InonfungibleToken *InonfungibleTokenSession) PERMITTYPEHASH() ([32]byte, error) { - return _InonfungibleToken.Contract.PERMITTYPEHASH(&_InonfungibleToken.CallOpts) -} - -// PERMITTYPEHASH is a free data retrieval call binding the contract method 0x30adf81f. -// -// Solidity: function PERMIT_TYPEHASH() pure returns(bytes32) -func (_InonfungibleToken *InonfungibleTokenCallerSession) PERMITTYPEHASH() ([32]byte, error) { - return _InonfungibleToken.Contract.PERMITTYPEHASH(&_InonfungibleToken.CallOpts) -} - -// WETH9 is a free data retrieval call binding the contract method 0x4aa4a4fc. -// -// Solidity: function WETH9() view returns(address) -func (_InonfungibleToken *InonfungibleTokenCaller) WETH9(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "WETH9") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// WETH9 is a free data retrieval call binding the contract method 0x4aa4a4fc. -// -// Solidity: function WETH9() view returns(address) -func (_InonfungibleToken *InonfungibleTokenSession) WETH9() (common.Address, error) { - return _InonfungibleToken.Contract.WETH9(&_InonfungibleToken.CallOpts) -} - -// WETH9 is a free data retrieval call binding the contract method 0x4aa4a4fc. -// -// Solidity: function WETH9() view returns(address) -func (_InonfungibleToken *InonfungibleTokenCallerSession) WETH9() (common.Address, error) { - return _InonfungibleToken.Contract.WETH9(&_InonfungibleToken.CallOpts) -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address owner) view returns(uint256 balance) -func (_InonfungibleToken *InonfungibleTokenCaller) BalanceOf(opts *bind.CallOpts, owner common.Address) (*big.Int, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "balanceOf", owner) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address owner) view returns(uint256 balance) -func (_InonfungibleToken *InonfungibleTokenSession) BalanceOf(owner common.Address) (*big.Int, error) { - return _InonfungibleToken.Contract.BalanceOf(&_InonfungibleToken.CallOpts, owner) -} - -// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. -// -// Solidity: function balanceOf(address owner) view returns(uint256 balance) -func (_InonfungibleToken *InonfungibleTokenCallerSession) BalanceOf(owner common.Address) (*big.Int, error) { - return _InonfungibleToken.Contract.BalanceOf(&_InonfungibleToken.CallOpts, owner) -} - -// Factory is a free data retrieval call binding the contract method 0xc45a0155. -// -// Solidity: function factory() view returns(address) -func (_InonfungibleToken *InonfungibleTokenCaller) Factory(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "factory") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// Factory is a free data retrieval call binding the contract method 0xc45a0155. -// -// Solidity: function factory() view returns(address) -func (_InonfungibleToken *InonfungibleTokenSession) Factory() (common.Address, error) { - return _InonfungibleToken.Contract.Factory(&_InonfungibleToken.CallOpts) -} - -// Factory is a free data retrieval call binding the contract method 0xc45a0155. -// -// Solidity: function factory() view returns(address) -func (_InonfungibleToken *InonfungibleTokenCallerSession) Factory() (common.Address, error) { - return _InonfungibleToken.Contract.Factory(&_InonfungibleToken.CallOpts) -} - -// GetApproved is a free data retrieval call binding the contract method 0x081812fc. -// -// Solidity: function getApproved(uint256 tokenId) view returns(address operator) -func (_InonfungibleToken *InonfungibleTokenCaller) GetApproved(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "getApproved", tokenId) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// GetApproved is a free data retrieval call binding the contract method 0x081812fc. -// -// Solidity: function getApproved(uint256 tokenId) view returns(address operator) -func (_InonfungibleToken *InonfungibleTokenSession) GetApproved(tokenId *big.Int) (common.Address, error) { - return _InonfungibleToken.Contract.GetApproved(&_InonfungibleToken.CallOpts, tokenId) -} - -// GetApproved is a free data retrieval call binding the contract method 0x081812fc. -// -// Solidity: function getApproved(uint256 tokenId) view returns(address operator) -func (_InonfungibleToken *InonfungibleTokenCallerSession) GetApproved(tokenId *big.Int) (common.Address, error) { - return _InonfungibleToken.Contract.GetApproved(&_InonfungibleToken.CallOpts, tokenId) -} - -// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. -// -// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) -func (_InonfungibleToken *InonfungibleTokenCaller) IsApprovedForAll(opts *bind.CallOpts, owner common.Address, operator common.Address) (bool, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "isApprovedForAll", owner, operator) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. -// -// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) -func (_InonfungibleToken *InonfungibleTokenSession) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { - return _InonfungibleToken.Contract.IsApprovedForAll(&_InonfungibleToken.CallOpts, owner, operator) -} - -// IsApprovedForAll is a free data retrieval call binding the contract method 0xe985e9c5. -// -// Solidity: function isApprovedForAll(address owner, address operator) view returns(bool) -func (_InonfungibleToken *InonfungibleTokenCallerSession) IsApprovedForAll(owner common.Address, operator common.Address) (bool, error) { - return _InonfungibleToken.Contract.IsApprovedForAll(&_InonfungibleToken.CallOpts, owner, operator) -} - -// Name is a free data retrieval call binding the contract method 0x06fdde03. -// -// Solidity: function name() view returns(string) -func (_InonfungibleToken *InonfungibleTokenCaller) Name(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "name") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// Name is a free data retrieval call binding the contract method 0x06fdde03. -// -// Solidity: function name() view returns(string) -func (_InonfungibleToken *InonfungibleTokenSession) Name() (string, error) { - return _InonfungibleToken.Contract.Name(&_InonfungibleToken.CallOpts) -} - -// Name is a free data retrieval call binding the contract method 0x06fdde03. -// -// Solidity: function name() view returns(string) -func (_InonfungibleToken *InonfungibleTokenCallerSession) Name() (string, error) { - return _InonfungibleToken.Contract.Name(&_InonfungibleToken.CallOpts) -} - -// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. -// -// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) -func (_InonfungibleToken *InonfungibleTokenCaller) OwnerOf(opts *bind.CallOpts, tokenId *big.Int) (common.Address, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "ownerOf", tokenId) - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. -// -// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) -func (_InonfungibleToken *InonfungibleTokenSession) OwnerOf(tokenId *big.Int) (common.Address, error) { - return _InonfungibleToken.Contract.OwnerOf(&_InonfungibleToken.CallOpts, tokenId) -} - -// OwnerOf is a free data retrieval call binding the contract method 0x6352211e. -// -// Solidity: function ownerOf(uint256 tokenId) view returns(address owner) -func (_InonfungibleToken *InonfungibleTokenCallerSession) OwnerOf(tokenId *big.Int) (common.Address, error) { - return _InonfungibleToken.Contract.OwnerOf(&_InonfungibleToken.CallOpts, tokenId) -} - -// Positions is a free data retrieval call binding the contract method 0x99fbab88. -// -// Solidity: function positions(uint256 tokenId) view returns(uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1) -func (_InonfungibleToken *InonfungibleTokenCaller) Positions(opts *bind.CallOpts, tokenId *big.Int) (struct { - Nonce *big.Int - Operator common.Address - Token0 common.Address - Token1 common.Address - Fee *big.Int - TickLower *big.Int - TickUpper *big.Int - Liquidity *big.Int - FeeGrowthInside0LastX128 *big.Int - FeeGrowthInside1LastX128 *big.Int - TokensOwed0 *big.Int - TokensOwed1 *big.Int -}, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "positions", tokenId) - - outstruct := new(struct { - Nonce *big.Int - Operator common.Address - Token0 common.Address - Token1 common.Address - Fee *big.Int - TickLower *big.Int - TickUpper *big.Int - Liquidity *big.Int - FeeGrowthInside0LastX128 *big.Int - FeeGrowthInside1LastX128 *big.Int - TokensOwed0 *big.Int - TokensOwed1 *big.Int - }) - if err != nil { - return *outstruct, err - } - - outstruct.Nonce = *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - outstruct.Operator = *abi.ConvertType(out[1], new(common.Address)).(*common.Address) - outstruct.Token0 = *abi.ConvertType(out[2], new(common.Address)).(*common.Address) - outstruct.Token1 = *abi.ConvertType(out[3], new(common.Address)).(*common.Address) - outstruct.Fee = *abi.ConvertType(out[4], new(*big.Int)).(**big.Int) - outstruct.TickLower = *abi.ConvertType(out[5], new(*big.Int)).(**big.Int) - outstruct.TickUpper = *abi.ConvertType(out[6], new(*big.Int)).(**big.Int) - outstruct.Liquidity = *abi.ConvertType(out[7], new(*big.Int)).(**big.Int) - outstruct.FeeGrowthInside0LastX128 = *abi.ConvertType(out[8], new(*big.Int)).(**big.Int) - outstruct.FeeGrowthInside1LastX128 = *abi.ConvertType(out[9], new(*big.Int)).(**big.Int) - outstruct.TokensOwed0 = *abi.ConvertType(out[10], new(*big.Int)).(**big.Int) - outstruct.TokensOwed1 = *abi.ConvertType(out[11], new(*big.Int)).(**big.Int) - - return *outstruct, err - -} - -// Positions is a free data retrieval call binding the contract method 0x99fbab88. -// -// Solidity: function positions(uint256 tokenId) view returns(uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1) -func (_InonfungibleToken *InonfungibleTokenSession) Positions(tokenId *big.Int) (struct { - Nonce *big.Int - Operator common.Address - Token0 common.Address - Token1 common.Address - Fee *big.Int - TickLower *big.Int - TickUpper *big.Int - Liquidity *big.Int - FeeGrowthInside0LastX128 *big.Int - FeeGrowthInside1LastX128 *big.Int - TokensOwed0 *big.Int - TokensOwed1 *big.Int -}, error) { - return _InonfungibleToken.Contract.Positions(&_InonfungibleToken.CallOpts, tokenId) -} - -// Positions is a free data retrieval call binding the contract method 0x99fbab88. -// -// Solidity: function positions(uint256 tokenId) view returns(uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1) -func (_InonfungibleToken *InonfungibleTokenCallerSession) Positions(tokenId *big.Int) (struct { - Nonce *big.Int - Operator common.Address - Token0 common.Address - Token1 common.Address - Fee *big.Int - TickLower *big.Int - TickUpper *big.Int - Liquidity *big.Int - FeeGrowthInside0LastX128 *big.Int - FeeGrowthInside1LastX128 *big.Int - TokensOwed0 *big.Int - TokensOwed1 *big.Int -}, error) { - return _InonfungibleToken.Contract.Positions(&_InonfungibleToken.CallOpts, tokenId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_InonfungibleToken *InonfungibleTokenCaller) SupportsInterface(opts *bind.CallOpts, interfaceId [4]byte) (bool, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "supportsInterface", interfaceId) - - if err != nil { - return *new(bool), err - } - - out0 := *abi.ConvertType(out[0], new(bool)).(*bool) - - return out0, err - -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_InonfungibleToken *InonfungibleTokenSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _InonfungibleToken.Contract.SupportsInterface(&_InonfungibleToken.CallOpts, interfaceId) -} - -// SupportsInterface is a free data retrieval call binding the contract method 0x01ffc9a7. -// -// Solidity: function supportsInterface(bytes4 interfaceId) view returns(bool) -func (_InonfungibleToken *InonfungibleTokenCallerSession) SupportsInterface(interfaceId [4]byte) (bool, error) { - return _InonfungibleToken.Contract.SupportsInterface(&_InonfungibleToken.CallOpts, interfaceId) -} - -// Symbol is a free data retrieval call binding the contract method 0x95d89b41. -// -// Solidity: function symbol() view returns(string) -func (_InonfungibleToken *InonfungibleTokenCaller) Symbol(opts *bind.CallOpts) (string, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "symbol") - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// Symbol is a free data retrieval call binding the contract method 0x95d89b41. -// -// Solidity: function symbol() view returns(string) -func (_InonfungibleToken *InonfungibleTokenSession) Symbol() (string, error) { - return _InonfungibleToken.Contract.Symbol(&_InonfungibleToken.CallOpts) -} - -// Symbol is a free data retrieval call binding the contract method 0x95d89b41. -// -// Solidity: function symbol() view returns(string) -func (_InonfungibleToken *InonfungibleTokenCallerSession) Symbol() (string, error) { - return _InonfungibleToken.Contract.Symbol(&_InonfungibleToken.CallOpts) -} - -// TokenByIndex is a free data retrieval call binding the contract method 0x4f6ccce7. -// -// Solidity: function tokenByIndex(uint256 index) view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenCaller) TokenByIndex(opts *bind.CallOpts, index *big.Int) (*big.Int, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "tokenByIndex", index) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// TokenByIndex is a free data retrieval call binding the contract method 0x4f6ccce7. -// -// Solidity: function tokenByIndex(uint256 index) view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenSession) TokenByIndex(index *big.Int) (*big.Int, error) { - return _InonfungibleToken.Contract.TokenByIndex(&_InonfungibleToken.CallOpts, index) -} - -// TokenByIndex is a free data retrieval call binding the contract method 0x4f6ccce7. -// -// Solidity: function tokenByIndex(uint256 index) view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenCallerSession) TokenByIndex(index *big.Int) (*big.Int, error) { - return _InonfungibleToken.Contract.TokenByIndex(&_InonfungibleToken.CallOpts, index) -} - -// TokenOfOwnerByIndex is a free data retrieval call binding the contract method 0x2f745c59. -// -// Solidity: function tokenOfOwnerByIndex(address owner, uint256 index) view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenCaller) TokenOfOwnerByIndex(opts *bind.CallOpts, owner common.Address, index *big.Int) (*big.Int, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "tokenOfOwnerByIndex", owner, index) - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// TokenOfOwnerByIndex is a free data retrieval call binding the contract method 0x2f745c59. -// -// Solidity: function tokenOfOwnerByIndex(address owner, uint256 index) view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenSession) TokenOfOwnerByIndex(owner common.Address, index *big.Int) (*big.Int, error) { - return _InonfungibleToken.Contract.TokenOfOwnerByIndex(&_InonfungibleToken.CallOpts, owner, index) -} - -// TokenOfOwnerByIndex is a free data retrieval call binding the contract method 0x2f745c59. -// -// Solidity: function tokenOfOwnerByIndex(address owner, uint256 index) view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenCallerSession) TokenOfOwnerByIndex(owner common.Address, index *big.Int) (*big.Int, error) { - return _InonfungibleToken.Contract.TokenOfOwnerByIndex(&_InonfungibleToken.CallOpts, owner, index) -} - -// TokenURI is a free data retrieval call binding the contract method 0xc87b56dd. -// -// Solidity: function tokenURI(uint256 tokenId) view returns(string) -func (_InonfungibleToken *InonfungibleTokenCaller) TokenURI(opts *bind.CallOpts, tokenId *big.Int) (string, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "tokenURI", tokenId) - - if err != nil { - return *new(string), err - } - - out0 := *abi.ConvertType(out[0], new(string)).(*string) - - return out0, err - -} - -// TokenURI is a free data retrieval call binding the contract method 0xc87b56dd. -// -// Solidity: function tokenURI(uint256 tokenId) view returns(string) -func (_InonfungibleToken *InonfungibleTokenSession) TokenURI(tokenId *big.Int) (string, error) { - return _InonfungibleToken.Contract.TokenURI(&_InonfungibleToken.CallOpts, tokenId) -} - -// TokenURI is a free data retrieval call binding the contract method 0xc87b56dd. -// -// Solidity: function tokenURI(uint256 tokenId) view returns(string) -func (_InonfungibleToken *InonfungibleTokenCallerSession) TokenURI(tokenId *big.Int) (string, error) { - return _InonfungibleToken.Contract.TokenURI(&_InonfungibleToken.CallOpts, tokenId) -} - -// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. -// -// Solidity: function totalSupply() view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _InonfungibleToken.contract.Call(opts, &out, "totalSupply") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. -// -// Solidity: function totalSupply() view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenSession) TotalSupply() (*big.Int, error) { - return _InonfungibleToken.Contract.TotalSupply(&_InonfungibleToken.CallOpts) -} - -// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. -// -// Solidity: function totalSupply() view returns(uint256) -func (_InonfungibleToken *InonfungibleTokenCallerSession) TotalSupply() (*big.Int, error) { - return _InonfungibleToken.Contract.TotalSupply(&_InonfungibleToken.CallOpts) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) Approve(opts *bind.TransactOpts, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "approve", to, tokenId) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenSession) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Approve(&_InonfungibleToken.TransactOpts, to, tokenId) -} - -// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. -// -// Solidity: function approve(address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) Approve(to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Approve(&_InonfungibleToken.TransactOpts, to, tokenId) -} - -// Burn is a paid mutator transaction binding the contract method 0x42966c68. -// -// Solidity: function burn(uint256 tokenId) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) Burn(opts *bind.TransactOpts, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "burn", tokenId) -} - -// Burn is a paid mutator transaction binding the contract method 0x42966c68. -// -// Solidity: function burn(uint256 tokenId) payable returns() -func (_InonfungibleToken *InonfungibleTokenSession) Burn(tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Burn(&_InonfungibleToken.TransactOpts, tokenId) -} - -// Burn is a paid mutator transaction binding the contract method 0x42966c68. -// -// Solidity: function burn(uint256 tokenId) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) Burn(tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Burn(&_InonfungibleToken.TransactOpts, tokenId) -} - -// Collect is a paid mutator transaction binding the contract method 0xfc6f7865. -// -// Solidity: function collect((uint256,address,uint128,uint128) params) payable returns(uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactor) Collect(opts *bind.TransactOpts, params INonfungiblePositionManagerCollectParams) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "collect", params) -} - -// Collect is a paid mutator transaction binding the contract method 0xfc6f7865. -// -// Solidity: function collect((uint256,address,uint128,uint128) params) payable returns(uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenSession) Collect(params INonfungiblePositionManagerCollectParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Collect(&_InonfungibleToken.TransactOpts, params) -} - -// Collect is a paid mutator transaction binding the contract method 0xfc6f7865. -// -// Solidity: function collect((uint256,address,uint128,uint128) params) payable returns(uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactorSession) Collect(params INonfungiblePositionManagerCollectParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Collect(&_InonfungibleToken.TransactOpts, params) -} - -// CreateAndInitializePoolIfNecessary is a paid mutator transaction binding the contract method 0x13ead562. -// -// Solidity: function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96) payable returns(address pool) -func (_InonfungibleToken *InonfungibleTokenTransactor) CreateAndInitializePoolIfNecessary(opts *bind.TransactOpts, token0 common.Address, token1 common.Address, fee *big.Int, sqrtPriceX96 *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "createAndInitializePoolIfNecessary", token0, token1, fee, sqrtPriceX96) -} - -// CreateAndInitializePoolIfNecessary is a paid mutator transaction binding the contract method 0x13ead562. -// -// Solidity: function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96) payable returns(address pool) -func (_InonfungibleToken *InonfungibleTokenSession) CreateAndInitializePoolIfNecessary(token0 common.Address, token1 common.Address, fee *big.Int, sqrtPriceX96 *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.CreateAndInitializePoolIfNecessary(&_InonfungibleToken.TransactOpts, token0, token1, fee, sqrtPriceX96) -} - -// CreateAndInitializePoolIfNecessary is a paid mutator transaction binding the contract method 0x13ead562. -// -// Solidity: function createAndInitializePoolIfNecessary(address token0, address token1, uint24 fee, uint160 sqrtPriceX96) payable returns(address pool) -func (_InonfungibleToken *InonfungibleTokenTransactorSession) CreateAndInitializePoolIfNecessary(token0 common.Address, token1 common.Address, fee *big.Int, sqrtPriceX96 *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.CreateAndInitializePoolIfNecessary(&_InonfungibleToken.TransactOpts, token0, token1, fee, sqrtPriceX96) -} - -// DecreaseLiquidity is a paid mutator transaction binding the contract method 0x0c49ccbe. -// -// Solidity: function decreaseLiquidity((uint256,uint128,uint256,uint256,uint256) params) payable returns(uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactor) DecreaseLiquidity(opts *bind.TransactOpts, params INonfungiblePositionManagerDecreaseLiquidityParams) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "decreaseLiquidity", params) -} - -// DecreaseLiquidity is a paid mutator transaction binding the contract method 0x0c49ccbe. -// -// Solidity: function decreaseLiquidity((uint256,uint128,uint256,uint256,uint256) params) payable returns(uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenSession) DecreaseLiquidity(params INonfungiblePositionManagerDecreaseLiquidityParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.DecreaseLiquidity(&_InonfungibleToken.TransactOpts, params) -} - -// DecreaseLiquidity is a paid mutator transaction binding the contract method 0x0c49ccbe. -// -// Solidity: function decreaseLiquidity((uint256,uint128,uint256,uint256,uint256) params) payable returns(uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactorSession) DecreaseLiquidity(params INonfungiblePositionManagerDecreaseLiquidityParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.DecreaseLiquidity(&_InonfungibleToken.TransactOpts, params) -} - -// IncreaseLiquidity is a paid mutator transaction binding the contract method 0x219f5d17. -// -// Solidity: function increaseLiquidity((uint256,uint256,uint256,uint256,uint256,uint256) params) payable returns(uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactor) IncreaseLiquidity(opts *bind.TransactOpts, params INonfungiblePositionManagerIncreaseLiquidityParams) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "increaseLiquidity", params) -} - -// IncreaseLiquidity is a paid mutator transaction binding the contract method 0x219f5d17. -// -// Solidity: function increaseLiquidity((uint256,uint256,uint256,uint256,uint256,uint256) params) payable returns(uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenSession) IncreaseLiquidity(params INonfungiblePositionManagerIncreaseLiquidityParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.IncreaseLiquidity(&_InonfungibleToken.TransactOpts, params) -} - -// IncreaseLiquidity is a paid mutator transaction binding the contract method 0x219f5d17. -// -// Solidity: function increaseLiquidity((uint256,uint256,uint256,uint256,uint256,uint256) params) payable returns(uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactorSession) IncreaseLiquidity(params INonfungiblePositionManagerIncreaseLiquidityParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.IncreaseLiquidity(&_InonfungibleToken.TransactOpts, params) -} - -// Mint is a paid mutator transaction binding the contract method 0x88316456. -// -// Solidity: function mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256) params) payable returns(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactor) Mint(opts *bind.TransactOpts, params INonfungiblePositionManagerMintParams) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "mint", params) -} - -// Mint is a paid mutator transaction binding the contract method 0x88316456. -// -// Solidity: function mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256) params) payable returns(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenSession) Mint(params INonfungiblePositionManagerMintParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Mint(&_InonfungibleToken.TransactOpts, params) -} - -// Mint is a paid mutator transaction binding the contract method 0x88316456. -// -// Solidity: function mint((address,address,uint24,int24,int24,uint256,uint256,uint256,uint256,address,uint256) params) payable returns(uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenTransactorSession) Mint(params INonfungiblePositionManagerMintParams) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Mint(&_InonfungibleToken.TransactOpts, params) -} - -// Permit is a paid mutator transaction binding the contract method 0x7ac2ff7b. -// -// Solidity: function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) Permit(opts *bind.TransactOpts, spender common.Address, tokenId *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "permit", spender, tokenId, deadline, v, r, s) -} - -// Permit is a paid mutator transaction binding the contract method 0x7ac2ff7b. -// -// Solidity: function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) payable returns() -func (_InonfungibleToken *InonfungibleTokenSession) Permit(spender common.Address, tokenId *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Permit(&_InonfungibleToken.TransactOpts, spender, tokenId, deadline, v, r, s) -} - -// Permit is a paid mutator transaction binding the contract method 0x7ac2ff7b. -// -// Solidity: function permit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) Permit(spender common.Address, tokenId *big.Int, deadline *big.Int, v uint8, r [32]byte, s [32]byte) (*types.Transaction, error) { - return _InonfungibleToken.Contract.Permit(&_InonfungibleToken.TransactOpts, spender, tokenId, deadline, v, r, s) -} - -// RefundETH is a paid mutator transaction binding the contract method 0x12210e8a. -// -// Solidity: function refundETH() payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) RefundETH(opts *bind.TransactOpts) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "refundETH") -} - -// RefundETH is a paid mutator transaction binding the contract method 0x12210e8a. -// -// Solidity: function refundETH() payable returns() -func (_InonfungibleToken *InonfungibleTokenSession) RefundETH() (*types.Transaction, error) { - return _InonfungibleToken.Contract.RefundETH(&_InonfungibleToken.TransactOpts) -} - -// RefundETH is a paid mutator transaction binding the contract method 0x12210e8a. -// -// Solidity: function refundETH() payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) RefundETH() (*types.Transaction, error) { - return _InonfungibleToken.Contract.RefundETH(&_InonfungibleToken.TransactOpts) -} - -// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) SafeTransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "safeTransferFrom", from, to, tokenId) -} - -// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenSession) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SafeTransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) -} - -// SafeTransferFrom is a paid mutator transaction binding the contract method 0x42842e0e. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) SafeTransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SafeTransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) -} - -// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) SafeTransferFrom0(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "safeTransferFrom0", from, to, tokenId, data) -} - -// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() -func (_InonfungibleToken *InonfungibleTokenSession) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SafeTransferFrom0(&_InonfungibleToken.TransactOpts, from, to, tokenId, data) -} - -// SafeTransferFrom0 is a paid mutator transaction binding the contract method 0xb88d4fde. -// -// Solidity: function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) SafeTransferFrom0(from common.Address, to common.Address, tokenId *big.Int, data []byte) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SafeTransferFrom0(&_InonfungibleToken.TransactOpts, from, to, tokenId, data) -} - -// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. -// -// Solidity: function setApprovalForAll(address operator, bool _approved) returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) SetApprovalForAll(opts *bind.TransactOpts, operator common.Address, _approved bool) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "setApprovalForAll", operator, _approved) -} - -// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. -// -// Solidity: function setApprovalForAll(address operator, bool _approved) returns() -func (_InonfungibleToken *InonfungibleTokenSession) SetApprovalForAll(operator common.Address, _approved bool) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SetApprovalForAll(&_InonfungibleToken.TransactOpts, operator, _approved) -} - -// SetApprovalForAll is a paid mutator transaction binding the contract method 0xa22cb465. -// -// Solidity: function setApprovalForAll(address operator, bool _approved) returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) SetApprovalForAll(operator common.Address, _approved bool) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SetApprovalForAll(&_InonfungibleToken.TransactOpts, operator, _approved) -} - -// SweepToken is a paid mutator transaction binding the contract method 0xdf2ab5bb. -// -// Solidity: function sweepToken(address token, uint256 amountMinimum, address recipient) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) SweepToken(opts *bind.TransactOpts, token common.Address, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "sweepToken", token, amountMinimum, recipient) -} - -// SweepToken is a paid mutator transaction binding the contract method 0xdf2ab5bb. -// -// Solidity: function sweepToken(address token, uint256 amountMinimum, address recipient) payable returns() -func (_InonfungibleToken *InonfungibleTokenSession) SweepToken(token common.Address, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SweepToken(&_InonfungibleToken.TransactOpts, token, amountMinimum, recipient) -} - -// SweepToken is a paid mutator transaction binding the contract method 0xdf2ab5bb. -// -// Solidity: function sweepToken(address token, uint256 amountMinimum, address recipient) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) SweepToken(token common.Address, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { - return _InonfungibleToken.Contract.SweepToken(&_InonfungibleToken.TransactOpts, token, amountMinimum, recipient) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "transferFrom", from, to, tokenId) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenSession) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.TransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) -} - -// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd. -// -// Solidity: function transferFrom(address from, address to, uint256 tokenId) returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) TransferFrom(from common.Address, to common.Address, tokenId *big.Int) (*types.Transaction, error) { - return _InonfungibleToken.Contract.TransferFrom(&_InonfungibleToken.TransactOpts, from, to, tokenId) -} - -// UnwrapWETH9 is a paid mutator transaction binding the contract method 0x49404b7c. -// -// Solidity: function unwrapWETH9(uint256 amountMinimum, address recipient) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactor) UnwrapWETH9(opts *bind.TransactOpts, amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { - return _InonfungibleToken.contract.Transact(opts, "unwrapWETH9", amountMinimum, recipient) -} - -// UnwrapWETH9 is a paid mutator transaction binding the contract method 0x49404b7c. -// -// Solidity: function unwrapWETH9(uint256 amountMinimum, address recipient) payable returns() -func (_InonfungibleToken *InonfungibleTokenSession) UnwrapWETH9(amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { - return _InonfungibleToken.Contract.UnwrapWETH9(&_InonfungibleToken.TransactOpts, amountMinimum, recipient) -} - -// UnwrapWETH9 is a paid mutator transaction binding the contract method 0x49404b7c. -// -// Solidity: function unwrapWETH9(uint256 amountMinimum, address recipient) payable returns() -func (_InonfungibleToken *InonfungibleTokenTransactorSession) UnwrapWETH9(amountMinimum *big.Int, recipient common.Address) (*types.Transaction, error) { - return _InonfungibleToken.Contract.UnwrapWETH9(&_InonfungibleToken.TransactOpts, amountMinimum, recipient) -} - -// InonfungibleTokenApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the InonfungibleToken contract. -type InonfungibleTokenApprovalIterator struct { - Event *InonfungibleTokenApproval // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InonfungibleTokenApprovalIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenApproval) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenApproval) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InonfungibleTokenApprovalIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InonfungibleTokenApprovalIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InonfungibleTokenApproval represents a Approval event raised by the InonfungibleToken contract. -type InonfungibleTokenApproval struct { - Owner common.Address - Approved common.Address - TokenId *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) -func (_InonfungibleToken *InonfungibleTokenFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, approved []common.Address, tokenId []*big.Int) (*InonfungibleTokenApprovalIterator, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var approvedRule []interface{} - for _, approvedItem := range approved { - approvedRule = append(approvedRule, approvedItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) - if err != nil { - return nil, err - } - return &InonfungibleTokenApprovalIterator{contract: _InonfungibleToken.contract, event: "Approval", logs: logs, sub: sub}, nil -} - -// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) -func (_InonfungibleToken *InonfungibleTokenFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenApproval, owner []common.Address, approved []common.Address, tokenId []*big.Int) (event.Subscription, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var approvedRule []interface{} - for _, approvedItem := range approved { - approvedRule = append(approvedRule, approvedItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "Approval", ownerRule, approvedRule, tokenIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InonfungibleTokenApproval) - if err := _InonfungibleToken.contract.UnpackLog(event, "Approval", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925. -// -// Solidity: event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId) -func (_InonfungibleToken *InonfungibleTokenFilterer) ParseApproval(log types.Log) (*InonfungibleTokenApproval, error) { - event := new(InonfungibleTokenApproval) - if err := _InonfungibleToken.contract.UnpackLog(event, "Approval", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InonfungibleTokenApprovalForAllIterator is returned from FilterApprovalForAll and is used to iterate over the raw logs and unpacked data for ApprovalForAll events raised by the InonfungibleToken contract. -type InonfungibleTokenApprovalForAllIterator struct { - Event *InonfungibleTokenApprovalForAll // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InonfungibleTokenApprovalForAllIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenApprovalForAll) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenApprovalForAll) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InonfungibleTokenApprovalForAllIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InonfungibleTokenApprovalForAllIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InonfungibleTokenApprovalForAll represents a ApprovalForAll event raised by the InonfungibleToken contract. -type InonfungibleTokenApprovalForAll struct { - Owner common.Address - Operator common.Address - Approved bool - Raw types.Log // Blockchain specific contextual infos -} - -// FilterApprovalForAll is a free log retrieval operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. -// -// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) -func (_InonfungibleToken *InonfungibleTokenFilterer) FilterApprovalForAll(opts *bind.FilterOpts, owner []common.Address, operator []common.Address) (*InonfungibleTokenApprovalForAllIterator, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var operatorRule []interface{} - for _, operatorItem := range operator { - operatorRule = append(operatorRule, operatorItem) - } - - logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "ApprovalForAll", ownerRule, operatorRule) - if err != nil { - return nil, err - } - return &InonfungibleTokenApprovalForAllIterator{contract: _InonfungibleToken.contract, event: "ApprovalForAll", logs: logs, sub: sub}, nil -} - -// WatchApprovalForAll is a free log subscription operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. -// -// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) -func (_InonfungibleToken *InonfungibleTokenFilterer) WatchApprovalForAll(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenApprovalForAll, owner []common.Address, operator []common.Address) (event.Subscription, error) { - - var ownerRule []interface{} - for _, ownerItem := range owner { - ownerRule = append(ownerRule, ownerItem) - } - var operatorRule []interface{} - for _, operatorItem := range operator { - operatorRule = append(operatorRule, operatorItem) - } - - logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "ApprovalForAll", ownerRule, operatorRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InonfungibleTokenApprovalForAll) - if err := _InonfungibleToken.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseApprovalForAll is a log parse operation binding the contract event 0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31. -// -// Solidity: event ApprovalForAll(address indexed owner, address indexed operator, bool approved) -func (_InonfungibleToken *InonfungibleTokenFilterer) ParseApprovalForAll(log types.Log) (*InonfungibleTokenApprovalForAll, error) { - event := new(InonfungibleTokenApprovalForAll) - if err := _InonfungibleToken.contract.UnpackLog(event, "ApprovalForAll", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InonfungibleTokenCollectIterator is returned from FilterCollect and is used to iterate over the raw logs and unpacked data for Collect events raised by the InonfungibleToken contract. -type InonfungibleTokenCollectIterator struct { - Event *InonfungibleTokenCollect // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InonfungibleTokenCollectIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenCollect) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenCollect) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InonfungibleTokenCollectIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InonfungibleTokenCollectIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InonfungibleTokenCollect represents a Collect event raised by the InonfungibleToken contract. -type InonfungibleTokenCollect struct { - TokenId *big.Int - Recipient common.Address - Amount0 *big.Int - Amount1 *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterCollect is a free log retrieval operation binding the contract event 0x40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f01. -// -// Solidity: event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) FilterCollect(opts *bind.FilterOpts, tokenId []*big.Int) (*InonfungibleTokenCollectIterator, error) { - - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "Collect", tokenIdRule) - if err != nil { - return nil, err - } - return &InonfungibleTokenCollectIterator{contract: _InonfungibleToken.contract, event: "Collect", logs: logs, sub: sub}, nil -} - -// WatchCollect is a free log subscription operation binding the contract event 0x40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f01. -// -// Solidity: event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) WatchCollect(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenCollect, tokenId []*big.Int) (event.Subscription, error) { - - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "Collect", tokenIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InonfungibleTokenCollect) - if err := _InonfungibleToken.contract.UnpackLog(event, "Collect", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseCollect is a log parse operation binding the contract event 0x40d0efd1a53d60ecbf40971b9daf7dc90178c3aadc7aab1765632738fa8b8f01. -// -// Solidity: event Collect(uint256 indexed tokenId, address recipient, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) ParseCollect(log types.Log) (*InonfungibleTokenCollect, error) { - event := new(InonfungibleTokenCollect) - if err := _InonfungibleToken.contract.UnpackLog(event, "Collect", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InonfungibleTokenDecreaseLiquidityIterator is returned from FilterDecreaseLiquidity and is used to iterate over the raw logs and unpacked data for DecreaseLiquidity events raised by the InonfungibleToken contract. -type InonfungibleTokenDecreaseLiquidityIterator struct { - Event *InonfungibleTokenDecreaseLiquidity // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InonfungibleTokenDecreaseLiquidityIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenDecreaseLiquidity) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenDecreaseLiquidity) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InonfungibleTokenDecreaseLiquidityIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InonfungibleTokenDecreaseLiquidityIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InonfungibleTokenDecreaseLiquidity represents a DecreaseLiquidity event raised by the InonfungibleToken contract. -type InonfungibleTokenDecreaseLiquidity struct { - TokenId *big.Int - Liquidity *big.Int - Amount0 *big.Int - Amount1 *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterDecreaseLiquidity is a free log retrieval operation binding the contract event 0x26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b4. -// -// Solidity: event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) FilterDecreaseLiquidity(opts *bind.FilterOpts, tokenId []*big.Int) (*InonfungibleTokenDecreaseLiquidityIterator, error) { - - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "DecreaseLiquidity", tokenIdRule) - if err != nil { - return nil, err - } - return &InonfungibleTokenDecreaseLiquidityIterator{contract: _InonfungibleToken.contract, event: "DecreaseLiquidity", logs: logs, sub: sub}, nil -} - -// WatchDecreaseLiquidity is a free log subscription operation binding the contract event 0x26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b4. -// -// Solidity: event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) WatchDecreaseLiquidity(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenDecreaseLiquidity, tokenId []*big.Int) (event.Subscription, error) { - - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "DecreaseLiquidity", tokenIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InonfungibleTokenDecreaseLiquidity) - if err := _InonfungibleToken.contract.UnpackLog(event, "DecreaseLiquidity", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseDecreaseLiquidity is a log parse operation binding the contract event 0x26f6a048ee9138f2c0ce266f322cb99228e8d619ae2bff30c67f8dcf9d2377b4. -// -// Solidity: event DecreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) ParseDecreaseLiquidity(log types.Log) (*InonfungibleTokenDecreaseLiquidity, error) { - event := new(InonfungibleTokenDecreaseLiquidity) - if err := _InonfungibleToken.contract.UnpackLog(event, "DecreaseLiquidity", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InonfungibleTokenIncreaseLiquidityIterator is returned from FilterIncreaseLiquidity and is used to iterate over the raw logs and unpacked data for IncreaseLiquidity events raised by the InonfungibleToken contract. -type InonfungibleTokenIncreaseLiquidityIterator struct { - Event *InonfungibleTokenIncreaseLiquidity // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InonfungibleTokenIncreaseLiquidityIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenIncreaseLiquidity) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenIncreaseLiquidity) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InonfungibleTokenIncreaseLiquidityIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InonfungibleTokenIncreaseLiquidityIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InonfungibleTokenIncreaseLiquidity represents a IncreaseLiquidity event raised by the InonfungibleToken contract. -type InonfungibleTokenIncreaseLiquidity struct { - TokenId *big.Int - Liquidity *big.Int - Amount0 *big.Int - Amount1 *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterIncreaseLiquidity is a free log retrieval operation binding the contract event 0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f. -// -// Solidity: event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) FilterIncreaseLiquidity(opts *bind.FilterOpts, tokenId []*big.Int) (*InonfungibleTokenIncreaseLiquidityIterator, error) { - - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "IncreaseLiquidity", tokenIdRule) - if err != nil { - return nil, err - } - return &InonfungibleTokenIncreaseLiquidityIterator{contract: _InonfungibleToken.contract, event: "IncreaseLiquidity", logs: logs, sub: sub}, nil -} - -// WatchIncreaseLiquidity is a free log subscription operation binding the contract event 0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f. -// -// Solidity: event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) WatchIncreaseLiquidity(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenIncreaseLiquidity, tokenId []*big.Int) (event.Subscription, error) { - - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "IncreaseLiquidity", tokenIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InonfungibleTokenIncreaseLiquidity) - if err := _InonfungibleToken.contract.UnpackLog(event, "IncreaseLiquidity", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseIncreaseLiquidity is a log parse operation binding the contract event 0x3067048beee31b25b2f1681f88dac838c8bba36af25bfb2b7cf7473a5847e35f. -// -// Solidity: event IncreaseLiquidity(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) -func (_InonfungibleToken *InonfungibleTokenFilterer) ParseIncreaseLiquidity(log types.Log) (*InonfungibleTokenIncreaseLiquidity, error) { - event := new(InonfungibleTokenIncreaseLiquidity) - if err := _InonfungibleToken.contract.UnpackLog(event, "IncreaseLiquidity", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - -// InonfungibleTokenTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the InonfungibleToken contract. -type InonfungibleTokenTransferIterator struct { - Event *InonfungibleTokenTransfer // Event containing the contract specifics and raw log - - contract *bind.BoundContract // Generic contract to use for unpacking event data - event string // Event name to use for unpacking event data - - logs chan types.Log // Log channel receiving the found contract events - sub ethereum.Subscription // Subscription for errors, completion and termination - done bool // Whether the subscription completed delivering logs - fail error // Occurred error to stop iteration -} - -// Next advances the iterator to the subsequent event, returning whether there -// are any more events found. In case of a retrieval or parsing error, false is -// returned and Error() can be queried for the exact failure. -func (it *InonfungibleTokenTransferIterator) Next() bool { - // If the iterator failed, stop iterating - if it.fail != nil { - return false - } - // If the iterator completed, deliver directly whatever's available - if it.done { - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenTransfer) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - default: - return false - } - } - // Iterator still in progress, wait for either a data or an error event - select { - case log := <-it.logs: - it.Event = new(InonfungibleTokenTransfer) - if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { - it.fail = err - return false - } - it.Event.Raw = log - return true - - case err := <-it.sub.Err(): - it.done = true - it.fail = err - return it.Next() - } -} - -// Error returns any retrieval or parsing error occurred during filtering. -func (it *InonfungibleTokenTransferIterator) Error() error { - return it.fail -} - -// Close terminates the iteration process, releasing any pending underlying -// resources. -func (it *InonfungibleTokenTransferIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -// InonfungibleTokenTransfer represents a Transfer event raised by the InonfungibleToken contract. -type InonfungibleTokenTransfer struct { - From common.Address - To common.Address - TokenId *big.Int - Raw types.Log // Blockchain specific contextual infos -} - -// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) -func (_InonfungibleToken *InonfungibleTokenFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address, tokenId []*big.Int) (*InonfungibleTokenTransferIterator, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.FilterLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) - if err != nil { - return nil, err - } - return &InonfungibleTokenTransferIterator{contract: _InonfungibleToken.contract, event: "Transfer", logs: logs, sub: sub}, nil -} - -// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) -func (_InonfungibleToken *InonfungibleTokenFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *InonfungibleTokenTransfer, from []common.Address, to []common.Address, tokenId []*big.Int) (event.Subscription, error) { - - var fromRule []interface{} - for _, fromItem := range from { - fromRule = append(fromRule, fromItem) - } - var toRule []interface{} - for _, toItem := range to { - toRule = append(toRule, toItem) - } - var tokenIdRule []interface{} - for _, tokenIdItem := range tokenId { - tokenIdRule = append(tokenIdRule, tokenIdItem) - } - - logs, sub, err := _InonfungibleToken.contract.WatchLogs(opts, "Transfer", fromRule, toRule, tokenIdRule) - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - // New log arrived, parse the event and forward to the user - event := new(InonfungibleTokenTransfer) - if err := _InonfungibleToken.contract.UnpackLog(event, "Transfer", log); err != nil { - return err - } - event.Raw = log - - select { - case sink <- event: - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - case err := <-sub.Err(): - return err - case <-quit: - return nil - } - } - }), nil -} - -// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef. -// -// Solidity: event Transfer(address indexed from, address indexed to, uint256 indexed tokenId) -func (_InonfungibleToken *InonfungibleTokenFilterer) ParseTransfer(log types.Log) (*InonfungibleTokenTransfer, error) { - event := new(InonfungibleTokenTransfer) - if err := _InonfungibleToken.contract.UnpackLog(event, "Transfer", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} diff --git a/relayer/chains/bitcoin/abi/iswap_router.go b/relayer/chains/bitcoin/abi/iswap_router.go deleted file mode 100644 index 6fdd712f..00000000 --- a/relayer/chains/bitcoin/abi/iswap_router.go +++ /dev/null @@ -1,328 +0,0 @@ -// Code generated - DO NOT EDIT. -// This file is a generated binding and any manual changes will be lost. - -package abi - -import ( - "errors" - "math/big" - "strings" - - ethereum "github.com/ethereum/go-ethereum" - "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/event" -) - -// Reference imports to suppress errors if they are not otherwise used. -var ( - _ = errors.New - _ = big.NewInt - _ = strings.NewReader - _ = ethereum.NotFound - _ = bind.Bind - _ = common.Big1 - _ = types.BloomLookup - _ = event.NewSubscription - _ = abi.ConvertType -) - -// ISwapRouterExactInputParams is an auto generated low-level Go binding around an user-defined struct. -type ISwapRouterExactInputParams struct { - Path []byte - Recipient common.Address - Deadline *big.Int - AmountIn *big.Int - AmountOutMinimum *big.Int -} - -// ISwapRouterExactInputSingleParams is an auto generated low-level Go binding around an user-defined struct. -type ISwapRouterExactInputSingleParams struct { - TokenIn common.Address - TokenOut common.Address - Fee *big.Int - Recipient common.Address - Deadline *big.Int - AmountIn *big.Int - AmountOutMinimum *big.Int - SqrtPriceLimitX96 *big.Int -} - -// ISwapRouterExactOutputParams is an auto generated low-level Go binding around an user-defined struct. -type ISwapRouterExactOutputParams struct { - Path []byte - Recipient common.Address - Deadline *big.Int - AmountOut *big.Int - AmountInMaximum *big.Int -} - -// ISwapRouterExactOutputSingleParams is an auto generated low-level Go binding around an user-defined struct. -type ISwapRouterExactOutputSingleParams struct { - TokenIn common.Address - TokenOut common.Address - Fee *big.Int - Recipient common.Address - Deadline *big.Int - AmountOut *big.Int - AmountInMaximum *big.Int - SqrtPriceLimitX96 *big.Int -} - -// IswaprouterMetaData contains all meta data concerning the Iswaprouter contract. -var IswaprouterMetaData = &bind.MetaData{ - ABI: "[{\"type\":\"function\",\"name\":\"exactInput\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactInputParams\",\"components\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOutMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"exactInputSingle\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactInputSingleParams\",\"components\":[{\"name\":\"tokenIn\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenOut\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOutMinimum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\",\"internalType\":\"uint160\"}]}],\"outputs\":[{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"exactOutput\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactOutputParams\",\"components\":[{\"name\":\"path\",\"type\":\"bytes\",\"internalType\":\"bytes\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountInMaximum\",\"type\":\"uint256\",\"internalType\":\"uint256\"}]}],\"outputs\":[{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"exactOutputSingle\",\"inputs\":[{\"name\":\"params\",\"type\":\"tuple\",\"internalType\":\"structISwapRouter.ExactOutputSingleParams\",\"components\":[{\"name\":\"tokenIn\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"tokenOut\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"fee\",\"type\":\"uint24\",\"internalType\":\"uint24\"},{\"name\":\"recipient\",\"type\":\"address\",\"internalType\":\"address\"},{\"name\":\"deadline\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountOut\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"amountInMaximum\",\"type\":\"uint256\",\"internalType\":\"uint256\"},{\"name\":\"sqrtPriceLimitX96\",\"type\":\"uint160\",\"internalType\":\"uint160\"}]}],\"outputs\":[{\"name\":\"amountIn\",\"type\":\"uint256\",\"internalType\":\"uint256\"}],\"stateMutability\":\"payable\"},{\"type\":\"function\",\"name\":\"uniswapV3SwapCallback\",\"inputs\":[{\"name\":\"amount0Delta\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"amount1Delta\",\"type\":\"int256\",\"internalType\":\"int256\"},{\"name\":\"data\",\"type\":\"bytes\",\"internalType\":\"bytes\"}],\"outputs\":[],\"stateMutability\":\"nonpayable\"}]", -} - -// IswaprouterABI is the input ABI used to generate the binding from. -// Deprecated: Use IswaprouterMetaData.ABI instead. -var IswaprouterABI = IswaprouterMetaData.ABI - -// Iswaprouter is an auto generated Go binding around an Ethereum contract. -type Iswaprouter struct { - IswaprouterCaller // Read-only binding to the contract - IswaprouterTransactor // Write-only binding to the contract - IswaprouterFilterer // Log filterer for contract events -} - -// IswaprouterCaller is an auto generated read-only Go binding around an Ethereum contract. -type IswaprouterCaller struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IswaprouterTransactor is an auto generated write-only Go binding around an Ethereum contract. -type IswaprouterTransactor struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IswaprouterFilterer is an auto generated log filtering Go binding around an Ethereum contract events. -type IswaprouterFilterer struct { - contract *bind.BoundContract // Generic contract wrapper for the low level calls -} - -// IswaprouterSession is an auto generated Go binding around an Ethereum contract, -// with pre-set call and transact options. -type IswaprouterSession struct { - Contract *Iswaprouter // Generic contract binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IswaprouterCallerSession is an auto generated read-only Go binding around an Ethereum contract, -// with pre-set call options. -type IswaprouterCallerSession struct { - Contract *IswaprouterCaller // Generic contract caller binding to set the session for - CallOpts bind.CallOpts // Call options to use throughout this session -} - -// IswaprouterTransactorSession is an auto generated write-only Go binding around an Ethereum contract, -// with pre-set transact options. -type IswaprouterTransactorSession struct { - Contract *IswaprouterTransactor // Generic contract transactor binding to set the session for - TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session -} - -// IswaprouterRaw is an auto generated low-level Go binding around an Ethereum contract. -type IswaprouterRaw struct { - Contract *Iswaprouter // Generic contract binding to access the raw methods on -} - -// IswaprouterCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. -type IswaprouterCallerRaw struct { - Contract *IswaprouterCaller // Generic read-only contract binding to access the raw methods on -} - -// IswaprouterTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. -type IswaprouterTransactorRaw struct { - Contract *IswaprouterTransactor // Generic write-only contract binding to access the raw methods on -} - -// NewIswaprouter creates a new instance of Iswaprouter, bound to a specific deployed contract. -func NewIswaprouter(address common.Address, backend bind.ContractBackend) (*Iswaprouter, error) { - contract, err := bindIswaprouter(address, backend, backend, backend) - if err != nil { - return nil, err - } - return &Iswaprouter{IswaprouterCaller: IswaprouterCaller{contract: contract}, IswaprouterTransactor: IswaprouterTransactor{contract: contract}, IswaprouterFilterer: IswaprouterFilterer{contract: contract}}, nil -} - -// NewIswaprouterCaller creates a new read-only instance of Iswaprouter, bound to a specific deployed contract. -func NewIswaprouterCaller(address common.Address, caller bind.ContractCaller) (*IswaprouterCaller, error) { - contract, err := bindIswaprouter(address, caller, nil, nil) - if err != nil { - return nil, err - } - return &IswaprouterCaller{contract: contract}, nil -} - -// NewIswaprouterTransactor creates a new write-only instance of Iswaprouter, bound to a specific deployed contract. -func NewIswaprouterTransactor(address common.Address, transactor bind.ContractTransactor) (*IswaprouterTransactor, error) { - contract, err := bindIswaprouter(address, nil, transactor, nil) - if err != nil { - return nil, err - } - return &IswaprouterTransactor{contract: contract}, nil -} - -// NewIswaprouterFilterer creates a new log filterer instance of Iswaprouter, bound to a specific deployed contract. -func NewIswaprouterFilterer(address common.Address, filterer bind.ContractFilterer) (*IswaprouterFilterer, error) { - contract, err := bindIswaprouter(address, nil, nil, filterer) - if err != nil { - return nil, err - } - return &IswaprouterFilterer{contract: contract}, nil -} - -// bindIswaprouter binds a generic wrapper to an already deployed contract. -func bindIswaprouter(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { - parsed, err := IswaprouterMetaData.GetAbi() - if err != nil { - return nil, err - } - return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Iswaprouter *IswaprouterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Iswaprouter.Contract.IswaprouterCaller.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Iswaprouter *IswaprouterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Iswaprouter.Contract.IswaprouterTransactor.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Iswaprouter *IswaprouterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Iswaprouter.Contract.IswaprouterTransactor.contract.Transact(opts, method, params...) -} - -// Call invokes the (constant) contract method with params as input values and -// sets the output to result. The result type might be a single field for simple -// returns, a slice of interfaces for anonymous returns and a struct for named -// returns. -func (_Iswaprouter *IswaprouterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { - return _Iswaprouter.Contract.contract.Call(opts, result, method, params...) -} - -// Transfer initiates a plain transaction to move funds to the contract, calling -// its default method if one is available. -func (_Iswaprouter *IswaprouterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { - return _Iswaprouter.Contract.contract.Transfer(opts) -} - -// Transact invokes the (paid) contract method with params as input values. -func (_Iswaprouter *IswaprouterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { - return _Iswaprouter.Contract.contract.Transact(opts, method, params...) -} - -// ExactInput is a paid mutator transaction binding the contract method 0xc04b8d59. -// -// Solidity: function exactInput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountOut) -func (_Iswaprouter *IswaprouterTransactor) ExactInput(opts *bind.TransactOpts, params ISwapRouterExactInputParams) (*types.Transaction, error) { - return _Iswaprouter.contract.Transact(opts, "exactInput", params) -} - -// ExactInput is a paid mutator transaction binding the contract method 0xc04b8d59. -// -// Solidity: function exactInput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountOut) -func (_Iswaprouter *IswaprouterSession) ExactInput(params ISwapRouterExactInputParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactInput(&_Iswaprouter.TransactOpts, params) -} - -// ExactInput is a paid mutator transaction binding the contract method 0xc04b8d59. -// -// Solidity: function exactInput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountOut) -func (_Iswaprouter *IswaprouterTransactorSession) ExactInput(params ISwapRouterExactInputParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactInput(&_Iswaprouter.TransactOpts, params) -} - -// ExactInputSingle is a paid mutator transaction binding the contract method 0x414bf389. -// -// Solidity: function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountOut) -func (_Iswaprouter *IswaprouterTransactor) ExactInputSingle(opts *bind.TransactOpts, params ISwapRouterExactInputSingleParams) (*types.Transaction, error) { - return _Iswaprouter.contract.Transact(opts, "exactInputSingle", params) -} - -// ExactInputSingle is a paid mutator transaction binding the contract method 0x414bf389. -// -// Solidity: function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountOut) -func (_Iswaprouter *IswaprouterSession) ExactInputSingle(params ISwapRouterExactInputSingleParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactInputSingle(&_Iswaprouter.TransactOpts, params) -} - -// ExactInputSingle is a paid mutator transaction binding the contract method 0x414bf389. -// -// Solidity: function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountOut) -func (_Iswaprouter *IswaprouterTransactorSession) ExactInputSingle(params ISwapRouterExactInputSingleParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactInputSingle(&_Iswaprouter.TransactOpts, params) -} - -// ExactOutput is a paid mutator transaction binding the contract method 0xf28c0498. -// -// Solidity: function exactOutput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountIn) -func (_Iswaprouter *IswaprouterTransactor) ExactOutput(opts *bind.TransactOpts, params ISwapRouterExactOutputParams) (*types.Transaction, error) { - return _Iswaprouter.contract.Transact(opts, "exactOutput", params) -} - -// ExactOutput is a paid mutator transaction binding the contract method 0xf28c0498. -// -// Solidity: function exactOutput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountIn) -func (_Iswaprouter *IswaprouterSession) ExactOutput(params ISwapRouterExactOutputParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactOutput(&_Iswaprouter.TransactOpts, params) -} - -// ExactOutput is a paid mutator transaction binding the contract method 0xf28c0498. -// -// Solidity: function exactOutput((bytes,address,uint256,uint256,uint256) params) payable returns(uint256 amountIn) -func (_Iswaprouter *IswaprouterTransactorSession) ExactOutput(params ISwapRouterExactOutputParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactOutput(&_Iswaprouter.TransactOpts, params) -} - -// ExactOutputSingle is a paid mutator transaction binding the contract method 0xdb3e2198. -// -// Solidity: function exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountIn) -func (_Iswaprouter *IswaprouterTransactor) ExactOutputSingle(opts *bind.TransactOpts, params ISwapRouterExactOutputSingleParams) (*types.Transaction, error) { - return _Iswaprouter.contract.Transact(opts, "exactOutputSingle", params) -} - -// ExactOutputSingle is a paid mutator transaction binding the contract method 0xdb3e2198. -// -// Solidity: function exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountIn) -func (_Iswaprouter *IswaprouterSession) ExactOutputSingle(params ISwapRouterExactOutputSingleParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactOutputSingle(&_Iswaprouter.TransactOpts, params) -} - -// ExactOutputSingle is a paid mutator transaction binding the contract method 0xdb3e2198. -// -// Solidity: function exactOutputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160) params) payable returns(uint256 amountIn) -func (_Iswaprouter *IswaprouterTransactorSession) ExactOutputSingle(params ISwapRouterExactOutputSingleParams) (*types.Transaction, error) { - return _Iswaprouter.Contract.ExactOutputSingle(&_Iswaprouter.TransactOpts, params) -} - -// UniswapV3SwapCallback is a paid mutator transaction binding the contract method 0xfa461e33. -// -// Solidity: function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes data) returns() -func (_Iswaprouter *IswaprouterTransactor) UniswapV3SwapCallback(opts *bind.TransactOpts, amount0Delta *big.Int, amount1Delta *big.Int, data []byte) (*types.Transaction, error) { - return _Iswaprouter.contract.Transact(opts, "uniswapV3SwapCallback", amount0Delta, amount1Delta, data) -} - -// UniswapV3SwapCallback is a paid mutator transaction binding the contract method 0xfa461e33. -// -// Solidity: function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes data) returns() -func (_Iswaprouter *IswaprouterSession) UniswapV3SwapCallback(amount0Delta *big.Int, amount1Delta *big.Int, data []byte) (*types.Transaction, error) { - return _Iswaprouter.Contract.UniswapV3SwapCallback(&_Iswaprouter.TransactOpts, amount0Delta, amount1Delta, data) -} - -// UniswapV3SwapCallback is a paid mutator transaction binding the contract method 0xfa461e33. -// -// Solidity: function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes data) returns() -func (_Iswaprouter *IswaprouterTransactorSession) UniswapV3SwapCallback(amount0Delta *big.Int, amount1Delta *big.Int, data []byte) (*types.Transaction, error) { - return _Iswaprouter.Contract.UniswapV3SwapCallback(&_Iswaprouter.TransactOpts, amount0Delta, amount1Delta, data) -} From cdcb90192a1caf998418fa89fb921628c7c55706 Mon Sep 17 00:00:00 2001 From: Shall Date: Mon, 18 Nov 2024 15:45:42 +0700 Subject: [PATCH 102/113] chore: update document and clean todo --- docs/bitcoin-relayer.md | 6 +- ...hx9a530643c071f15e8411eadd9f0b2ee5a871d37f | 22 ------- ...30643c071f15e8411eadd9f0b2ee5a871d37f.pass | 1 - relayer/chains/bitcoin/provider.go | 5 -- relayer/chains/evm/event_parse.go | 1 - relayer/chains/icon/client.go | 2 - relayer/chains/icon/keys.go | 21 +++---- relayer/chains/icon/route.go | 61 +++++++++---------- utils/multisig/multisig_test.go | 29 ++++----- 9 files changed, 58 insertions(+), 90 deletions(-) delete mode 100644 keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f delete mode 100644 keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md index da906cf0..d43b7eb9 100644 --- a/docs/bitcoin-relayer.md +++ b/docs/bitcoin-relayer.md @@ -106,7 +106,7 @@ bridgeMsg := BridgeDecodedMsg{ Message: XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "0:1", + TokenAddress: "0:0", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", From: "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su", Amount: new(big.Int).SetUint64(100000).Bytes(), @@ -235,3 +235,7 @@ RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start - With a tx send to the relayer multisig wallet, if the BTC amount of btc does not match with the BTC amount defined in the xcall message, and the relayer will refund the amount to the sender but minus the fee. - To stress test the system, you need to prepare a lot of BTC/RUNE utxos for the relayer multisig wallet, to make sure the system has enough utxos to process the transactions and avoid the issue of insufficient utxos. - In case Rollback transaction, the relayer will refund the same amount of BTC/RUNE that the user sent to the relayer multisig wallet. + +### How to build transaction + +To build transaction please check the file relayer/chains/bitcoin/provider_mainnet_test.go diff --git a/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f b/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f deleted file mode 100644 index c9fd2507..00000000 --- a/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f +++ /dev/null @@ -1,22 +0,0 @@ -{ - "version": 3, - "id": "c324d6d7-b1ed-41dd-bb7c-0a014628f121", - "address": "hx9a530643c071f15e8411eadd9f0b2ee5a871d37f", - "crypto": { - "ciphertext": "7353d2c1332d96511fb6ad5c74f710a6c30135431a04128fde1ed36dd5e7414c", - "cipherparams": { - "iv": "b5aa163de4de082065169a5acf5eb676" - }, - "cipher": "aes-128-ctr", - "kdf": "scrypt", - "kdfparams": { - "dklen": 32, - "salt": "7240a6dbcff5290551ca7a760f3c69fc6489b47fdc500fa803cc6e626865e253", - "n": 16384, - "r": 8, - "p": 1 - }, - "mac": "d6dc6d8f4cb4d6f703976eb79c92029b856230f0bb8ee142ac7af368ca324345" - }, - "coinType": "icx" -} \ No newline at end of file diff --git a/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass b/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass deleted file mode 100644 index 87b7e2fc..00000000 --- a/keystore/0x2.icon/hx9a530643c071f15e8411eadd9f0b2ee5a871d37f.pass +++ /dev/null @@ -1 +0,0 @@ -S@ng123!@# \ No newline at end of file diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 2730b991..30e4b155 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -235,7 +235,6 @@ func (p *Provider) QueryLatestHeight(ctx context.Context) (uint64, error) { return p.client.GetLatestBlockHeight(ctx) } -// todo: fill up the result func (p *Provider) QueryTransactionReceipt(ctx context.Context, txHash string) (*relayTypes.Receipt, error) { res, err := p.client.GetTransactionReceipt(ctx, txHash) if err != nil { @@ -315,7 +314,6 @@ func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockIn func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, addressPkScript []byte) ([]*multisig.Input, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*int64(p.cfg.RequestTimeout))) defer cancel() - // TODO: loop query until sastified amountRequired resp, err := GetBtcUtxo(ctx, server, p.cfg.UniSatKey, address, 0, 64) if err != nil { return nil, fmt.Errorf("failed to query bitcoin UTXOs from unisat: %v", err) @@ -353,7 +351,6 @@ func (p *Provider) GetBitcoinUTXOs(server, address string, amountRequired int64, func (p *Provider) GetRuneUTXOs(server, address, runeId string, amountRequired uint128.Uint128, addressPkScript []byte) ([]*multisig.Input, error) { ctx, cancel := context.WithTimeout(context.Background(), time.Duration(int64(time.Second)*int64(p.cfg.RequestTimeout))) defer cancel() - // TODO: loop query until sastified amountRequired resp, err := GetRuneUtxo(ctx, server, p.cfg.UniSatKey, address, runeId, 0, 64) if err != nil { return nil, fmt.Errorf("failed to query rune UTXOs from unisat: %v", err) @@ -627,7 +624,6 @@ func (p *Provider) selectUnspentUTXOs(satToSend int64, runeToSend uint128.Uint12 inputs = append(inputs, runeInputs...) } - // TODO: cover case rune UTXOs have big enough dust amount to cover inputsSatNeeded, can store rune and bitcoin in the same utxo // query bitcoin UTXOs from unisat bitcoinInputs, err := p.GetBitcoinUTXOs(p.cfg.UniSatURL, address, satToSend, addressPkScript) if err != nil { @@ -1098,7 +1094,6 @@ func (p *Provider) getHeightStream(done <-chan bool, fromHeight, toHeight uint64 func (p *Provider) fetchBlockMessages(ctx context.Context, heightInfo *HeightRange) ([]*relayTypes.BlockInfo, error) { var ( - // todo: query from provide.config multisigAddress = p.cfg.Address preFixOP = p.cfg.OpCode ) diff --git a/relayer/chains/evm/event_parse.go b/relayer/chains/evm/event_parse.go index 4ee7ee25..469b374d 100644 --- a/relayer/chains/evm/event_parse.go +++ b/relayer/chains/evm/event_parse.go @@ -13,7 +13,6 @@ func (p *Provider) getRelayMessageFromLog(log types.Log) (*providerTypes.Message return nil, fmt.Errorf("topic length mismatch") } topic := log.Topics[0] - // TODO: Bitcoin if len(topic) != 0 { transmission.CallBitcoinRelay(topic.Hex()) } diff --git a/relayer/chains/icon/client.go b/relayer/chains/icon/client.go index e289ae34..c7765bb3 100644 --- a/relayer/chains/icon/client.go +++ b/relayer/chains/icon/client.go @@ -268,8 +268,6 @@ func (c *Client) Monitor(ctx context.Context, reqUrl string, reqPtr, respPtr int c.log.Debug(fmt.Sprintf("Monitor finish %s", conn.RemoteAddr().String())) c.wsClose(conn) }() - //TODO: should remove after test - // if err = c.wsRequest(conn, interface{}("")); err != nil { if err = c.wsRequest(conn, reqPtr); err != nil { return err } diff --git a/relayer/chains/icon/keys.go b/relayer/chains/icon/keys.go index e6e92f0f..4dcc10ca 100644 --- a/relayer/chains/icon/keys.go +++ b/relayer/chains/icon/keys.go @@ -15,22 +15,19 @@ func (p *Provider) RestoreKeystore(ctx context.Context) error { if err != nil { return err } - - // TODO: Should remove comment this - // keystoreJson, err := p.kms.Decrypt(ctx, keystoreCipher) - // if err != nil { - // return err - // } + keystoreJson, err := p.kms.Decrypt(ctx, keystoreCipher) + if err != nil { + return err + } authCipher, err := os.ReadFile(path + ".pass") if err != nil { return err } - // TODO: Should remove comment this - // secret, err := p.kms.Decrypt(ctx, authCipher) - // if err != nil { - // return err - // } - wallet, err := wallet.NewFromKeyStore(keystoreCipher, authCipher) + secret, err := p.kms.Decrypt(ctx, authCipher) + if err != nil { + return err + } + wallet, err := wallet.NewFromKeyStore(keystoreJson, secret) if err != nil { return err } diff --git a/relayer/chains/icon/route.go b/relayer/chains/icon/route.go index f42d6a67..f2f5176a 100644 --- a/relayer/chains/icon/route.go +++ b/relayer/chains/icon/route.go @@ -2,8 +2,8 @@ package icon import ( "context" + "encoding/hex" "fmt" - "strings" "github.com/icon-project/centralized-relay/relayer/chains/icon/types" "github.com/icon-project/centralized-relay/relayer/events" @@ -13,22 +13,28 @@ import ( ) func (p *Provider) Route(ctx context.Context, message *providerTypes.Message, callback providerTypes.TxResponseFunc) error { - // TODO: remove this after testing - if strings.HasSuffix(message.Src, "btc") { - p.log.Info("starting to route message", zap.Any("message", message)) - iconMessage, err := p.MakeIconMessage(message) + p.log.Info("starting to route message", + zap.String("src", message.Src), + zap.String("dst", message.Dst), + zap.Any("sn", message.Sn), + zap.Any("req_id", message.ReqID), + zap.String("event_type", message.EventType), + zap.String("data", hex.EncodeToString(message.Data)), + ) - if err != nil { - return err - } - messageKey := message.MessageKey() + iconMessage, err := p.MakeIconMessage(message) + if err != nil { + return err + } + messageKey := message.MessageKey() - txhash, err := p.SendTransaction(ctx, iconMessage) - if err != nil { - return errors.Wrapf(err, "error occured while sending transaction") - } - return p.WaitForTxResult(ctx, txhash, messageKey, iconMessage.Method, callback) + txhash, err := p.SendTransaction(ctx, iconMessage) + if err != nil { + return errors.Wrapf(err, "error occured while sending transaction") } + + p.WaitForTxResult(ctx, txhash, messageKey, iconMessage.Method, callback) + return nil } @@ -126,19 +132,13 @@ func (p *Provider) SendTransaction(ctx context.Context, msg *IconMessage) ([]byt return txParam.TxHash.Value() } -// TODO: review try to remove wait for Tx from packet-transfer and only use this for client and connection creation func (p *Provider) WaitForTxResult( ctx context.Context, txHash []byte, messageKey *providerTypes.MessageKey, method string, callback providerTypes.TxResponseFunc, -) error { - if callback == nil { - // no point to wait for result if callback is nil - return nil - } - +) { txhash := types.NewHexBytes(txHash) res := &providerTypes.TxResponse{ TxHash: string(txhash), @@ -146,28 +146,25 @@ func (p *Provider) WaitForTxResult( txRes, err := p.client.WaitForResults(ctx, &types.TransactionHashParam{Hash: txhash}) if err != nil { - p.log.Error("get txn result failed", zap.String("txHash", string(txhash)), zap.String("method", method), zap.Error(err)) callback(messageKey, res, err) - return err + return } height, err := txRes.BlockHeight.Value() if err != nil { callback(messageKey, res, err) + return } - // assign tx successful height + res.Height = height if status, err := txRes.Status.Int(); status != 1 || err != nil { - err = fmt.Errorf("error: %s", err) - callback(messageKey, res, err) - p.LogFailedTx(method, txRes, err) - return err + res.Code = providerTypes.Failed + callback(messageKey, res, fmt.Errorf("transaction failed: %w", err)) + } else { + res.Code = providerTypes.Success + callback(messageKey, res, nil) } - res.Code = providerTypes.Success - callback(messageKey, res, nil) - p.LogSuccessTx(method, txRes) - return nil } func (p *Provider) LogSuccessTx(method string, result *types.TransactionResult) { diff --git a/utils/multisig/multisig_test.go b/utils/multisig/multisig_test.go index 021a4832..201cea63 100644 --- a/utils/multisig/multisig_test.go +++ b/utils/multisig/multisig_test.go @@ -18,6 +18,7 @@ const ( TX_FEE = 10000 RELAYER_MULTISIG_ADDRESS = "tb1pv5j5j0dmq2c8d0vnehrlsgrwr9g95m849dl5v0tal8chfdgzqxfskv0w8u" USER_MULTISIG_ADDRESS = "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + DUST_UTXO_AMOUNT = 547 ) func TestGenerateKeys(t *testing.T) { @@ -105,7 +106,7 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - bridgeMsg := BridgeDecodedMsg { + bridgeMsg := BridgeDecodedMsg{ &XCallMessage{ MessageType: 1, Action: "Deposit", @@ -127,10 +128,10 @@ func TestTransferBitcoinWithBridgeMessage(t *testing.T) { inputs := []*Input{ // user bitcoin UTXO to transfer and pay tx fee { - TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", - OutputIdx: 4, - OutputAmount: 1929000, - PkScript: userMultisigWallet.PKScript, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, + PkScript: userMultisigWallet.PKScript, }, } @@ -188,7 +189,7 @@ func TestTransferRuneWithBridgeMessage(t *testing.T) { userPrivKeys, userMultisigInfo := RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := BuildMultisigWallet(userMultisigInfo) - bridgeMsg := BridgeDecodedMsg { + bridgeMsg := BridgeDecodedMsg{ &XCallMessage{ Action: "Deposit", TokenAddress: "840000:3", @@ -207,17 +208,17 @@ func TestTransferRuneWithBridgeMessage(t *testing.T) { inputs := []*Input{ // userrune UTXO used to transfer { - TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", - OutputIdx: 0, - OutputAmount: DUST_UTXO_AMOUNT, - PkScript: userMultisigWallet.PKScript, + TxHash: "647a499a394bdb2a477f29b9f0515ed186e57a469a732be362a172cde4ea67a5", + OutputIdx: 0, + OutputAmount: DUST_UTXO_AMOUNT, + PkScript: userMultisigWallet.PKScript, }, // user bitcoin UTXO to pay tx fee { - TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", - OutputIdx: 4, - OutputAmount: 1929000, - PkScript: userMultisigWallet.PKScript, + TxHash: "d316231a8aa1f74472ed9cc0f1ed0e36b9b290254cf6b2c377f0d92b299868bf", + OutputIdx: 4, + OutputAmount: 1929000, + PkScript: userMultisigWallet.PKScript, }, } From afa0fd987ae4e7897a92ef5a23549b061ed87616 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Mon, 18 Nov 2024 17:12:57 +0700 Subject: [PATCH 103/113] chore: update documents and missing func in provier --- config.yaml | 49 ------------------------------ docs/bitcoin-relayer.md | 3 +- relayer/chains/bitcoin/provider.go | 12 +++++--- 3 files changed, 10 insertions(+), 54 deletions(-) delete mode 100644 config.yaml diff --git a/config.yaml b/config.yaml deleted file mode 100644 index e4432cc7..00000000 --- a/config.yaml +++ /dev/null @@ -1,49 +0,0 @@ -global: - timeout: 10s - kms-key-id: f5c550ca-a6f2-4597-895c-4846ab8e4ad2 -chains: - icon: - type: icon - value: - rpc-url: https://lisbon.net.solidwallet.io/api/v3/ - address: hx9a530643c071f15e8411eadd9f0b2ee5a871d37f - start-height: 42860355 - step-min: 1 - step-limit: 2000000000000000000 - contracts: - xcall: cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 - connection: cx577f5e756abd89cbcba38a58508b60a12754d2f5 - network-id: 2 - finality-block: 10 - nid: 0x2.icon - - bitcoin: - type: bitcoin - value: - rpc-url: stylish-white-paper.btc-testnet.quiknode.pro/f87ecf84754d9daf8cf45b0334ba3fee9b356db6/ - rpc-user: 123 - rpc-password: 123 - address: tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su - protocals: - - cx577f5e756abd89cbcba38a58508b60a12754d2f5 - # - cxf5a0b146af1572e44775a40ef06c5a39b143ed1e - unisat-url: https://open-api-testnet.unisat.io - unisat-key: 60b7bf52654454f19d8553e1b6427fb9fd2c722ea8dc6822bdf1dd7615b4b35d - # start-height: 2874137 - # start-height: 2874459 - start-height: 2901648 - network-id: 2 - op-code: 0x5e - finality-block: 10 - nid: 0x2.btc - chain-name: bitcoin - mode: master - slave-server-1: http://localhost:8081 - slave-server-2: http://localhost:8082 - port: 8082 - api-key: key - masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 - slave1PubKey: 0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052 - slave2PubKey: 021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833 - relayerPrivKey: cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy - recoveryLockTime: 1234 diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md index d43b7eb9..7970238d 100644 --- a/docs/bitcoin-relayer.md +++ b/docs/bitcoin-relayer.md @@ -30,7 +30,7 @@ bitcoin: finality-block: # Bitcoin Finality Block (10: default) nid: 0x1.btc # Bitcoin NID (0x1.btc: Bitcoin Mainnet, 0x2.btc: Bitcoin Testnet) chain-name: bitcoin # Bitcoin Chain Name - recoveryLockTime: # Recovery Lock Time (recovery lock time of the master wallet) + recoveryLockTime: # Recovery Lock Time (recovery lock time of the master wallet) start-height: # Start Height (start height) mode: master # master or slave slave-server-1: # Slave Server 1 URL (only used when mode is master) @@ -210,6 +210,7 @@ RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start - https://mempool.space/address/bc1p2sdwgq7j32j250w8h47fe9v3hyc8fl2rdftwhxp0r7ww89mcwrns5reskh ##### Deposit BTC with wrong amount, and got refund +*The refund amount does not include tx fee, if the transfer amount can not cover tx fee, the refund tx will be ignored* - Request tx: - https://mempool.space/tx/50aa0c67d8a533d3766bd2076a2bc57bb67de7d61e9f503db271e915f0f75bae diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 30e4b155..c77ff6ec 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -270,14 +270,14 @@ func (p *Provider) Config() provider.Config { return p.cfg } -func (p *Provider) Listener(ctx context.Context, lastSavedHeight uint64, blockInfoChan chan *relayTypes.BlockInfo) error { +func (p *Provider) Listener(ctx context.Context, lastProcessedTx relayTypes.LastProcessedTx, blockInfoChan chan *relayTypes.BlockInfo) error { // run http server to help btc interact each others latestHeight, err := p.QueryLatestHeight(ctx) if err != nil { p.logger.Error("failed to get latest block height", zap.Error(err)) return err } - + lastSavedHeight := lastProcessedTx.Height startHeight, err := p.getStartHeight(latestHeight, lastSavedHeight) if err != nil { p.logger.Error("failed to determine start height", zap.Error(err)) @@ -991,8 +991,8 @@ func (p *Provider) ShouldSendMessage(ctx context.Context, message *relayTypes.Me return true, nil } -func (p *Provider) GenerateMessages(ctx context.Context, messageKey *relayTypes.MessageKeyWithMessageHeight) ([]*relayTypes.Message, error) { - blocks, err := p.fetchBlockMessages(ctx, &HeightRange{messageKey.Height, messageKey.Height}) +func (p *Provider) GenerateMessages(ctx context.Context, fromHeight, toHeight uint64) ([]*relayTypes.Message, error) { + blocks, err := p.fetchBlockMessages(ctx, &HeightRange{fromHeight, toHeight}) if err != nil { return nil, err } @@ -1406,6 +1406,10 @@ func (p *Provider) GetSerialNumber() *big.Int { return p.LastSerialNumFunc() } +func (p *Provider) FetchTxMessages(ctx context.Context, txHash string) ([]*relayTypes.Message, error) { + return nil, nil +} + func (p *Config) sanitize() error { // TODO: return nil From 02d3ee16014fdcca5bf44e654a1bd81952ffca73 Mon Sep 17 00:00:00 2001 From: justinlydialabs <129317395+justinlydialabs@users.noreply.github.com> Date: Mon, 18 Nov 2024 14:55:51 -0800 Subject: [PATCH 104/113] Content fix - Justin --- docs/bitcoin-relayer.md | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md index 7970238d..2f547c30 100644 --- a/docs/bitcoin-relayer.md +++ b/docs/bitcoin-relayer.md @@ -1,17 +1,17 @@ # Bitcoin Relayer -This is a relayer for Bitcoin that allows you to send or receive BTC/Rune from your Bitcoin taproot wallet to your wallet on other chains. +This is a relayer for Bitcoin that enables you to send or receive BTC or Runes from your Bitcoin Taproot wallet to your wallet on other blockchains. ## Prerequisites -- Understand the basics of Bitcoin transactions and Multisig taproot wallets -- Understand about Bitcoin RPC and the related APIs (Unisat, Quicknode, etc.) +- Understand the basics of Bitcoin transactions and multisig Taproot wallets. +- Gain knowledge about Bitcoin RPC and related APIs, such as Unisat, Quicknode, and others. -Note: At this implementation, We use 3rd party APIs such as Quicknode to crawl the Bitcoin transactions, and Unisat to get BTC/RUNE utxos or fee rate, so we need to prepare the API keys for these services. +Note: In this implementation, we use third-party APIs, such as Quicknode, to crawl Bitcoin transactions and Unisat to retrieve BTC/RUNE UTXOs or fee rates. Therefore, it is necessary to prepare API keys for these services. ## Configuration -config.yaml is the main configuration file for the Bitcoin relayer. It includes the following sections: +config.yaml is the main configuration file for the Bitcoin relayer. It includes the following configurations: ```yaml bitcoin: @@ -50,35 +50,35 @@ The mechanism of the Bitcoin relayer is based on the master-slave architecture. ## Relayer Multisig Taproot Wallet -- Because in Bitcoin network that not support the smart contract, so the Relayer Multisig Taproot Wallet is the wallet that will receive the BTC/Rune, keep them and the logic to handle send and receive BTC/Rune will process based on this wallet +- Since the Bitcoin network does not support smart contracts, the Relayer Multisig Taproot Wallet serves as the wallet to receive BTC/Rune, securely store them, and the logic for sending and receiving BTC/Rune will be based on this wallet. -- The private key of the Relayer Multisig Taproot Wallet was generated from the `relayerPrivKey` in the config.yaml file +- The private key of the Relayer Multisig Taproot Wallet is generated from the `relayerPrivKey` in the config.yaml file -- This Wallet Address was combined from 3 different public keys: the master public key, slave1 public key and slave2 public key +- This wallet address is derived from three different public keys: the master public key, the slave1 public key, and the slave2 public key. -- To spend token from this wallet, it needs 3 signatures from the 3 public keys (the master public key and one of the slave public keys) +- To spend tokens from this wallet, it requires signatures from two out of the three public keys: the master public key and one of the slave public keys. -**_Note: The order of the public keys in the wallet address is important, it must be the same between the order when we generate the Relayer Multisig Taproot Wallet and sign the transaction_** +**_Note: The order of the public keys in the wallet address is crucial. It must remain consistent between the order used to generate the Relayer Multisig Taproot Wallet and the order used to sign the transaction_** ## Master Server -The master server will crawl Bitcoin transaction from the Bitcoin network and check if the transaction is a valid transaction with recipient is Relayer multigsig wallet address and the condition that contain value of OP_14 data is the same as the `op-code` in the config.yaml file. -The master server is the main server that handles: +The master server will crawl Bitcoin transactions from the Bitcoin network and verify if the transaction is valid. A valid transaction must have the recipient as the Relayer Multisig Wallet address and must include an OP_14 data value matching the `op-code` specified in the `config.yaml` file. +The master server is the primary server responsible for: - Requesting the slave servers to sign the transactions -- Combining the signatures from the slave servers and itself then broadcasting the transaction to the Bitcoin network +- Combining the signatures from the slave servers and its own, then broadcasting the transaction to the Bitcoin network. ## Slave Servers -It works as the same with the master server, but the slave servers will not broadcast transaction instead of they crawl transactions and cache them, and waiting for the master request to sign the transactions and send the signature back to the master server. +It functions similarly to the master server, but the slave servers do not broadcast transactions. Instead, they crawl transactions, cache them, and wait for requests from the master server to sign the transactions. Once signed, the slave servers send the signatures back to the master server. ## Data Structure -Based on the XCall message structure, The Bitcoin Relayer was designed and implemented to parse message with structure `OP_14 YOUR _PAYLOAD`. +Based on the XCall message structure, the Bitcoin Relayer is designed and implemented to parse messages with the following structure: `OP_14 YOUR _PAYLOAD`. -Because we use leverage op code to send data so the limitation is 40 bytes by Bitcoin Core's default standardness rules, so the payload `(YOUR_PAYLOAD)` will be split into multiple utxos (output) with the maximum size of 40 bytes including a dust amount (547 sats) for each part. +Since we leverage op codes to send data, the limitation is 40 bytes per transaction due to Bitcoin Core's default standardness rules. Therefore, the payload `(YOUR_PAYLOAD)` will be split into multiple UTXOs (outputs), each with a maximum size of 40 bytes, including a dust amount of 547 sats for each part. -The Bitcoin Relayer will decode the message from the Bitcoin transaction and parse the payload to `BridgeDecodedMsg` data structure. +The Bitcoin Relayer will decode the message from the Bitcoin transaction and parse the payload into the `BridgeDecodedMsg` data structure. ```golang type BridgeDecodedMsg struct { @@ -122,11 +122,11 @@ bridgeMsg := BridgeDecodedMsg{ ### Deploy the Relayer -Since the Bitcoin relayer works based on the master-slave architecture, so we should deploy seperate the master server and at least 2 slave servers, in totally there are 3 servers need to be run at the same time for ideally, or deploy these servers in the same server for testing purpose. +Since the Bitcoin Relayer operates based on a master-slave architecture, the master server and at least two slave servers should be deployed separately. Ideally, a total of three servers should run simultaneously. However, for testing purposes, these servers can be deployed on the same machine. #### Master Server Configuration -Here is some config difference between master and slave servers: +Here are some configuration differences between the master and slave servers: ```yaml # ... config above @@ -143,7 +143,7 @@ relayerPrivKey: # Relayer Private Key for master public key #### Slave Server Configuration -For slave, don't need to config `slave-server-1` and `slave-server-2` but `mode` will be `slave` +For the slave servers, there is no need to configure `slave-server-1` and `slave-server-2`. The mode parameter should be set to `slave`. ```yaml # ... config above @@ -163,10 +163,10 @@ RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start ### Implementation Details: -- Deposit BTC/Runes from BTC to Icon -- Withdraw BTC/Runes from Icon to BTC -- Rollback BTC/Runes when deposit fail -- Refund BTC if the bridge message amount does not match the output to the relayer +- Deposit BTC/Runes from Bitcoin to ICON +- Withdraw BTC/Runes from ICON to Bitcoin +- Rollback BTC/Runes in case the deposit fails +- Refund BTC if the bridge message amount does not match the output sent to the Relayer #### Testing Results: @@ -210,7 +210,7 @@ RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start - https://mempool.space/address/bc1p2sdwgq7j32j250w8h47fe9v3hyc8fl2rdftwhxp0r7ww89mcwrns5reskh ##### Deposit BTC with wrong amount, and got refund -*The refund amount does not include tx fee, if the transfer amount can not cover tx fee, the refund tx will be ignored* +*The refund amount does not include the transaction fee. If the transfer amount cannot cover the transaction fee, the refund transaction will be ignored.* - Request tx: - https://mempool.space/tx/50aa0c67d8a533d3766bd2076a2bc57bb67de7d61e9f503db271e915f0f75bae @@ -219,24 +219,24 @@ RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start ##### Withdraw BTC Successfully -- Icon tx: +- ICON tx: - https://tracker.icon.community/transaction/0x3854443002829635830e679c83d41303ace0093a78320846aa6f543835ecf751 - Bitcoin tx: - https://mempool.space/tx/cf671e0ecc434e2cb06152bae30d35114d7fef8c1c3ec7ae60aea45691edf75b ##### Withdraw RUNE Successfully -- Icon tx: +- ICON tx: - https://tracker.icon.community/transaction/0x2fbb0aca1b99692b24baae68c2b451945db9eb829f09996eac01b5799bf35fc1 - Bitcoin tx: - https://mempool.space/tx/21f8ba718ba003e38ef291c1f8a6de7706fb49b2addfbb3eadf4bf1808d83a17 ### Known Issues -- With a tx send to the relayer multisig wallet, if the BTC amount of btc does not match with the BTC amount defined in the xcall message, and the relayer will refund the amount to the sender but minus the fee. -- To stress test the system, you need to prepare a lot of BTC/RUNE utxos for the relayer multisig wallet, to make sure the system has enough utxos to process the transactions and avoid the issue of insufficient utxos. -- In case Rollback transaction, the relayer will refund the same amount of BTC/RUNE that the user sent to the relayer multisig wallet. +- If a transaction sent to the Relayer Multisig Wallet contains a BTC amount that does not match the BTC amount defined in the XCall message, the relayer will refund the amount to the sender, minus the transaction fee. +- To stress test the system, you need to prepare a large number of BTC/RUNE UTXOs for the Relayer Multisig Wallet. This ensures the system has sufficient UTXOs to process transactions and avoids issues related to insufficient UTXOs. +- In the case of a rollback transaction, the relayer will refund the exact amount of BTC/RUNE that the user sent to the Relayer Multisig Wallet. ### How to build transaction -To build transaction please check the file relayer/chains/bitcoin/provider_mainnet_test.go +To build a transaction, please refer to this file relayer/chains/bitcoin/provider_mainnet_test.go for detailed instructions and guidelines. From 02133f591503ad4616cb81d3bcbaa2068d0ca22d Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Tue, 19 Nov 2024 09:45:11 +0700 Subject: [PATCH 105/113] chore: update docs --- docs/bitcoin-relayer.md | 14 +++++++------- relayer/chains/bitcoin/provider.go | 21 +++++++++++---------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md index 2f547c30..f5341a7b 100644 --- a/docs/bitcoin-relayer.md +++ b/docs/bitcoin-relayer.md @@ -24,7 +24,7 @@ bitcoin: unisat-url: # Unisat API URL unisat-key: # Unisat API Key unisat-wallet-url: # Unisat OPEN API URL (https://wallet-api.unisat.io for mainnet, https://wallet-api-testnet.unisat.io for testnet) - request-timeout: 1000 # Request Timeout (ms) + request-timeout: 100 # Request Timeout (seconds) network-id: # Bitcoin Network ID (1: Bitcoin Mainnet, 2: Bitcoin Testnet) op-code: # Bitcoin OP Code (0x5e: default) finality-block: # Bitcoin Finality Block (10: default) @@ -52,11 +52,11 @@ The mechanism of the Bitcoin relayer is based on the master-slave architecture. - Since the Bitcoin network does not support smart contracts, the Relayer Multisig Taproot Wallet serves as the wallet to receive BTC/Rune, securely store them, and the logic for sending and receiving BTC/Rune will be based on this wallet. -- The private key of the Relayer Multisig Taproot Wallet is generated from the `relayerPrivKey` in the config.yaml file +- The private key of the Relayer Multisig Taproot Wallet is generated from the `relayerPrivKey` in all config.yaml file - This wallet address is derived from three different public keys: the master public key, the slave1 public key, and the slave2 public key. -- To spend tokens from this wallet, it requires signatures from two out of the three public keys: the master public key and one of the slave public keys. +- To spend tokens from this wallet, it requires signatures from three out of the three public keys: the master public key and two of the slave public keys. **_Note: The order of the public keys in the wallet address is crucial. It must remain consistent between the order used to generate the Relayer Multisig Taproot Wallet and the order used to sign the transaction_** @@ -104,7 +104,7 @@ type XCallMessage struct { ```golang bridgeMsg := BridgeDecodedMsg{ Message: XCallMessage{ - MessageType: 1, + MessageType: 1, //require xcall response the status of the tx in evet log, set it to 0 to ignore Action: "Deposit", TokenAddress: "0:0", To: "0x2.icon/hx452e235f9f1fd1006b1941ed1ad19ef51d1192f6", @@ -112,10 +112,10 @@ bridgeMsg := BridgeDecodedMsg{ Amount: new(big.Int).SetUint64(100000).Bytes(), Data: []byte(""), }, - ChainId: 1, - Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", + ChainId: 1, //1 is icon mainnet, 3 is icon testnet + Receiver: "cxfc86ee7687e1bf681b5548b2667844485c0e7192", //asset manager contract Connectors: []string{ - "cx577f5e756abd89cbcba38a58508b60a12754d2f5", + "cx577f5e756abd89cbcba38a58508b60a12754d2f5", //connector contract }, } ``` diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index c77ff6ec..5e10aef1 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -37,15 +37,16 @@ import ( ) var ( - BTCToken = "0:0" - MethodDeposit = "Deposit" - MethodWithdrawTo = "WithdrawTo" - MethodRefundTo = "RefundTo" - MethodRollback = "Rollback" - MasterMode = "master" - SlaveMode = "slave" - BtcDB = "btc.db" - WitnessSize = 380 + BTCToken = "0:0" + MethodDeposit = "Deposit" + MethodWithdrawTo = "WithdrawTo" + MethodRefundTo = "RefundTo" + MethodRollback = "Rollback" + MasterMode = "master" + SlaveMode = "slave" + BtcDB = "btc.db" + WitnessSize = 380 + NumberRequiredSigs = 3 ) var chainIdToName = map[uint8]string{ @@ -644,7 +645,7 @@ func (p *Provider) buildMultisigWallet() (*multisig.MultisigWallet, error) { relayersMultisigInfo := multisig.MultisigInfo{ PubKeys: [][]byte{masterPubKey, slave1PubKey, slave2PubKey}, EcPubKeys: nil, - NumberRequiredSigs: 3, + NumberRequiredSigs: NumberRequiredSigs, RecoveryPubKey: masterPubKey, RecoveryLockTime: uint64(p.cfg.RecoveryLockTime), } From 74ded8451362ed13abefce6de44c53a4f3e515d9 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Fri, 22 Nov 2024 10:35:07 +0700 Subject: [PATCH 106/113] fix: remove unused code --- relayer/chains/evm/event_parse.go | 5 +--- relayer/transmission/transmission.go | 38 ---------------------------- 2 files changed, 1 insertion(+), 42 deletions(-) delete mode 100644 relayer/transmission/transmission.go diff --git a/relayer/chains/evm/event_parse.go b/relayer/chains/evm/event_parse.go index 469b374d..538ae86c 100644 --- a/relayer/chains/evm/event_parse.go +++ b/relayer/chains/evm/event_parse.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/ethereum/go-ethereum/core/types" - "github.com/icon-project/centralized-relay/relayer/transmission" providerTypes "github.com/icon-project/centralized-relay/relayer/types" ) @@ -13,9 +12,7 @@ func (p *Provider) getRelayMessageFromLog(log types.Log) (*providerTypes.Message return nil, fmt.Errorf("topic length mismatch") } topic := log.Topics[0] - if len(topic) != 0 { - transmission.CallBitcoinRelay(topic.Hex()) - } + switch topic { case EmitMessageHash: msg, err := p.client.ParseConnectionMessage(log) diff --git a/relayer/transmission/transmission.go b/relayer/transmission/transmission.go deleted file mode 100644 index 80ddea00..00000000 --- a/relayer/transmission/transmission.go +++ /dev/null @@ -1,38 +0,0 @@ -package transmission - -import ( - "bytes" - "fmt" - "io" - "log" - "net/http" - "os" -) - -func CallBitcoinRelay(message string) []byte { - fmt.Printf("Call Bitcoin Relayer") - masterServer := os.Getenv("MASTER_SERVER") - - client := &http.Client{} - apiKeyHeader := os.Getenv("API_KEY") - - req, err := http.NewRequest("POST", masterServer+"/execute", bytes.NewBuffer([]byte(message))) - if err != nil { - log.Fatalf("Failed to create request: %v", err) - } - - req.Header.Add("x-api-key", apiKeyHeader) - req.Header.Set("Content-Type", "application/json") - - resp, err := client.Do(req) - if err != nil { - log.Fatalf("Failed to send request: %v", err) - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - log.Fatalf("Error reading response: %v", err) - } - return body -} From a2873f02520de38d06dc64752cfd824b29f2431e Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Mon, 25 Nov 2024 14:11:09 +0700 Subject: [PATCH 107/113] chore: remove unnecessary --- .gitignore | 2 -- .vscode/launch.json | 18 ------------------ 2 files changed, 20 deletions(-) delete mode 100644 .vscode/launch.json diff --git a/.gitignore b/.gitignore index f3a42f16..9c8deea4 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,5 @@ vendor .*env dist -/go.work -/go.work.sum keystore data diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 33b4dca6..00000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Launch App", - "type": "go", - "request": "launch", - "mode": "auto", - "program": "${workspaceFolder}", - "args": [ - "start", - ], - "env": { - "RELAY_HOME": "/Users/Corgi/Corgi/workspace/lydia/centralized-relay" - } - } - ] -} \ No newline at end of file From 794455fb90f884dd2e67d77b32da16f48468624b Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Tue, 26 Nov 2024 15:21:00 +0700 Subject: [PATCH 108/113] fix: handle error without fatalf log --- relayer/chains/bitcoin/provider.go | 25 +++++++++++++++++-------- utils/multisig/tx.go | 2 -- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 5e10aef1..f235f975 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -91,6 +91,12 @@ type slaveRequestUpdateRelayMessageStatus struct { TxHash string `json:"txHash"` } +type slaveResponse struct { + order int + sigs [][]byte + err error +} + type StoredMessageData struct { OriginalMessage *relayTypes.Message TxHash string @@ -207,10 +213,7 @@ func (c *Config) NewProvider(ctx context.Context, log *zap.Logger, homepath stri func (p *Provider) CallSlaves(slaveRequestData []byte, path string) [][][]byte { resultChan := make(chan [][][]byte) go func() { - responses := make(chan struct { - order int - sigs [][]byte - }, 2) + responses := make(chan slaveResponse, 2) var wg sync.WaitGroup wg.Add(2) @@ -224,6 +227,10 @@ func (p *Provider) CallSlaves(slaveRequestData []byte, path string) [][][]byte { results := make([][][]byte, 2) for res := range responses { + if res.err != nil { + p.logger.Error("failed to call slaves", zap.Error(res.err)) + continue + } results[res.order-1] = res.sigs } resultChan <- results @@ -930,13 +937,15 @@ func (p *Provider) sendTransaction(ctx context.Context, message *relayTypes.Mess if err != nil { p.logger.Error("err combine tx: ", zap.Error(err)) + return "", err } p.logger.Info("signedMsgTx", zap.Any("transaction", signedMsgTx)) var buf bytes.Buffer err = signedMsgTx.Serialize(&buf) if err != nil { - log.Fatal(err) + p.logger.Error("err serialize tx: ", zap.Error(err)) + return "", err } txSize := len(buf.Bytes()) @@ -1371,11 +1380,11 @@ func (p *Provider) getAddressesFromTx(txOut *wire.TxOut, chainParams *chaincfg.P scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(txOut.PkScript, chainParams) if err != nil { - fmt.Printf(" Script: Unable to parse (possibly OP_RETURN)\n") + p.logger.Error("Script: Unable to parse (possibly OP_RETURN)", zap.Error(err)) } else { - fmt.Printf(" Script Class: %s\n", scriptClass) + p.logger.Info("Script Class", zap.String("scriptClass", scriptClass.String())) if len(addresses) > 0 { - fmt.Printf(" Receiver Address: %s\n", addresses[0].String()) + p.logger.Info("Receiver Address", zap.String("address", addresses[0].String())) receiverAddresses = append(receiverAddresses, addresses[0].String()) } } diff --git a/utils/multisig/tx.go b/utils/multisig/tx.go index f1ec2470..acfa1df5 100644 --- a/utils/multisig/tx.go +++ b/utils/multisig/tx.go @@ -32,12 +32,10 @@ func TransposeSigs(sigs [][][]byte) [][][]byte { } func ParseTx(data string) (*wire.MsgTx, error) { - fmt.Printf("ParseTx data: %v\n", string(data)) dataBytes, err := hex.DecodeString(data) if err != nil { return nil, err } - fmt.Printf("ParseTx dataBytes: %v\n", string(dataBytes)) tx := &wire.MsgTx{} err = tx.Deserialize(strings.NewReader(string(dataBytes))) if err != nil { From 877c3cb22b1a27e045d387b9f5418631f00c2f71 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Tue, 26 Nov 2024 15:31:14 +0700 Subject: [PATCH 109/113] fix: validate slave signs before sign transaction --- relayer/chains/bitcoin/master.go | 34 ++++++++++++++++-------------- relayer/chains/bitcoin/provider.go | 5 +++++ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/relayer/chains/bitcoin/master.go b/relayer/chains/bitcoin/master.go index b40456e6..6257a5ea 100644 --- a/relayer/chains/bitcoin/master.go +++ b/relayer/chains/bitcoin/master.go @@ -55,28 +55,24 @@ func handleExecute(w http.ResponseWriter, r *http.Request) { return } - fmt.Println("Received message: ", msg) - // Send a response w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") response := map[string]string{"status": "success", "msg": msg} - fmt.Println(response) json.NewEncoder(w).Encode(response) } -func requestPartialSign(apiKey string, url string, slaveRequestData []byte, responses chan<- struct { - order int - sigs [][]byte -}, order int, wg *sync.WaitGroup) { +func requestPartialSign(apiKey string, url string, slaveRequestData []byte, responses chan<- slaveResponse, order int, wg *sync.WaitGroup) { defer wg.Done() - + response := slaveResponse{} client := &http.Client{} payload := bytes.NewBuffer(slaveRequestData) req, err := http.NewRequest("POST", url, payload) if err != nil { - log.Fatalf("Failed to create request: %v", err) + response.err = fmt.Errorf("failed to create request: %v", err) + responses <- response + return } req.Header.Add("x-api-key", apiKey) @@ -84,22 +80,28 @@ func requestPartialSign(apiKey string, url string, slaveRequestData []byte, resp resp, err := client.Do(req) if err != nil { - log.Fatalf("Failed to send request: %v", err) + response.err = fmt.Errorf("failed to send request: %v", err) + responses <- response + return } defer resp.Body.Close() body, err := io.ReadAll(resp.Body) if err != nil { - log.Fatalf("Error reading response: %v", err) + response.err = fmt.Errorf("error reading response: %v", err) + responses <- response + return } sigs := [][]byte{} err = json.Unmarshal(body, &sigs) if err != nil { - fmt.Println("err Unmarshal: ", err) + response.err = fmt.Errorf("err Unmarshal: %v", err) + responses <- response + return } - responses <- struct { - order int - sigs [][]byte - }{order: order, sigs: sigs} + response.order = order + response.sigs = sigs + response.err = nil + responses <- response } diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index f235f975..9a295ca2 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -929,7 +929,12 @@ func (p *Provider) sendTransaction(ctx context.Context, message *relayTypes.Mess slaveRequestData, _ := json.Marshal(rsi) slaveSigs := p.CallSlaves(slaveRequestData, "") + p.logger.Info("Slave signatures", zap.Any("slave sigs", slaveSigs)) + if len(slaveSigs) < 2 || len(slaveSigs[0]) == 0 || len(slaveSigs[1]) == 0 { + return "", fmt.Errorf("slave sigs is empty") + } + totalSigs = append(totalSigs, slaveSigs...) // combine sigs From 1db133de5250e91f081406e9514f16ff624d3eab Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Tue, 26 Nov 2024 15:34:18 +0700 Subject: [PATCH 110/113] fix: remove fatal log --- relayer/chains/bitcoin/provider.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 9a295ca2..45b70dc2 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "encoding/json" "fmt" - "log" "math/big" "runtime" "slices" @@ -799,20 +798,20 @@ func (p *Provider) decodeWithdrawToMessage(input []byte) (*MessageDecoded, []byt withdrawInfoWrapper := CSMessage{} _, err := codec.RLP.UnmarshalFromBytes(input, &withdrawInfoWrapper) if err != nil { - log.Fatal(err.Error()) + return nil, nil, fmt.Errorf("failed to unmarshal withdraw info wrapper: %v", err) } // withdraw info data withdrawInfoWrapperV2 := CSMessageRequestV2{} _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapper.Payload, &withdrawInfoWrapperV2) if err != nil { - log.Fatal(err.Error()) + return nil, nil, fmt.Errorf("failed to unmarshal withdraw info wrapper: %v", err) } // withdraw info withdrawInfo := &MessageDecoded{} _, err = codec.RLP.UnmarshalFromBytes(withdrawInfoWrapperV2.Data, &withdrawInfo) if err != nil { - log.Fatal(err.Error()) + return nil, nil, fmt.Errorf("failed to unmarshal withdraw info: %v", err) } return withdrawInfo, withdrawInfoWrapperV2.Data, nil From 7c41ba0113eb7a218164cb150daff86835cf4378 Mon Sep 17 00:00:00 2001 From: Shall Date: Fri, 29 Nov 2024 16:23:52 +0700 Subject: [PATCH 111/113] chore: update doc --- docs/bitcoin-relayer.md | 219 +++++++++++++++++- relayer/chains/bitcoin/provider.go | 10 +- .../chains/bitcoin/provider_mainnet_test.go | 2 +- relayer/chains/bitcoin/provider_test.go | 53 +++-- 4 files changed, 252 insertions(+), 32 deletions(-) diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md index f5341a7b..38518aca 100644 --- a/docs/bitcoin-relayer.md +++ b/docs/bitcoin-relayer.md @@ -41,7 +41,6 @@ bitcoin: slave1PubKey: # Slave 1 Public Key (public key of the slave wallet 1) slave2PubKey: # Slave 2 Public Key (public key of the slave wallet 2) relayerPrivKey: # Relayer Private Key (private key of the relayer it depends the deployed server that which start for master/slave1/slave2 server) - ``` # How it works @@ -210,7 +209,8 @@ RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start - https://mempool.space/address/bc1p2sdwgq7j32j250w8h47fe9v3hyc8fl2rdftwhxp0r7ww89mcwrns5reskh ##### Deposit BTC with wrong amount, and got refund -*The refund amount does not include the transaction fee. If the transfer amount cannot cover the transaction fee, the refund transaction will be ignored.* + +_The refund amount does not include the transaction fee. If the transfer amount cannot cover the transaction fee, the refund transaction will be ignored._ - Request tx: - https://mempool.space/tx/50aa0c67d8a533d3766bd2076a2bc57bb67de7d61e9f503db271e915f0f75bae @@ -240,3 +240,218 @@ RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start ### How to build transaction To build a transaction, please refer to this file relayer/chains/bitcoin/provider_mainnet_test.go for detailed instructions and guidelines. + +### Config to run the relayers on testnet and build Bitcoin transactions + +#### Start command: + +```bash +RELAY_HOME="YOUR_SOURCE_CODE_PATH" go run main.go start +``` + +**_Note: Run Slave Relayers before Master Relayer_** + +#### Slave 1 Relayer + +```yaml +global: + timeout: 10s + kms-key-id: YOUR_KMS_KEY_ID +chains: + icon: + type: icon + value: + rpc-url: https://lisbon.net.solidwallet.io/api/v3/ + address: hx620fb6cf1b6ad1988ee246a636e61b54a7c139d8 + start-height: 44139420 # should set to the latest height of the icon lisbon testnet + step-min: 1 + step-limit: 2000000000000000000 + contracts: + xcall: cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 + connection: cxc7a77b874eddfe3fb5434effaf35375b697496ca + network-id: 2 + finality-block: 10 + nid: 0x2.icon + + bitcoin: + type: bitcoin + value: + rpc-url: Your_Bitcoin_Testnet_RPC_URL # we use Quicknode for testnet + rpc-user: Your_Bitcoin_Testnet_RPC_User # if you use Quicknode set it to any value + rpc-password: Your_Bitcoin_Testnet_RPC_Password # if you use Quicknode set it to any value + address: tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk + connections: + - cxc7a77b874eddfe3fb5434effaf35375b697496ca + unisat-url: https://open-api-testnet.unisat.io + unisat-key: Your_Unisat_Testnet_API_Key # Your Unisat Testnet API Key + unisat-wallet-url: https://wallet-api-testnet.unisat.io + request-timeout: 1000 + mempool-url: https://mempool.space/testnet/api/tx + start-height: 3004578 # should set to the latest height of the bitcoin testnet + network-id: 2 + op-code: 0x5e + finality-block: 10 + nid: 0x2.btc + chain-name: bitcoin + mode: slave + slave-server-1: Your_Slave_Server_1_URL + slave-server-2: Your_Slave_Server_2_URL + port: 8081 # Slave 1 Port + api-key: YOUR_API_KEY + masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 + slave1PubKey: 0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052 + slave2PubKey: 021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833 + relayerPrivKey: cRfK7N7cPZ1BZi6MpsNBuz7k3LiMMA7jreHMx3KUBjRV4KAQT9ou # private key of the slave1 wallet + recoveryLockTime: 1234 + btc-token: 0:1 +``` + +#### Slave 2 Relayer + +```yaml +global: + timeout: 10s + kms-key-id: YOUR_KMS_KEY_ID +chains: + icon: + type: icon + value: + rpc-url: https://lisbon.net.solidwallet.io/api/v3/ + address: hx620fb6cf1b6ad1988ee246a636e61b54a7c139d8 + start-height: 44139420 # should set to the latest height of the icon lisbon testnet + step-min: 1 + step-limit: 2000000000000000000 + contracts: + xcall: cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 + connection: cxc7a77b874eddfe3fb5434effaf35375b697496ca + network-id: 2 + finality-block: 10 + nid: 0x2.icon + + bitcoin: + type: bitcoin + value: + rpc-url: Your_Bitcoin_Testnet_RPC_URL # we use Quicknode for testnet + rpc-user: Your_Bitcoin_Testnet_RPC_User # if you use Quicknode set it to any value + rpc-password: Your_Bitcoin_Testnet_RPC_Password # if you use Quicknode set it to any value + address: tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk + connections: + - cxc7a77b874eddfe3fb5434effaf35375b697496ca + unisat-url: https://open-api-testnet.unisat.io + unisat-key: Your_Unisat_Testnet_API_Key + unisat-wallet-url: https://wallet-api-testnet.unisat.io + request-timeout: 1000 + mempool-url: https://mempool.space/testnet/api/tx + start-height: 3004578 + network-id: 2 + op-code: 0x5e + finality-block: 10 + nid: 0x2.btc + chain-name: bitcoin + mode: slave + slave-server-1: Your_Slave_Server_1_URL + slave-server-2: Your_Slave_Server_2_URL + port: 8082 # Slave 2 Port + api-key: YOUR_API_KEY + masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 + slave1PubKey: 0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052 + slave2PubKey: 021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833 + relayerPrivKey: cU8TYnj3fp9t6hVcAz1rNm2GNLoLL2PFHpiCbkXmBCN6F1GZccxf # private key of the slave2 wallet + recoveryLockTime: 1234 + btc-token: 0:1 +``` + +#### Master Relayer + +```yaml +global: + timeout: 10s + kms-key-id: YOUR_KMS_KEY_ID +chains: + icon: + type: icon + value: + rpc-url: https://lisbon.net.solidwallet.io/api/v3/ + address: hx620fb6cf1b6ad1988ee246a636e61b54a7c139d8 + start-height: 44139420 # should set to the latest height of the icon lisbon testnet + step-min: 1 + step-limit: 2000000000000000000 + contracts: + xcall: cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 + connection: cxc7a77b874eddfe3fb5434effaf35375b697496ca + network-id: 2 + finality-block: 10 + nid: 0x2.icon + + bitcoin: + type: bitcoin + value: + rpc-url: Your_Bitcoin_Testnet_RPC_URL # we use Quicknode for testnet + rpc-user: Your_Bitcoin_Testnet_RPC_User # if you use Quicknode set it to any value + rpc-password: Your_Bitcoin_Testnet_RPC_Password # if you use Quicknode set it to any value + address: tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk + connections: + - cxc7a77b874eddfe3fb5434effaf35375b697496ca + unisat-url: https://open-api-testnet.unisat.io + unisat-key: Your_Unisat_Testnet_API_Key + unisat-wallet-url: https://wallet-api-testnet.unisat.io + request-timeout: 1000 + mempool-url: https://mempool.space/testnet/api/tx + start-height: 3004578 # should set to the latest height of the bitcoin testnet + network-id: 2 + op-code: 0x5e + finality-block: 10 + nid: 0x2.btc + chain-name: bitcoin + mode: master + slave-server-1: Your_Slave_Server_1_URL + slave-server-2: Your_Slave_Server_2_URL + port: 8080 + api-key: YOUR_API_KEY + masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 + slave1PubKey: 0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052 + slave2PubKey: 021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833 + relayerPrivKey: cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy # private key of the master wallet + recoveryLockTime: 1234 + btc-token: 0:1 +``` + +### Contract Addresseses + +| Contract Name | Address | TokenId | +| ----------------------- | ------------------------------------------ | -------------------- | +| XCall | cx15a339fa60bd86225050b22ea8cd4a9d7cd8bb83 | | +| Access Manager | cx8c9a213cd5dcebfb539c30e1af6d77990b200ca4 | | +| Bitcoin address (dec 8) | cx76c9b35b11bb85990ea2557fc7e0bde74a370f1d | 0x2.btc/0:1 | +| LYDIALABS TOKEN( dec 0) | cx925ad1194a69b7fd8733196e93c15542884b9600 | 0x2.btc/2904354:3119 | +| Access Manager | cx8c9a213cd5dcebfb539c30e1af6d77990b200ca4 | | + +- Connection Contract: `cxc7a77b874eddfe3fb5434effaf35375b697496ca` +- Admin Wallet's Connection Contract: `hx620fb6cf1b6ad1988ee246a636e61b54a7c139d8` +- Admin Wallet's Private Key: `3dd1c874c61a2308374cfa91601edd2d44977b7fbb5765496166164c8daadab3` +- Multisig Relayer Bitcoin Address: `tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk` + +#### After the relayer is started you can try to build a transaction by yourself please follow the testcase in the file below: + +- [Build Bitcoin transactions](https://github.com/lydialabs/centralized-relay/blob/feat/bitcoin-relayer/relayer/chains/bitcoin/provider_test.go) + +#### Check available UTXOs + +- [BITCOIN UTXO](https://docs.unisat.io/dev/unisat-developer-center/bitcoin/general/addresses/get-btc-utxo) +- [RUNE UTXO](https://docs.unisat.io/dev/unisat-developer-center/bitcoin/runes/get-address-runes-utxo) + +#### Testcases + +**_Note: please change the input transaction before you run the testcases, the data you can get from unisat API_** + +```go +inputs := []*multisig.Input{} +``` + +- Testcase 1: [Deposit BTC Successfully](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L297) +- Testcase 2: [Deposit RUNE Successfully](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L427) +- Testcase 3: [Deposit BTC Failed](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L363) +- Testcase 4: [Deposit RUNE Failed](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L500C6-L500C38) +- Testcase 5: [Deposit BTC with wrong amount, and got refund](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L224) +- Testcase 6: Withdraw BTC Successfully => Should be called on ICON chain by your wallet that received token by deposit testcase above +- Testcase 7: Withdraw RUNE Successfully => Should be called on ICON chain by your wallet that received token by deposit testcase above diff --git a/relayer/chains/bitcoin/provider.go b/relayer/chains/bitcoin/provider.go index 45b70dc2..577fd79f 100644 --- a/relayer/chains/bitcoin/provider.go +++ b/relayer/chains/bitcoin/provider.go @@ -36,7 +36,6 @@ import ( ) var ( - BTCToken = "0:0" MethodDeposit = "Deposit" MethodWithdrawTo = "WithdrawTo" MethodRefundTo = "RefundTo" @@ -149,6 +148,7 @@ type Config struct { RelayerPrivKey string `json:"relayerPrivKey" yaml:"relayerPrivKey"` RecoveryLockTime int `json:"recoveryLockTime" yaml:"recoveryLockTime"` Connections []string `json:"connections" yaml:"connections"` + BTCToken string `json:"btc-token" yaml:"btc-token"` } // NewProvider returns new Icon provider @@ -445,7 +445,7 @@ func (p *Provider) CreateBitcoinMultisigTx( // add withdraw output amount := new(big.Int).SetBytes(decodedData.Amount) if decodedData.Action == MethodWithdrawTo || decodedData.Action == MethodDeposit || decodedData.Action == MethodRollback { - if decodedData.TokenAddress == BTCToken { + if decodedData.TokenAddress == p.cfg.BTCToken { // transfer btc bitcoinAmountRequired = amount.Int64() outputs = []*wire.TxOut{ @@ -499,7 +499,7 @@ func (p *Provider) CreateBitcoinMultisigTx( bitcoinAmountRequired = multisig.RUNE_DUST_UTXO_AMOUNT * 2 } } else if decodedData.Action == MethodRefundTo { - if decodedData.TokenAddress != BTCToken { + if decodedData.TokenAddress != p.cfg.BTCToken { return nil, nil, fmt.Errorf("refund is only supported for btc token, current token: %s", decodedData.TokenAddress) } uintAmount := amount.Uint64() @@ -884,7 +884,7 @@ func (p *Provider) buildTxMessage(message *relayTypes.Message, feeRate int64, ms p.logger.Error("failed to get decode data: %v", zap.Error(err)) return nil, nil, err } - if messageDecoded.TokenAddress != BTCToken { + if messageDecoded.TokenAddress != p.cfg.BTCToken { return nil, nil, fmt.Errorf("only support refund for BTC") } decodedData = messageDecoded @@ -1264,7 +1264,7 @@ func (p *Provider) verifyBridgeTx(tx *TxSearchRes, messageInfo *multisig.XCallMe continue } - if messageInfo.TokenAddress == BTCToken { + if messageInfo.TokenAddress == p.cfg.BTCToken { verified = true btcAmount := big.NewInt(out.Value) if amount.Cmp(btcAmount) == 0 { diff --git a/relayer/chains/bitcoin/provider_mainnet_test.go b/relayer/chains/bitcoin/provider_mainnet_test.go index f3806da2..4ca9463c 100644 --- a/relayer/chains/bitcoin/provider_mainnet_test.go +++ b/relayer/chains/bitcoin/provider_mainnet_test.go @@ -221,7 +221,7 @@ func TestBuildWithdrawRunesTxMessageMainnet(t *testing.T) { btcProvider.logger.Info("txHash", zap.String("transaction_hash", txHash)) } -func TestBuildRollbackBtcTxMessageMainnet(t *testing.T) { +func TestBuildRefundBtcTxMessageMainnet(t *testing.T) { // Create a mock Provider btcProvider, termpDir := initBtcProviderMainnet() defer os.Remove(termpDir) diff --git a/relayer/chains/bitcoin/provider_test.go b/relayer/chains/bitcoin/provider_test.go index aeb37eff..0cba96b1 100644 --- a/relayer/chains/bitcoin/provider_test.go +++ b/relayer/chains/bitcoin/provider_test.go @@ -24,12 +24,15 @@ import ( const ( // TESTNET - TESTNET_USER_WALLET_ADDRESS = "" - TESTNET_RELAYER_ADDRESS = "" - TESTNET_ASSET_MANAGER_ADDRESS = "" - TESTNET_ASSET_MANAGER_ADDRESS_WRONG = "" - TESTNET_CONNECTION_ADDRESS = "" + TESTNET_USER_WALLET_ADDRESS = "tb1pgzx880yfr7q8dgz8dqhw50sncu4f4hmw5cn3800354tuzcy9jx5shvv7su" + TESTNET_RELAYER_ADDRESS = "tb1pf0atpt2d3zel6udws38pkrh2e49vqd3c5jcud3a82srphnmpe55q0ecrzk" + TESTNET_ASSET_MANAGER_ADDRESS = "cx8c9a213cd5dcebfb539c30e1af6d77990b200ca4" + TESTNET_ASSET_MANAGER_ADDRESS_WRONG = "cx8c9a213cd5dcebfb539c30e1af6d77990b200ca5" + TESTNET_CONNECTION_ADDRESS = "cxc7a77b874eddfe3fb5434effaf35375b697496ca" TESTNET_TX_FEE = 20000 + TESTNET_BTCTOKEN = "0:1" + TESTNET_RUNETOKEN = "2904354:3119" + TESTNET_ICON_RECEIVER_ADDRESS = "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800" ) func initBtcProviderTestnet() (*Provider, string) { @@ -43,13 +46,13 @@ func initBtcProviderTestnet() (*Provider, string) { config := &Config{} config = &Config{ UniSatURL: "https://open-api.unisat.io", - UniSatKey: "", + UniSatKey: "YOUR_UNISAT_API_KEY", - MasterPubKey: "", - Slave1PubKey: "", - Slave2PubKey: "", - RelayerPrivKey: "", - RecoveryLockTime: 0, + MasterPubKey: "02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2", + Slave1PubKey: "0230edd881db1bc32b94f83ea5799c2e959854e0f99427d07c211206abd876d052", + Slave2PubKey: "021e83d56728fde393b41b74f2b859381661025f2ecec567cf392da7372de47833", + RelayerPrivKey: "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy", + RecoveryLockTime: 1234, OpCode: 0x5e, MempoolURL: "https://mempool.space/api/v1", SlaveServer1: "http://localhost:8081", @@ -93,7 +96,7 @@ func initBtcProviderTestnet() (*Provider, string) { } func buildUserMultisigWalletTestnet(chainParam *chaincfg.Params) ([]string, *multisig.MultisigWallet, error) { - userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 1}, 1, 1) + userPrivKeys, userMultisigInfo := multisig.RandomMultisigInfo(2, 2, chainParam, []int{0, 3}, 1, 1) userMultisigWallet, _ := multisig.BuildMultisigWallet(userMultisigInfo) return userPrivKeys, userMultisigWallet, nil } @@ -221,7 +224,7 @@ func TestBuildWithdrawRunesTxMessageTestnet(t *testing.T) { btcProvider.logger.Info("txHash", zap.String("transaction_hash", txHash)) } -func TestBuildRollbackBtcTxMessageTestnet(t *testing.T) { +func TestBuildRefundBtcTxMessageTestnet(t *testing.T) { // Create a mock Provider btcProvider, termpDir := initBtcProviderTestnet() defer os.Remove(termpDir) @@ -235,9 +238,9 @@ func TestBuildRollbackBtcTxMessageTestnet(t *testing.T) { Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "0:0", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", // user icon address - From: TESTNET_USER_WALLET_ADDRESS, // user bitcoin address + TokenAddress: TESTNET_BTCTOKEN, + To: TESTNET_ICON_RECEIVER_ADDRESS, // user icon address + From: TESTNET_USER_WALLET_ADDRESS, // user bitcoin address Amount: new(big.Int).SetUint64(5000).Bytes(), Data: []byte(""), }, @@ -307,8 +310,8 @@ func TestDepositBitcoinToIconTestnet(t *testing.T) { Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "0:0", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + TokenAddress: TESTNET_BTCTOKEN, + To: TESTNET_ICON_RECEIVER_ADDRESS, From: TESTNET_USER_WALLET_ADDRESS, Amount: new(big.Int).SetUint64(1000).Bytes(), Data: []byte(""), @@ -373,8 +376,8 @@ func TestDepositBitcoinToIconFailTestnet(t *testing.T) { Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "0:0", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + TokenAddress: TESTNET_BTCTOKEN, + To: TESTNET_ICON_RECEIVER_ADDRESS, From: TESTNET_USER_WALLET_ADDRESS, Amount: new(big.Int).SetUint64(3000).Bytes(), Data: []byte(""), @@ -437,8 +440,8 @@ func TestDepositRuneToIconTestnet(t *testing.T) { Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "1:0", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + TokenAddress: TESTNET_RUNETOKEN, + To: TESTNET_ICON_RECEIVER_ADDRESS, From: TESTNET_USER_WALLET_ADDRESS, Amount: new(big.Int).SetUint64(1).Bytes(), Data: []byte(""), @@ -510,8 +513,8 @@ func TestDepositRuneToIconFailTestnet(t *testing.T) { Message: &multisig.XCallMessage{ MessageType: 1, Action: "Deposit", - TokenAddress: "1:0", - To: "0x2.icon/hx1493794ba31fa3372bf7903f04030497e7d14800", + TokenAddress: TESTNET_RUNETOKEN, + To: TESTNET_ICON_RECEIVER_ADDRESS, From: TESTNET_USER_WALLET_ADDRESS, Amount: new(big.Int).SetUint64(1).Bytes(), Data: []byte(""), @@ -569,6 +572,7 @@ func TestDepositRuneToIconFailTestnet(t *testing.T) { fmt.Println("err: ", err) } +// Run to build Relayer Multisig Wallet func TestBuildRelayerMultisigWalletTestnet(t *testing.T) { btcProvider, termpDir := initBtcProviderTestnet() defer os.Remove(termpDir) @@ -584,6 +588,7 @@ func TestBuildRelayerMultisigWalletTestnet(t *testing.T) { fmt.Println("err: ", err) } +// Run to build User Multisig Wallet func TestBuildUserMultisigWalletTestnet(t *testing.T) { btcProvider, termpDir := initBtcProviderTestnet() defer os.Remove(termpDir) From 2c6eeb1538b96b28169fa1c887d95cf62f14f9f9 Mon Sep 17 00:00:00 2001 From: Shall Date: Fri, 29 Nov 2024 16:30:34 +0700 Subject: [PATCH 112/113] chore: update doc for more details --- docs/bitcoin-relayer.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/bitcoin-relayer.md b/docs/bitcoin-relayer.md index 38518aca..28bb67e0 100644 --- a/docs/bitcoin-relayer.md +++ b/docs/bitcoin-relayer.md @@ -294,8 +294,8 @@ chains: nid: 0x2.btc chain-name: bitcoin mode: slave - slave-server-1: Your_Slave_Server_1_URL - slave-server-2: Your_Slave_Server_2_URL + slave-server-1: Your_Slave_Server_1_URL # http://localhost:8081 + slave-server-2: Your_Slave_Server_2_URL # http://localhost:8082 port: 8081 # Slave 1 Port api-key: YOUR_API_KEY masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 @@ -349,8 +349,8 @@ chains: nid: 0x2.btc chain-name: bitcoin mode: slave - slave-server-1: Your_Slave_Server_1_URL - slave-server-2: Your_Slave_Server_2_URL + slave-server-1: Your_Slave_Server_1_URL # http://localhost:8081 + slave-server-2: Your_Slave_Server_2_URL # http://localhost:8082 port: 8082 # Slave 2 Port api-key: YOUR_API_KEY masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 @@ -404,8 +404,8 @@ chains: nid: 0x2.btc chain-name: bitcoin mode: master - slave-server-1: Your_Slave_Server_1_URL - slave-server-2: Your_Slave_Server_2_URL + slave-server-1: Your_Slave_Server_1_URL # http://localhost:8081 + slave-server-2: Your_Slave_Server_2_URL # http://localhost:8082 port: 8080 api-key: YOUR_API_KEY masterPubKey: 02fe44ec9f26b97ed30bd33898cf22de726e05389bde632d3aa6ad6746e15221d2 @@ -442,16 +442,17 @@ chains: #### Testcases -**_Note: please change the input transaction before you run the testcases, the data you can get from unisat API_** +**_Note: please change the input transaction and UniSatKey before you run the testcases, the input transaction you can get from unisat API_** ```go +UniSatKey: "YOUR_UNISAT_API_KEY", inputs := []*multisig.Input{} ``` -- Testcase 1: [Deposit BTC Successfully](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L297) -- Testcase 2: [Deposit RUNE Successfully](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L427) -- Testcase 3: [Deposit BTC Failed](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L363) -- Testcase 4: [Deposit RUNE Failed](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L500C6-L500C38) -- Testcase 5: [Deposit BTC with wrong amount, and got refund](https://github.com/lydialabs/centralized-relay/blob/1db133de5250e91f081406e9514f16ff624d3eab/relayer/chains/bitcoin/provider_test.go#L224) +- Testcase 1: [Deposit BTC Successfully](https://github.com/lydialabs/centralized-relay/blob/7c41ba0113eb7a218164cb150daff86835cf4378/relayer/chains/bitcoin/provider_test.go#L300) +- Testcase 2: [Deposit RUNE Successfully](https://github.com/lydialabs/centralized-relay/blob/7c41ba0113eb7a218164cb150daff86835cf4378/relayer/chains/bitcoin/provider_test.go#L430) +- Testcase 3: [Deposit BTC Failed](https://github.com/lydialabs/centralized-relay/blob/7c41ba0113eb7a218164cb150daff86835cf4378/relayer/chains/bitcoin/provider_test.go#L366) +- Testcase 4: [Deposit RUNE Failed](https://github.com/lydialabs/centralized-relay/blob/7c41ba0113eb7a218164cb150daff86835cf4378/relayer/chains/bitcoin/provider_test.go#L503) +- Testcase 5: [Deposit BTC with wrong amount, and got refund](https://github.com/lydialabs/centralized-relay/blob/7c41ba0113eb7a218164cb150daff86835cf4378/relayer/chains/bitcoin/provider_test.go#L227) - Testcase 6: Withdraw BTC Successfully => Should be called on ICON chain by your wallet that received token by deposit testcase above - Testcase 7: Withdraw RUNE Successfully => Should be called on ICON chain by your wallet that received token by deposit testcase above From 9d71ae7e80a7b338fad4d39d08622546222a6366 Mon Sep 17 00:00:00 2001 From: spiderlipovitan Date: Sat, 30 Nov 2024 11:23:29 +0700 Subject: [PATCH 113/113] fix: update mempoolURL in test --- relayer/chains/bitcoin/provider_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/relayer/chains/bitcoin/provider_test.go b/relayer/chains/bitcoin/provider_test.go index 0cba96b1..0622fb18 100644 --- a/relayer/chains/bitcoin/provider_test.go +++ b/relayer/chains/bitcoin/provider_test.go @@ -54,7 +54,7 @@ func initBtcProviderTestnet() (*Provider, string) { RelayerPrivKey: "cTYRscQxVhtsGjHeV59RHQJbzNnJHbf3FX4eyX5JkpDhqKdhtRvy", RecoveryLockTime: 1234, OpCode: 0x5e, - MempoolURL: "https://mempool.space/api/v1", + MempoolURL: "https://mempool.space/testnet/api/tx", SlaveServer1: "http://localhost:8081", SlaveServer2: "http://localhost:8082", Port: "8080",