Skip to content

Commit

Permalink
feat: support btc cross-chain (#32)
Browse files Browse the repository at this point in the history
* feat: implement mint && createBridgeCell

* impl burn && watch burn event

* code clean

* feat: support tron network

* feat: fix tron integration

* feat: support eos chain

* feat: use ForceBridgeCongi instead of nconf

* fix: bugfix on ckb handler

* chore: code format

* chore: bugfix when deploy ckb

* feat: impl molecule serialization

* feat: optimize ckb handler for eth

* fix(tron): optimize tron handler

* feat: optimize ckb handler for tron

* feat: support getSudtBalance

* feat: optimize ckb handler for eos

* chore: clean code

* minor change

* fix: fix unit test

* chore: make github-ci

* minor change

* fix: fix pr comments

* fix: use indexer waitUntilSync intead of asleep

* fix: ckb rpc url fix

* fix: github ci fix

* fix: the problem of amount conversion

* fix: amount visualization optimization

* chore: use tron shasta testnet

* feat: support btc cross-chain

* fix: update burn hash start with 0x of btc module

* fix: remove usless comments

* feat: support btc cross-chain

* chore: remove usless comments

Co-authored-by: jacobdenver007 <jacobdenver@163.com>
Co-authored-by: 方平 <fpchen@outlook.com>
  • Loading branch information
3 people committed Apr 12, 2021
1 parent 6992b04 commit ca42aff
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 176 deletions.
2 changes: 1 addition & 1 deletion offchain-modules/package.json
Expand Up @@ -22,7 +22,7 @@
"tron-test": "ts-node ./src/scripts/integration-test/tron.ts",
"prepare-xchain-test": "sleep 2",
"btc-test": "ts-node ./src/scripts/integration-test/btc.ts",
"xchain-test": "run-s prepare-xchain-test eth-test eos-test tron-test",
"xchain-test": "run-s prepare-xchain-test eth-test eos-test tron-test btc-test",
"integration-test": "run-p -r start xchain-test",
"ci": "run-s clean build deploy integration-test",
"test:unit": "nyc --silent ava",
Expand Down
12 changes: 6 additions & 6 deletions offchain-modules/src/apps/relayer/index.ts
Expand Up @@ -46,12 +46,12 @@ async function main() {
const tronHandler = new TronHandler(tronDb);
tronHandler.start();
}
// if (config.btc !== undefined) {
// const btcDb = new BtcDb(conn);
// const btcChain = new BTCChain();
// const btcHandler = new BtcHandler(btcDb, btcChain);
// btcHandler.start();
// }
if (config.btc !== undefined) {
const btcDb = new BtcDb(conn);
const btcChain = new BTCChain();
const btcHandler = new BtcHandler(btcDb, btcChain);
btcHandler.start();
}
}

main();
27 changes: 20 additions & 7 deletions offchain-modules/src/packages/ckb/model/asset.ts
Expand Up @@ -41,8 +41,6 @@ export class EthAsset extends Asset {
}

