From 1d7e2b01462360f9063f473f4793e779089d7116 Mon Sep 17 00:00:00 2001 From: jacobdenver007 Date: Thu, 8 Apr 2021 18:27:04 +0800 Subject: [PATCH 1/3] fix(tron): add trc10 test for ci --- offchain-modules/config.json.example | 4 +- .../src/packages/handlers/tron.ts | 7 +- .../src/scripts/integration-test/tron.ts | 90 +++++++++++++++---- 3 files changed, 78 insertions(+), 23 deletions(-) diff --git a/offchain-modules/config.json.example b/offchain-modules/config.json.example index 86d9c153..ccd82d42 100644 --- a/offchain-modules/config.json.example +++ b/offchain-modules/config.json.example @@ -85,7 +85,7 @@ } }, "tron": { - "tronGridUrl": "https://nile.trongrid.io/", + "tronGridUrl": "https://api.shasta.trongrid.io", "committee": { "address": "TX3MGfWT5aGv81vTSdZtr6hbHxhMVh1FFM", "permissionId": 2, @@ -94,7 +94,7 @@ "EE782FE170F680D6CAB340ECA5ED2F6E05B0B9809082CF745207E87734211C72" ] }, - "feeLimit": 1000000 + "feeLimit": 10000000 } } } diff --git a/offchain-modules/src/packages/handlers/tron.ts b/offchain-modules/src/packages/handlers/tron.ts index 31d664eb..83b32666 100644 --- a/offchain-modules/src/packages/handlers/tron.ts +++ b/offchain-modules/src/packages/handlers/tron.ts @@ -77,6 +77,10 @@ export class TronHandler { fingerprint: fingerprint, }); for (const data of txs.data) { + if (Object.keys(data.token_info).length == 0) { + logger.debug('invalid trc20 tx, token info is undefined', data); + continue; + } const tx = await this.tronWeb.trx.getTransaction(data.transaction_id); const event = { tx_hash: data.transaction_id, @@ -162,7 +166,7 @@ export class TronHandler { const trc20LockEvents = await this.getTrc20TxsLockEvents(minTimestamp); const totalLockEvents = trxAndTrc10Events.concat(trc20LockEvents); - logger.debug('total lock events', totalLockEvents.length); + logger.debug('total lock events', totalLockEvents); for (const event of totalLockEvents) { if (event.timestamp <= minTimestamp) { @@ -276,7 +280,6 @@ export class TronHandler { logger.debug('flush pending tx to confirm'); const pendingRecords = await this.db.getTronUnlockRecords('pending'); for (const pendingRecord of pendingRecords) { - // todo: check tx is confirmed try { const confirmedTx = await this.tronWeb.trx.getConfirmedTransaction(pendingRecord.tronTxHash); console.log(confirmedTx); diff --git a/offchain-modules/src/scripts/integration-test/tron.ts b/offchain-modules/src/scripts/integration-test/tron.ts index f86b4b6b..857f487c 100644 --- a/offchain-modules/src/scripts/integration-test/tron.ts +++ b/offchain-modules/src/scripts/integration-test/tron.ts @@ -23,6 +23,36 @@ async function transferTrx(tronWeb, from, to, amount, memo, priv) { return broad_tx; } +async function transferTrc10(tronWeb, from, to, amount, tokenID, memo, priv) { + const unsigned_tx = await tronWeb.transactionBuilder.sendToken(to, amount, tokenID, from); + const unsignedWithMemoTx = await tronWeb.transactionBuilder.addUpdateData(unsigned_tx, memo, 'utf8'); + const signed_tx = await tronWeb.trx.sign(unsignedWithMemoTx, priv); + const broad_tx = await tronWeb.trx.broadcast(signed_tx); + return broad_tx; +} + +async function transferTrc20(tronWeb, from, to, amount, contractAddress, memo, priv) { + const options = {}; + const functionSelector = 'transfer(address,uint256)'; + const params = [ + { type: 'address', value: to }, + { type: 'uint256', value: amount }, + ]; + + const unsigned_tx = await tronWeb.transactionBuilder.triggerSmartContract( + contractAddress, + functionSelector, + options, + params, + from, + ); + const unsignedWithMemoTx = await tronWeb.transactionBuilder.addUpdateData(unsigned_tx.transaction, memo, 'utf8'); + + const signed_tx = await tronWeb.trx.sign(unsignedWithMemoTx, priv); + const broad_tx = await tronWeb.trx.broadcast(signed_tx); + return broad_tx; +} + async function main() { const conn = await createConnection(); const ckbDb = new CkbDb(conn); @@ -43,21 +73,50 @@ async function main() { const recipientLockscript = 'ckt1qyq2f0uwf3lk7e0nthfucvxgl3zu36v6zuwq6mlzps'; const sudtExtraData = 'transfer 100 to ckt1qyq2f0uwf3lk7e0nthfucvxgl3zu36v6zuwq6mlzps'; const memo = recipientLockscript.concat(',').concat(sudtExtraData); - const lockRes = await transferTrx(tronWeb, from, to, amount, memo, userPrivateKey); - const txHash: string = lockRes.transaction.txID; + + const trxLockRes = await transferTrx(tronWeb, from, to, amount, memo, userPrivateKey); + const trxTxHash: string = trxLockRes.transaction.txID; + + const trc10LockRes = await transferTrc10(tronWeb, from, to, amount, '1000696', memo, userPrivateKey); + const trc10TxHash: string = trc10LockRes.transaction.txID; + + const trc20LockRes = await transferTrc20( + tronWeb, + from, + to, + amount, + 'TVWvkCasxAJUyzPKMQ2Rus1NtmBwrkVyBR', + memo, + userPrivateKey, + ); + const trc20TxHash: string = trc20LockRes.transaction.txID; // create tron unlock const recipientAddress = 'TS6VejPL8cQy6pA8eDGyusmmhCrXHRdJK6'; - const record = { + const trxRecord = { ckbTxHash: genRandomHex(32), asset: 'trx', assetType: 'trx', amount: '100', recipientAddress, }; - await ckbDb.createTronUnlock([record]); + const trc10Record = { + ckbTxHash: genRandomHex(32), + asset: '1000696', + assetType: 'trc10', + amount: '100', + recipientAddress, + }; + const trc20Record = { + ckbTxHash: genRandomHex(32), + asset: 'TVWvkCasxAJUyzPKMQ2Rus1NtmBwrkVyBR', + assetType: 'trc20', + amount: '100', + recipientAddress, + }; + await ckbDb.createTronUnlock([trxRecord, trc10Record, trc20Record]); - const checkEffect = async () => { + const checkEffect = async (txHash, ckbTxHash, asset, assetType) => { // check TronLock and CkbMint saved. const tronLockRecords = await conn.manager.find(TronLock, { where: { @@ -70,8 +129,8 @@ async function main() { assert(tronLockRecord.memo === memo); assert(tronLockRecord.sender === from); - assert(tronLockRecord.asset === 'trx'); - assert(tronLockRecord.assetType === 'trx'); + assert(tronLockRecord.asset === asset); + assert(tronLockRecord.assetType === assetType); const ckbMintRecords = await conn.manager.find(CkbMint, { where: { @@ -84,35 +143,28 @@ async function main() { assert(ckbMintRecord.chain === ChainType.TRON); assert(ckbMintRecord.sudtExtraData === sudtExtraData); assert(ckbMintRecord.status === 'todo'); - assert(ckbMintRecord.asset === 'trx'); + assert(ckbMintRecord.asset === asset); assert(ckbMintRecord.amount === amount.toString()); assert(ckbMintRecord.recipientLockscript === recipientLockscript); // check unlock record send const tronUnlockRecords = await conn.manager.find(TronUnlock, { where: { - ckbTxHash: record.ckbTxHash, + ckbTxHash: ckbTxHash, }, }); assert(tronUnlockRecords.length === 1); const tronUnlockRecord = tronUnlockRecords[0]; assert(tronUnlockRecord.status === 'success'); - - // const unlockReceipt = await provider.getTransactionReceipt(ethUnlockRecord.ethTxHash); - // logger.debug('unlockReceipt', unlockReceipt); - // assert(unlockReceipt.logs.length === 1); - // const parsedLog = iface.parseLog(unlockReceipt.logs[0]); - // logger.debug('parsedLog', parsedLog); - // assert(parsedLog.args.token === record.asset); - // assert(record.amount === parsedLog.args.receivedAmount.toHexString()); - // assert(record.recipientAddress === parsedLog.args.recipient); }; // try 100 times and wait for 3 seconds every time. for (let i = 0; i < 100; i++) { await asyncSleep(10000); try { - await checkEffect(); + await checkEffect(trxTxHash, trxRecord.ckbTxHash, 'trx', 'trx'); + await checkEffect(trc10TxHash, trc10Record.ckbTxHash, '1000696', 'trc10'); + //await checkEffect(trc20TxHash, trc20Record.ckbTxHash, 'TVWvkCasxAJUyzPKMQ2Rus1NtmBwrkVyBR', 'trc20'); } catch (e) { logger.warn('The tron component integration not pass yet.', { i, e }); continue; From c0680d520076233680db91f8b6b590f6c26fa85a Mon Sep 17 00:00:00 2001 From: jacobdenver007 Date: Thu, 8 Apr 2021 22:43:29 +0800 Subject: [PATCH 2/3] fix(tron): add check balance --- .../src/scripts/integration-test/tron.ts | 62 ++++++++++--------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/offchain-modules/src/scripts/integration-test/tron.ts b/offchain-modules/src/scripts/integration-test/tron.ts index e99d08b4..5597a1f9 100644 --- a/offchain-modules/src/scripts/integration-test/tron.ts +++ b/offchain-modules/src/scripts/integration-test/tron.ts @@ -113,6 +113,29 @@ async function main() { const recipientAddress = 'TS6VejPL8cQy6pA8eDGyusmmhCrXHRdJK6'; let burnTxHash; + + const getBalance = async (assetName) => { + const account = new Account(PRI_KEY); + const ownLockHash = ckb.utils.scriptToHash(await account.getLockscript()); + const asset = new TronAsset(assetName, ownLockHash); + const bridgeCellLockscript = { + codeHash: ForceBridgeCore.config.ckb.deps.bridgeLock.script.codeHash, + hashType: ForceBridgeCore.config.ckb.deps.bridgeLock.script.hashType, + args: asset.toBridgeLockscriptArgs(), + }; + const sudtArgs = ckb.utils.scriptToHash(bridgeCellLockscript); + const sudtType = { + codeHash: ForceBridgeCore.config.ckb.deps.sudtType.script.codeHash, + hashType: ForceBridgeCore.config.ckb.deps.sudtType.script.hashType, + args: sudtArgs, + }; + const balance = await collector.getSUDTBalance( + new Script(sudtType.codeHash, sudtType.args, sudtType.hashType), + await account.getLockscript(), + ); + return balance; + }; + const checkLock = async (txHash, assetName, assetType, sendBurn) => { // check TronLock and CkbMint saved. const tronLockRecords = await conn.manager.find(TronLock, { @@ -145,31 +168,13 @@ async function main() { assert(ckbMintRecord.recipientLockscript === recipientLockscript); // check sudt balance. - const account = new Account(PRI_KEY); - const ownLockHash = ckb.utils.scriptToHash(await account.getLockscript()); - const asset = new TronAsset(assetName, ownLockHash); - const bridgeCellLockscript = { - codeHash: ForceBridgeCore.config.ckb.deps.bridgeLock.script.codeHash, - hashType: ForceBridgeCore.config.ckb.deps.bridgeLock.script.hashType, - args: asset.toBridgeLockscriptArgs(), - }; - const sudtArgs = ckb.utils.scriptToHash(bridgeCellLockscript); - const sudtType = { - codeHash: ForceBridgeCore.config.ckb.deps.sudtType.script.codeHash, - hashType: ForceBridgeCore.config.ckb.deps.sudtType.script.hashType, - args: sudtArgs, - }; - const balance = await collector.getSUDTBalance( - new Script(sudtType.codeHash, sudtType.args, sudtType.hashType), - await account.getLockscript(), - ); + const balance = await getBalance(assetName); if (!sendBurn) { logger.debug('assetName', assetName); logger.debug('sudt balance:', balance); - // logger.debug('expect balance:', Amount.fromUInt128LE(bigintToSudtAmount(amount)).toHexString()); logger.debug('expect balance:', new Amount(amount.toString())); - //assert(balance.eq(new Amount(amount.toString()))); + assert(balance.eq(new Amount(amount.toString()))); } }; @@ -194,13 +199,14 @@ async function main() { return txHash; }; - const checkUnlock = async (burnTxHash) => { + const checkUnlock = async (burnTxHash, assetName) => { const burnAmount = 1; - // logger.debug('sudt balance:', balance); - // const expectBalance = new Amount((amount - burnAmount).toString()); - // logger.debug('expect sudt balance:', expectBalance); - // // logger.debug('expect balance:', Amount.fromUInt128LE(bigintToSudtAmount(amount)).sub(Amount.fromUInt128LE('0x01'))); - // assert(balance.eq(expectBalance)); + const balance = await getBalance(assetName); + + logger.debug('sudt balance:', balance); + const expectBalance = new Amount((amount - burnAmount).toString()); + logger.debug('expect sudt balance:', expectBalance); + assert(balance.eq(expectBalance)); // check unlock record send const tronUnlockRecords = await conn.manager.find(TronUnlock, { @@ -225,12 +231,12 @@ async function main() { await checkLock(trxTxHash, 'trx', 'trx', trxSendBurn); burnTrxTxHash = await burn(trxSendBurn, 'trx', burnTrxTxHash); trxSendBurn = true; - await checkUnlock(burnTrxTxHash); + await checkUnlock(burnTrxTxHash, 'trx'); await checkLock(trc10TxHash, '1000696', 'trc10', trc10SendBurn); burnTrc10TxHash = await burn(trc10SendBurn, '1000696', burnTrc10TxHash); trc10SendBurn = true; - await checkUnlock(burnTrc10TxHash); + await checkUnlock(burnTrc10TxHash, '1000696'); //await checkEffect(trc20TxHash, 'TVWvkCasxAJUyzPKMQ2Rus1NtmBwrkVyBR', 'trc20'); } catch (e) { From c20ebd9c962b4abc18e3275efa25478675051aa4 Mon Sep 17 00:00:00 2001 From: jacobdenver007 Date: Thu, 8 Apr 2021 23:49:34 +0800 Subject: [PATCH 3/3] fix(tron): rm unused code --- .../src/packages/handlers/tron.ts | 1 - .../src/scripts/integration-test/test.ts | 99 ------------------- offchain-modules/start-mysql.sh | 31 ------ 3 files changed, 131 deletions(-) delete mode 100644 offchain-modules/src/scripts/integration-test/test.ts delete mode 100644 offchain-modules/start-mysql.sh diff --git a/offchain-modules/src/packages/handlers/tron.ts b/offchain-modules/src/packages/handlers/tron.ts index 2da903d4..956ef0eb 100644 --- a/offchain-modules/src/packages/handlers/tron.ts +++ b/offchain-modules/src/packages/handlers/tron.ts @@ -221,7 +221,6 @@ export class TronHandler { for (const key of this.committee.keys) { signed_tx = await this.tronWeb.trx.multiSign(signed_tx, key); } - logger.debug(signed_tx); return signed_tx; } diff --git a/offchain-modules/src/scripts/integration-test/test.ts b/offchain-modules/src/scripts/integration-test/test.ts deleted file mode 100644 index 78952e79..00000000 --- a/offchain-modules/src/scripts/integration-test/test.ts +++ /dev/null @@ -1,99 +0,0 @@ -import 'module-alias/register'; -import nconf from 'nconf'; -import { Config, TronConfig } from '@force-bridge/config'; -import { logger } from '@force-bridge/utils/logger'; -import { asyncSleep, bigintToSudtAmount } from '@force-bridge/utils'; -import { createConnection } from 'typeorm'; -import { CkbDb, TronDb } from '@force-bridge/db'; -import { CkbMint, TronLock, TronUnlock } from '@force-bridge/db/model'; -import assert from 'assert'; -import { ChainType, EthAsset, TronAsset } from '@force-bridge/ckb/model/asset'; -import { Account } from '@force-bridge/ckb/model/accounts'; -import { CkbTxGenerator } from '@force-bridge/ckb/tx-helper/generator'; -import { IndexerCollector } from '@force-bridge/ckb/tx-helper/collector'; -import { Amount, Script } from '@lay2/pw-core'; -import { CkbIndexer } from '@force-bridge/ckb/tx-helper/indexer'; -import { ForceBridgeCore } from '@force-bridge/core'; -import { BigNumber } from 'ethers'; -const TronWeb = require('tronweb'); - -const PRI_KEY = '0xa800c82df5461756ae99b5c6677d019c98cc98c7786b80d7b2e77256e46ea1fe'; -const CKB = require('@nervosnetwork/ckb-sdk-core').default; -const CKB_URL = process.env.CKB_URL || 'http://127.0.0.1:8114'; -const indexer = new CkbIndexer('http://127.0.0.1:8114', 'http://127.0.0.1:8116'); -const collector = new IndexerCollector(indexer); -const ckb = new CKB(CKB_URL); - -async function transferTrx(tronWeb, from, to, amount, memo, priv) { - const from_hex = tronWeb.address.toHex(from); - const to_hex = tronWeb.address.toHex(to); - - const unsigned_tx = await tronWeb.transactionBuilder.sendTrx(to_hex, amount, from_hex); - const unsignedWithMemoTx = await tronWeb.transactionBuilder.addUpdateData(unsigned_tx, memo, 'utf8'); - - const signed_tx = await tronWeb.trx.sign(unsignedWithMemoTx, priv); - const broad_tx = await tronWeb.trx.broadcast(signed_tx); - - return broad_tx; -} - -async function transferTrc10(tronWeb, from, to, amount, tokenID, memo, priv) { - const unsigned_tx = await tronWeb.transactionBuilder.sendToken(to, amount, tokenID, from); - const unsignedWithMemoTx = await tronWeb.transactionBuilder.addUpdateData(unsigned_tx, memo, 'utf8'); - const signed_tx = await tronWeb.trx.sign(unsignedWithMemoTx, priv); - const broad_tx = await tronWeb.trx.broadcast(signed_tx); - return broad_tx; -} - -async function transferTrc20(tronWeb, from, to, amount, contractAddress, memo, priv) { - const options = {}; - const functionSelector = 'transfer(address,uint256)'; - const params = [ - { type: 'address', value: to }, - { type: 'uint256', value: amount }, - ]; - - const unsigned_tx = await tronWeb.transactionBuilder.triggerSmartContract( - contractAddress, - functionSelector, - options, - params, - from, - ); - const unsignedWithMemoTx = await tronWeb.transactionBuilder.addUpdateData(unsigned_tx.transaction, memo, 'utf8'); - - const signed_tx = await tronWeb.trx.sign(unsignedWithMemoTx, priv); - const broad_tx = await tronWeb.trx.broadcast(signed_tx); - return broad_tx; -} - -async function main() { - // try 100 times and wait for 3 seconds every time. - const checkEffect = async (sendBurn) => { - logger.debug('test', sendBurn); - }; - let trc10SendBurn = false; - for (let i = 0; i < 100; i++) { - await asyncSleep(10000); - try { - // await checkEffect(trxTxHash, 'trx', 'trx', trxSendBurn); - // await burn(trxSendBurn, 'trx'); - // trxSendBurn = true; - - await checkEffect(trc10SendBurn); - trc10SendBurn = true; - - //await checkEffect(trc20TxHash, 'TVWvkCasxAJUyzPKMQ2Rus1NtmBwrkVyBR', 'trc20'); - } catch (e) { - logger.warn('The tron component integration not pass yet.', { i, e }); - continue; - } - } -} - -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - }); diff --git a/offchain-modules/start-mysql.sh b/offchain-modules/start-mysql.sh deleted file mode 100644 index 38d6bf85..00000000 --- a/offchain-modules/start-mysql.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -set -o errexit -set -o xtrace - -PROJECT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd .. && pwd )" -DB_NAME=forcebridge -DB_PATH=mysql://root:root@127.0.0.1:3306/${DB_NAME} -MYSQL_NAME=force_bridge_mysql - -start_mysql() { - docker run -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 --name ${MYSQL_NAME} -d mysql:5.7 - docker exec ${MYSQL_NAME} bash -c "echo -e '[mysqld]\nskip-grant-tables' > /etc/mysql/conf.d/my.cnf" - docker restart ${MYSQL_NAME} - sleep 8 - - docker exec ${MYSQL_NAME} mysql --user root --password=root -e "create database ${DB_NAME}; use ${DB_NAME}; show tables;" - files=$(ls $SQL_PATH) - for filename in $files - do - if [ "${filename##*.}" = "sql" ]; then - docker cp $SQL_PATH$filename ${MYSQL_NAME}:/tmp/$filename - docker exec ${MYSQL_NAME} mysql --user root --password=root -e "use ${DB_NAME};source /tmp/${filename};" - sleep 1 - fi - done - docker exec ${MYSQL_NAME} mysql --user root --password=root -e "show databases;" - echo "***** start mysql successfully *****" -} - -start_mysql