From 11010e3893e418e3d8145061c01b3db1ebbd4855 Mon Sep 17 00:00:00 2001 From: mollkeith Date: Thu, 23 Jan 2025 12:38:55 +0800 Subject: [PATCH] sign btc rawdata --- README.MD | 1 + app/arbiter/arbiter/arbiter.go | 222 +++++-- app/arbiter/config/config.go | 1 + .../contract_abi/arbiterConfigManagerABI.go | 585 ++++++++++++++++++ app/arbiter/contract/contract_listener.go | 7 +- app/arbiter/contract/contract_main.go | 82 ++- app/arbiter/main.go | 8 +- app/arbiter/manifest/config/config.yaml | 7 +- docker/dockerfile | 2 +- docs/deploy_loan_arbiter.sh | 6 +- 10 files changed, 825 insertions(+), 96 deletions(-) create mode 100644 app/arbiter/contract/contract_abi/arbiterConfigManagerABI.go diff --git a/README.MD b/README.MD index a36b72a..bd53edc 100644 --- a/README.MD +++ b/README.MD @@ -62,6 +62,7 @@ $ make escStartHeight: 21205821 escArbiterContractAddress: "0xD206be45b53Fa5C2065049c7a70B1aa1755a9475" escArbiterManagerContractAddress: "0x54eE4fc8951A936b6AA02079B76c497c0471c52A" + escConfigManagerContractAddress: "0x4421c63241A262C423277FFA82C376953072d25f" escArbiterAddress: "0x0262aB0ED65373cC855C34529fDdeAa0e686D913" dataPath: "~/loan_arbiter/data" keyFilePath: "~/loan_arbiter/keys" diff --git a/app/arbiter/arbiter/arbiter.go b/app/arbiter/arbiter/arbiter.go index 25c36bb..a33cb51 100644 --- a/app/arbiter/arbiter/arbiter.go +++ b/app/arbiter/arbiter/arbiter.go @@ -12,10 +12,14 @@ import ( "log" "os" "path/filepath" + "strings" "time" "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2/ecdsa" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/ethereum/go-ethereum/common" _ "github.com/gogf/gf/contrib/drivers/pgsql/v2" @@ -127,15 +131,16 @@ func (v *Arbiter) listenESCContract() { func (v *Arbiter) processArbiterSig() { g.Log().Info(v.ctx, "processArbiterSignature start") - // var netWorkParams = chaincfg.MainNetParams - // if strings.ToLower(v.config.Network) == "testnet" { - // netWorkParams = chaincfg.TestNet3Params - // } + var netWorkParams = chaincfg.MainNetParams + if strings.ToLower(v.config.Network) == "testnet" { + netWorkParams = chaincfg.TestNet3Params + } for { // get all deploy file files, err := os.ReadDir(v.config.LoanNeedSignReqPath) if err != nil { + g.Log().Error(v.ctx, "read dir error", err) continue } @@ -176,69 +181,152 @@ func (v *Arbiter) processArbiterSig() { g.Log().Info(v.ctx, "arbitratorAddress", arbitratorAddress) // sign btc tx - // tx, err := decodeTx(rawData) - // if err != nil { - // g.Log().Error(v.ctx, "decodeTx error", err, "rawData:", rawData) - // v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".decodeRawDataFailed") - // v.logger.Println("[ERR] SIGN: decode event failed, block:", logEvt.Block, "tx:", logEvt.TxHash) - // continue - // } - // script1Hash := sha256.Sum256(script) - // wsh, err := btcutil.NewAddressWitnessScriptHash(script1Hash[:], &netWorkParams) - // if err != nil { - // g.Log().Error(v.ctx, "NewAddressWitnessScriptHash err:", err) - // v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".newAddressWitnessScriptHashFailed") - // v.logger.Println("[ERR] SIGN: new addr witness sh failed, block:", logEvt.Block, "tx:", logEvt.TxHash) - // continue - // } - // payAddress, err := btcutil.DecodeAddress(wsh.EncodeAddress(), &netWorkParams) - // if err != nil { - // g.Log().Error(v.ctx, "DecodeAddress err:", err) - // v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".DecodeAddressFailed") - // v.logger.Println("[ERR] SIGN: decode address failed, block:", logEvt.Block, "tx:", logEvt.TxHash) - // continue - // } - // g.Log().Info(v.ctx, "payAddress", payAddress.String()) - // p2wsh, err := txscript.PayToAddrScript(payAddress) - // if err != nil { - // g.Log().Error(v.ctx, "PayToAddrScript err:", err) - // v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".PayToAddrScriptFailed") - // v.logger.Println("[ERR] SIGN: get ptaddr script failed, block:", logEvt.Block, "tx:", logEvt.TxHash) - // continue - // } - - // // get preOutput by tx.Inputs(idx) - // // only one input - // idx := 0 - // input := tx.TxIn[idx] - // g.Log().Info(v.ctx, "input.PreviousOutPoint.Hash", input.PreviousOutPoint.Hash.String()) - // preTx, err := v.mempoolAPI.GetRawTransaction(input.PreviousOutPoint.Hash.String()) - // if err != nil { - // g.Log().Error(v.ctx, "GetRawTransaction error", err) - // v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".GetRawTransactionFailed") - // v.logger.Println("[ERR] SIGN: get raw tx failed, block:", logEvt.Block, "tx:", logEvt.TxHash) - // continue - // } - - // preAmount := int64(preTx.Vout[input.PreviousOutPoint.Index].Value) - // prevFetcher := txscript.NewCannedPrevOutputFetcher( - // p2wsh, preAmount, - // ) - // sigHashes := txscript.NewTxSigHashes(tx, prevFetcher) - // sigHash, err := txscript.CalcWitnessSigHash(script, sigHashes, txscript.SigHashAll, tx, idx, preAmount) - // if err != nil { - // g.Log().Error(v.ctx, "CalcWitnessSigHash error", err) - // v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".CalcWitnessSigHashFailed") - // v.logger.Println("[ERR] SIGN: calculate sigHash failed, block:", logEvt.Block, "tx:", logEvt.TxHash) - // continue - // } - // var sigDataHash [32]byte - // copy(sigDataHash[:], sigHash) - // g.Log().Info(v.ctx, "sigHash", hex.EncodeToString(sigDataHash[:])) - // g.Log().Info(v.ctx, "script", hex.EncodeToString(script)) - - first := sha256.Sum256(rawData) - sigHash := sha256.Sum256(first[:]) + tx, err := decodeTx(rawData) + if err != nil { + g.Log().Error(v.ctx, "decodeTx error", err, "rawData:", rawData) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".decodeRawDataFailed") + v.logger.Println("[ERR] SIGN: decode event failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + + // todo check tx outputs, need to have output to arbiter + if len(tx.TxOut) != 2 { + g.Log().Error(v.ctx, "invalid tx outputs", len(tx.TxOut)) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".invalidTxOutputs") + v.logger.Println("[ERR] SIGN: invalid tx outputs count, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + + // get btc arbiter BTC address + arbiterAddress := common.HexToAddress(arbitratorAddress.String()) + arbitratorBTCAddress, err := v.escNode.GetArbiterBTCAddress(arbiterAddress) + if err != nil { + g.Log().Error(v.ctx, "GetArbiterOperatorAddress error", err) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".getArbiterOperatorAddressFailed") + v.logger.Println("[ERR] SIGN: get arbiter operator address failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + existArbiterBtcAddress := false + arbiterFeeVoutIndex := 0 + for i, vout := range tx.TxOut { + if vout.Value < 546 { + g.Log().Error(v.ctx, "invalid tx outputs with dust value") + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".invalidTxOutputs") + v.logger.Println("[ERR] SIGN: invalid tx outputs with dust value, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + _, addrs, _, err := txscript.ExtractPkScriptAddrs(vout.PkScript, &netWorkParams) + if err != nil { + g.Log().Error(v.ctx, "ExtractPkScriptAddrs err:", err) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".ExtractPkScriptAddrsFailed") + v.logger.Println("[ERR] SIGN: extract pk script failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + for _, addr := range addrs { + g.Log().Info(v.ctx, "tx vout addr:", addr.String(), "arbitratorBTCAddress:", arbitratorBTCAddress) + if addr.String() == arbitratorBTCAddress { + existArbiterBtcAddress = true + arbiterFeeVoutIndex = i + } + } + } + if !existArbiterBtcAddress { + g.Log().Error(v.ctx, "invalid tx outputs, without fee to arbiter") + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".invalidTxOutputs") + v.logger.Println("[ERR] SIGN: invalid tx outputs, without fee to arbiter, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + + // get pay address by script + script1Hash := sha256.Sum256(script) + wsh, err := btcutil.NewAddressWitnessScriptHash(script1Hash[:], &netWorkParams) + if err != nil { + g.Log().Error(v.ctx, "NewAddressWitnessScriptHash err:", err) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".newAddressWitnessScriptHashFailed") + v.logger.Println("[ERR] SIGN: new addr witness sh failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + payAddress, err := btcutil.DecodeAddress(wsh.EncodeAddress(), &netWorkParams) + if err != nil { + g.Log().Error(v.ctx, "DecodeAddress err:", err) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".DecodeAddressFailed") + v.logger.Println("[ERR] SIGN: decode address failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + g.Log().Info(v.ctx, "payAddress", payAddress.String()) + p2wsh, err := txscript.PayToAddrScript(payAddress) + if err != nil { + g.Log().Error(v.ctx, "PayToAddrScript err:", err) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".PayToAddrScriptFailed") + v.logger.Println("[ERR] SIGN: get ptaddr script failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + + // get preOutput by tx.Inputs(idx) + idx := 1 - arbiterFeeVoutIndex + input := tx.TxIn[idx] + g.Log().Info(v.ctx, "input.PreviousOutPoint.Hash", input.PreviousOutPoint.Hash.String()) + preTx, err := v.mempoolAPI.GetRawTransaction(input.PreviousOutPoint.Hash.String()) + if err != nil { + g.Log().Error(v.ctx, "GetRawTransaction error", err) + // v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".GetRawTransactionFailed") + v.logger.Println("[ERR] SIGN: get raw tx failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + // check utxo tx output counts + if len(preTx.Vout) <= int(input.PreviousOutPoint.Index) { + g.Log().Error(v.ctx, "invalid input.PreviousOutPoint.Index", input.PreviousOutPoint.Index) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".invalidPreviousOutPointIndex") + v.logger.Println("[ERR] SIGN: invalid input.PreviousOutPoint.Index, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + preAmount := int64(preTx.Vout[input.PreviousOutPoint.Index].Value) + + // check fee rate + feeRate, err := v.escNode.GetArbitrationBTCFeeRate() + if err != nil { + g.Log().Error(v.ctx, "GetArbitrationBTCFeeRate error", err) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".GetArbitrationBTCFeeRateFailed") + v.logger.Println("[ERR] SIGN: get fee rate failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + arbiterFee := preAmount * feeRate.Int64() / 10000 + if tx.TxOut[arbiterFeeVoutIndex].Value < arbiterFee { + g.Log().Error(v.ctx, "invalid fee rate", feeRate) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".invalidFeeRate") + v.logger.Println("[ERR] SIGN: invalid fee rate, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + + // check utxo address + g.Log().Info(v.ctx, "### preTx Vout:", preTx.Vout[input.PreviousOutPoint.Index]) + utxoAddr := preTx.Vout[input.PreviousOutPoint.Index].ScriptpubkeyAddress + if utxoAddr != payAddress.EncodeAddress() { + g.Log().Error(v.ctx, "invalid utxo address:", utxoAddr, "need to be:", payAddress) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".invalidUtxoAddress") + v.logger.Println("[ERR] SIGN: invalid utxo address, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + + // calculate sigHash + prevFetcher := txscript.NewCannedPrevOutputFetcher( + p2wsh, preAmount, + ) + sigHashes := txscript.NewTxSigHashes(tx, prevFetcher) + sigHash, err := txscript.CalcWitnessSigHash(script, sigHashes, txscript.SigHashAll, tx, idx, preAmount) + if err != nil { + g.Log().Error(v.ctx, "CalcWitnessSigHash error", err) + v.moveToDirectory(filePath, v.config.LoanNeedSignFailedPath+"/"+file.Name()+".CalcWitnessSigHashFailed") + v.logger.Println("[ERR] SIGN: calculate sigHash failed, block:", logEvt.Block, "tx:", logEvt.TxHash) + continue + } + var sigDataHash [32]byte + copy(sigDataHash[:], sigHash) + g.Log().Info(v.ctx, "sigHash", hex.EncodeToString(sigDataHash[:])) + g.Log().Info(v.ctx, "script", hex.EncodeToString(script)) + + // first := sha256.Sum256(rawData) + // sigHash := sha256.Sum256(first[:]) // ecdsa sign priKeyBytes, _ := hex.DecodeString(v.account.PrivateKey) diff --git a/app/arbiter/config/config.go b/app/arbiter/config/config.go index 3c69418..a6ab300 100644 --- a/app/arbiter/config/config.go +++ b/app/arbiter/config/config.go @@ -12,6 +12,7 @@ type Config struct { ESCStartHeight uint64 ESCArbiterContractAddress string ESCArbiterManagerContractAddress string + ESCConfigManagerContractAddress string ESCArbiterAddress string DataDir string diff --git a/app/arbiter/contract/contract_abi/arbiterConfigManagerABI.go b/app/arbiter/contract/contract_abi/arbiterConfigManagerABI.go new file mode 100644 index 0000000..acc477f --- /dev/null +++ b/app/arbiter/contract/contract_abi/arbiterConfigManagerABI.go @@ -0,0 +1,585 @@ +// Copyright (c) 2025 The bel2 developers + +package contract_abi + +const ArbiterConfigManagerABI = `[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidInitialization", + "type": "error" + }, + { + "inputs": [], + "name": "NotInitializing", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldValue", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newValue", + "type": "uint256" + } + ], + "name": "ConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint64", + "name": "version", + "type": "uint64" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "ARBITRATION_BTC_FEE_RATE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ARBITRATION_FROZEN_PERIOD", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ARBITRATION_TIMEOUT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_STAKE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_TRANSACTION_DURATION", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_STAKE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_STAKE_LOCKED_TIME", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_TRANSACTION_DURATION", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_COMPENSATION_FEE_RATE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_FEE_COLLECTOR", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SYSTEM_FEE_RATE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TRANSACTION_MIN_FEE_RATE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllConfigs", + "outputs": [ + { + "internalType": "bytes32[]", + "name": "keys", + "type": "bytes32[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getArbitrationBTCFeeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getArbitrationFrozenPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getArbitrationTimeout", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "key", + "type": "bytes32" + } + ], + "name": "getConfig", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSystemCompensationFeeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSystemFeeCollector", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSystemFeeRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "feeRate", + "type": "uint256" + } + ], + "name": "setArbitrationBTCFeeRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "period", + "type": "uint256" + } + ], + "name": "setArbitrationFrozenPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timeout", + "type": "uint256" + } + ], + "name": "setArbitrationTimeout", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "keys", + "type": "bytes32[]" + }, + { + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "setConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setMaxStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "setMaxTransactionDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setMinStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "time", + "type": "uint256" + } + ], + "name": "setMinStakeLockedTime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "duration", + "type": "uint256" + } + ], + "name": "setMinTransactionDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "name": "setSystemCompensationFeeRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "collector", + "type": "address" + } + ], + "name": "setSystemFeeCollector", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "name": "setSystemFeeRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rate", + "type": "uint256" + } + ], + "name": "setTransactionMinFeeRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ]` diff --git a/app/arbiter/contract/contract_listener.go b/app/arbiter/contract/contract_listener.go index 5d95cf7..334c05d 100644 --- a/app/arbiter/contract/contract_listener.go +++ b/app/arbiter/contract/contract_listener.go @@ -36,23 +36,24 @@ func NewListener(ctx context.Context, client *CrossClient, } func (c *ContractListener) Start(startHeight uint64) (uint64, error) { + confirmBlocksCount := uint64(10) endBlock, err := c.queryClient.GetLatestHeight() if err != nil { g.Log().Warning(c.ctx, "GetLatestHeight failed", err) return math.MaxUint64, err } - if startHeight > endBlock-2 { + if startHeight > endBlock-confirmBlocksCount { return math.MaxUint64, errors.New("start block must be less than end block") } distance := uint64(10000) toBlock := startHeight loanQuery := c.queryClient.BuildQuery(c.loanContract, c.listeneTopics, nil, nil) - for i := startHeight; i <= endBlock-2; i += distance { + for i := startHeight; i <= endBlock-confirmBlocksCount; i += distance { if i+distance < endBlock { toBlock = i + distance } else { - toBlock = endBlock - 2 + toBlock = endBlock - confirmBlocksCount } loanQuery.FromBlock = big.NewInt(0).SetUint64(i) loanQuery.ToBlock = big.NewInt(0).SetUint64(toBlock) diff --git a/app/arbiter/contract/contract_main.go b/app/arbiter/contract/contract_main.go index 9098074..b747aa1 100644 --- a/app/arbiter/contract/contract_main.go +++ b/app/arbiter/contract/contract_main.go @@ -30,34 +30,34 @@ type ArbitratorContract struct { chan_interrupt chan struct{} Loan_abi abi.ABI Arbiter_manager_abi abi.ABI + Arbiter_config_abi abi.ABI loanContract *common.Address arbiterManagerContract *common.Address + configManagerContract *common.Address cfg *config.Config logger *log.Logger } // ArbitratorStatus should be defined according to the possible statuses you have. -type ArbitratorStatus int // Adjust this type based on actual values in Solidity type ArbitratorInfo struct { - Arbitrator string // Arbitrator Ethereum address - CurrentFeeRate *big.Int // Current fee rate - PendingFeeRate *big.Int // Pending new fee rate - Status ArbitratorStatus // Arbitrator status - ActiveTransactionID [32]byte // Current transaction ID (bytes32) - EthAmount *big.Int // ETH stake amount - Erc20Token string // ERC20 token address - NftContract string // NFT contract address - NftTokenIds []uint64 // NFT token IDs - Operator string // Operator address - OperatorBtcPubKey []byte // Bitcoin public key - OperatorBtcAddress string // Bitcoin address - Deadline time.Time // Last arbitration time , deadline - RevenueBtcPubKey []byte // Bitcoin public key for receiving arbitrator earnings - RevenueBtcAddress string // Bitcoin address for receiving arbitrator earnings - RevenueETHAddress string // ETH address for receiving arbitrator earnings - LastSubmittedWorkTime time.Time // Last submitted work time + Arbitrator string // Arbitrator Ethereum address + Paused bool // Paused + CurrentFeeRate *big.Int // Current fee rate + ActiveTransactionID [32]byte // Current transaction ID (bytes32) + EthAmount *big.Int // ETH stake amount + Erc20Token string // ERC20 token address + NftContract string // NFT contract address + NftTokenIds []uint64 // NFT token IDs + Operator string // Operator address + OperatorBtcPubKey []byte // Bitcoin public key + OperatorBtcAddress string // Bitcoin address + Deadline *big.Int // Last arbitration time , deadline + RevenueBtcPubKey []byte // Bitcoin public key for receiving arbitrator earnings + RevenueBtcAddress string // Bitcoin address for receiving arbitrator earnings + RevenueETHAddress string // ETH address for receiving arbitrator earnings + LastSubmittedWorkTime *big.Int // Last submitted work time } func New(ctx context.Context, cfg *config.Config, privateKey string, logger *log.Logger) (*ArbitratorContract, error) { @@ -67,6 +67,7 @@ func New(ctx context.Context, cfg *config.Config, privateKey string, logger *log } loanAddress := common.HexToAddress(cfg.ESCArbiterContractAddress) arbiterManagerAddress := common.HexToAddress(cfg.ESCArbiterManagerContractAddress) + configManagerAddress := common.HexToAddress(cfg.ESCConfigManagerContractAddress) eventChan := make(chan *events.ContractLogEvent, 3) chan_interrupt := make(chan struct{}) listener, err := NewListener(ctx, client, loanAddress, eventChan) @@ -82,6 +83,10 @@ func New(ctx context.Context, cfg *config.Config, privateKey string, logger *log if err != nil { return nil, err } + arbiterConfigABI, err := abi.JSON(strings.NewReader(contract_abi.ArbiterConfigManagerABI)) + if err != nil { + return nil, err + } submitter, err := NewSubmitter(ctx, client, privateKey) if err != nil { @@ -95,8 +100,10 @@ func New(ctx context.Context, cfg *config.Config, privateKey string, logger *log chan_interrupt: chan_interrupt, Loan_abi: loanABI, Arbiter_manager_abi: arbiterManagerABI, + Arbiter_config_abi: arbiterConfigABI, loanContract: &loanAddress, arbiterManagerContract: &arbiterManagerAddress, + configManagerContract: &configManagerAddress, cfg: cfg, logger: logger, } @@ -236,3 +243,42 @@ func (c *ArbitratorContract) getArbiterOperatorAddress(arbiter common.Address) ( return common.HexToAddress(info.Operator), nil } + +func (c *ArbitratorContract) GetArbiterBTCAddress(arbiter common.Address) (string, error) { + input, err := c.Arbiter_manager_abi.Pack("getArbitratorInfo", arbiter) + if err != nil { + return "", err + } + // use c.arbiterManagerContract to call get getArbitratorInfo operator address + msg := ethereum.CallMsg{From: common.Address{}, To: c.arbiterManagerContract, Data: input} + result, err := c.submitter.CallContract(context.TODO(), msg, nil) + if err != nil { + return "", err + } + ev, err := c.Arbiter_manager_abi.Unpack("getArbitratorInfo", result) + if err != nil || len(ev) == 0 { + g.Log().Error(c.ctx, "parse ArbitratorInfo UnpackIntoMap error", err) + return "", err + } + info := ArbitratorInfo{} + data, err := json.Marshal(ev[0]) + if err != nil { + return "", err + } + json.Unmarshal(data, &info) + + return info.RevenueBtcAddress, nil +} + +func (c *ArbitratorContract) GetArbitrationBTCFeeRate() (*big.Int, error) { + input, err := c.Arbiter_config_abi.Pack("getArbitrationBTCFeeRate") + if err != nil { + return nil, err + } + msg := ethereum.CallMsg{From: common.Address{}, To: c.configManagerContract, Data: input} + result, err := c.submitter.CallContract(context.TODO(), msg, nil) + if err != nil { + return nil, err + } + return big.NewInt(0).SetBytes(result), nil +} diff --git a/app/arbiter/main.go b/app/arbiter/main.go index ba3c758..c132a75 100644 --- a/app/arbiter/main.go +++ b/app/arbiter/main.go @@ -15,8 +15,8 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gctx" - "github.com/BeL2Labs/Arbiter_Signer/app/arbiter/config" "github.com/BeL2Labs/Arbiter_Signer/app/arbiter/arbiter" + "github.com/BeL2Labs/Arbiter_Signer/app/arbiter/config" ) func main() { @@ -82,6 +82,11 @@ func initConfig(ctx context.Context) *config.Config { g.Log().Error(ctx, "get escArbiterManagerAddress config err:", err) os.Exit(1) } + escConfigManagerAddress, err := g.Cfg().Get(ctx, "arbiter.escConfigManagerContractAddress") + if err != nil { + g.Log().Error(ctx, "get escConfigManagerAddress config err:", err) + os.Exit(1) + } escArbiterAddress, err := g.Cfg().Get(ctx, "arbiter.escArbiterAddress") if err != nil { g.Log().Error(ctx, "get escArbiterAddress config err:", err) @@ -128,6 +133,7 @@ func initConfig(ctx context.Context) *config.Config { ESCStartHeight: escStartHeight.Uint64(), ESCArbiterContractAddress: escArbiterContractAddress.String(), ESCArbiterManagerContractAddress: escArbiterManagerAddress.String(), + ESCConfigManagerContractAddress: escConfigManagerAddress.String(), ESCArbiterAddress: escArbiterAddress.String(), DataDir: dataPath, diff --git a/app/arbiter/manifest/config/config.yaml b/app/arbiter/manifest/config/config.yaml index 80b31b3..4922cba 100644 --- a/app/arbiter/manifest/config/config.yaml +++ b/app/arbiter/manifest/config/config.yaml @@ -4,12 +4,13 @@ chain: # Arbiter arbiter: - listener: true, - signer: true, + listener: true + signer: true network: "mainnet" - escStartHeight: 28437808 + escStartHeight: 28804848 escArbiterContractAddress: "0xA10b92006743Ef3B12077da67e465963743b03D3" escArbiterManagerContractAddress: "0x9963b5214434776D043A4e98Bc7f33321F6aaCfc" + escConfigManagerContractAddress: "0x4421c63241A262C423277FFA82C376953072d25f" escArbiterAddress: "0x0262aB0ED65373cC855C34529fDdeAa0e686D913" dataPath: "./app/arbiter/data" keyFilePath: "./app/arbiter/data/keys/" diff --git a/docker/dockerfile b/docker/dockerfile index f883345..6c23c66 100644 --- a/docker/dockerfile +++ b/docker/dockerfile @@ -1,8 +1,8 @@ FROM ubuntu:20.04 RUN apt-get update && apt-get install -y curl -RUN cd ~ RUN apt-get install wget -y RUN apt-get install vim -y +RUN cd ~ RUN wget https://download.bel2.org/loan-arbiter/deploy_loan_arbiter.sh RUN chmod a+x deploy_loan_arbiter.sh RUN echo $ARBITER_ADDRESS diff --git a/docs/deploy_loan_arbiter.sh b/docs/deploy_loan_arbiter.sh index 1799df5..9f2a575 100644 --- a/docs/deploy_loan_arbiter.sh +++ b/docs/deploy_loan_arbiter.sh @@ -76,7 +76,7 @@ deploy_arbiter() cd $SCRIPT_PATH #prepare config.yaml - wget https://download.bel2.org/loan-arbiter/loan-arbiter-v0.0.1/conf.tgz + wget -O conf.tgz https://download.bel2.org/loan-arbiter/loan-arbiter-v0.0.1/conf.tgz tar xf conf.tgz #mv conf/config.yaml . sed -i "s/0x0262aB0ED65373cC855C34529fDdeAa0e686D913/$1/g" config.yaml @@ -90,7 +90,7 @@ deploy_arbiter() if [ "$(uname -m)" == "armv6l" ] || [ "$(uname -m)" == "armv7l" ] || [ "$(uname -m)" == "aarch64" ]; then echo "The current system architecture is ARM" echo_info "Downloading loan arbiter..." - wget https://download.bel2.org/loan-arbiter/loan-arbiter-v0.0.1/loan-arbiter-linux-arm64.tgz + wget -O loan-arbiter-linux-arm64.tgz https://download.bel2.org/loan-arbiter/loan-arbiter-v0.0.1/loan-arbiter-linux-arm64.tgz tar xf loan-arbiter-linux-arm64.tgz echo_info "Replacing arbiter.." cp -v loan-arbiter-linux-arm64/arbiter ~/loan_arbiter/ @@ -101,7 +101,7 @@ deploy_arbiter() else echo "The current system architecture is x86" echo_info "Downloading loan arbiter..." - wget https://download.bel2.org/loan-arbiter/loan-arbiter-v0.0.1/loan-arbiter-linux-x86_64.tgz + wget -O loan-arbiter-linux-x86_64.tgz https://download.bel2.org/loan-arbiter/loan-arbiter-v0.0.1/loan-arbiter-linux-x86_64.tgz tar xf loan-arbiter-linux-x86_64.tgz echo_info "Replacing arbiter.." cp -v loan-arbiter-linux-x86_64/arbiter ~/loan_arbiter/