export class TronAsset extends Asset {
// '0x00000000000000000000' represents ETH
// other address represents ERC20 address
constructor(public address: string, public ownLockHash: string) {
super();
this.chainType = ChainType.TRON;
Expand All @@ -63,13 +61,8 @@ export class TronAsset extends Asset {
}

export class EosAsset extends Asset {
// '0x00000000000000000000' represents ETH
// other address represents ERC20 address
constructor(public address: string, public ownLockHash: string) {
super();
// if (!address.startsWith('') || address.length !== 42) {
// throw new Error('invalid Tron asset address');
// }
this.chainType = ChainType.EOS;
}

Expand All @@ -86,3 +79,23 @@ export class EosAsset extends Asset {
return toHexString(stringToUint8Array(this.address));
}
}

export class BtcAsset extends Asset {
constructor(public address: string, public ownLockHash: string) {
super();
this.chainType = ChainType.BTC;
}

toBridgeLockscriptArgs(): string {
const params = {
owner_lock_hash: fromHexString(this.ownLockHash).buffer,
chain: this.chainType,
asset: fromHexString(toHexString(stringToUint8Array(this.address))).buffer,
};
return `0x${toHexString(new Uint8Array(SerializeForceBridgeLockscriptArgs(params)))}`;
}

getAddress(): string {
return toHexString(stringToUint8Array(this.address));
}
}
8 changes: 8 additions & 0 deletions offchain-modules/src/packages/db/ckb.ts
Expand Up @@ -5,11 +5,13 @@ import {
CkbBurn,
EthUnlock,
EosUnlock,
BtcUnlock,
IEosUnlock,
IEthUnlock,
ITronUnlock,
TronUnlock,
ICkbBurn,
IBtcUnLock,
} from '@force-bridge/db/model';

export class CkbDb {
Expand Down Expand Up @@ -65,4 +67,10 @@ export class CkbDb {
const dbRecords = records.map((r) => tronUnlockRepo.create(r));
await tronUnlockRepo.save(dbRecords);
}

async createBtcUnlock(records: IBtcUnLock[]): Promise<void> {
const btcUnlockRepo = this.connection.getRepository(BtcUnlock);
const dbRecords = records.map((r) => btcUnlockRepo.create(r));
await btcUnlockRepo.save(dbRecords);
}
}
3 changes: 3 additions & 0 deletions offchain-modules/src/packages/handlers/btc.ts
Expand Up @@ -45,6 +45,9 @@ export class BtcHandler {
logger.debug(`save CkbMint and BTCLock successful for BTC tx ${btcLockEventData.txHash}.`);
},
async (ckbTxHash: string) => {
if (!ckbTxHash.startsWith('0x')) {
ckbTxHash = '0x' + ckbTxHash;
}
const records: BtcUnlock[] = await this.db.getNotSuccessUnlockRecord(ckbTxHash);
if (records.length === 0) {
return;
Expand Down
32 changes: 31 additions & 1 deletion offchain-modules/src/packages/handlers/ckb.ts
Expand Up @@ -2,7 +2,7 @@ import { CkbDb } from '../db';
import { CkbMint, ICkbBurn } from '../db/model';
import { logger } from '../utils/logger';
import { asyncSleep, fromHexString, toHexString, uint8ArrayToString, bigintToSudtAmount } from '../utils';
import { Asset, ChainType, EosAsset, EthAsset, TronAsset } from '../ckb/model/asset';
import { Asset, BtcAsset, ChainType, EosAsset, EthAsset, TronAsset } from '../ckb/model/asset';
import { Address, Amount, AddressType, Script, HashType } from '@lay2/pw-core';
import { Account } from '@force-bridge/ckb/model/accounts';

Expand All @@ -29,6 +29,17 @@ export class CkbHandler {
logger.debug('save burn event:', burns);
for (const burn of burns) {
switch (burn.chain) {
case ChainType.BTC:
await this.db.createBtcUnlock([
{
ckbTxHash: burn.ckbTxHash,
asset: burn.asset,
amount: burn.amount,
chain: burn.chain,
recipientAddress: burn.recipientAddress,
},
]);
break;
case ChainType.ETH:
await this.db.createEthUnlock([
{
Expand Down Expand Up @@ -100,6 +111,16 @@ export class CkbHandler {
const chain = v.getChain();
let burn;
switch (chain) {
case ChainType.BTC:
burn = {
ckbTxHash: k,
asset: uint8ArrayToString(new Uint8Array(v.getAsset().raw())),
chain,
amount: Amount.fromUInt128LE(`0x${toHexString(new Uint8Array(v.getAmount().raw()))}`).toString(),
recipientAddress: uint8ArrayToString(new Uint8Array(v.getRecipientAddress().raw())),
blockNumber: latestHeight,
};
break;
case ChainType.ETH:
burn = {
ckbTxHash: k,
Expand Down Expand Up @@ -152,6 +173,9 @@ export class CkbHandler {
let asset;
const assetAddress = toHexString(new Uint8Array(cellData.getAsset().raw()));
switch (cellData.getChain()) {
case ChainType.BTC:
asset = new BtcAsset(uint8ArrayToString(fromHexString(assetAddress)), ownLockHash);
break;
case ChainType.ETH:
asset = new EthAsset(`0x${assetAddress}`, ownLockHash);
break;
Expand Down Expand Up @@ -245,6 +269,12 @@ export class CkbHandler {

filterMintRecords(r: CkbMint, ownLockHash: string): any {
switch (r.chain) {
case ChainType.BTC:
return {
asset: new BtcAsset(r.asset, ownLockHash),
recipient: new Address(r.recipientLockscript, AddressType.ckb),
amount: new Amount(r.amount),
};
case ChainType.ETH:
return {
asset: new EthAsset(r.asset, ownLockHash),
Expand Down
16 changes: 6 additions & 10 deletions offchain-modules/src/packages/xchain/btc/scripts.ts
Expand Up @@ -97,11 +97,9 @@ export class BTCChain {
const utxos = getVins(liveUtxos, BigInt(amount));
if (utxos.length === 0) {
throw new Error(
`the unspend utxo is not enough for lock. need : ${amount}. actual uxtos : ${JSON.stringify(
liveUtxos,
null,
2,
)}`,
`the unspent utxo is not enough for lock. need : ${amount}. actual :${Unit.fromBTC(
liveUtxos.total_amount,
).toSatoshis()}`,
);
}
const lockTx = new bitcore.Transaction()
Expand Down Expand Up @@ -145,11 +143,9 @@ export class BTCChain {
const utxos = getVins(liveUtxos, VinNeedAmount);
if (utxos.length === 0) {
throw new Error(
`the unspend utxo is no for unlock. need : ${VinNeedAmount}. actual uxtos : ${JSON.stringify(
liveUtxos,
null,
2,
)}`,
`the unspent utxo is not enough for unlock. need : ${VinNeedAmount}. actual amount : ${Unit.fromBTC(
liveUtxos.total_amount,
).toSatoshis()}`,
);
}

Expand Down

0 comments on commit ca42aff

Please sign in to comment.