Skip to content

Commit

Permalink
Feat/recovery script (#12)
Browse files Browse the repository at this point in the history
* update code for testing recovery script

* chore: add log

* sync header only if not equal current hash

* update lib-js

* remove cache block

* update debug log

* chore: update duckdb to v1.1.3

* chore: optimize get pending deposits

* remove write block header to duckdb

* update initialize of duckdb

* update thread of duckdb

* feat: split chunk query block height to reduce latency on querying pending deposits

* update log

* fix fetch simulate app cw bitcoin

* chore: remove log

* hot_fix: fix skipped scanning mempool txs

* make webhook client is an optional

* chore: update env.example
  • Loading branch information
perfogic authored Jan 16, 2025
1 parent c7a7b1c commit fa88bf4
Show file tree
Hide file tree
Showing 19 changed files with 280 additions and 331 deletions.
34 changes: 34 additions & 0 deletions packages/contracts-sdk/src/AppBitcoin.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,16 @@ export interface AppBitcoinInterface extends AppBitcoinReadOnlyInterface {
_memo?: string,
_funds?: Coin[]
) => Promise<ExecuteResult>;
updateFoundationKeys: (
{
xpubs,
}: {
xpubs: String[];
},
_fee?: number | StdFee | "auto",
_memo?: string,
_funds?: Coin[]
) => Promise<ExecuteResult>;
relayDeposit: (
{
btcHeight,
Expand Down Expand Up @@ -486,6 +496,7 @@ export class AppBitcoinClient
this.updateBitcoinConfig = this.updateBitcoinConfig.bind(this);
this.updateCheckpointConfig = this.updateCheckpointConfig.bind(this);
this.registerValidator = this.registerValidator.bind(this);
this.updateFoundationKeys = this.updateFoundationKeys.bind(this);
this.relayDeposit = this.relayDeposit.bind(this);
this.relayCheckpoint = this.relayCheckpoint.bind(this);
this.withdrawToBitcoin = this.withdrawToBitcoin.bind(this);
Expand Down Expand Up @@ -610,6 +621,29 @@ export class AppBitcoinClient
_funds
);
};
updateFoundationKeys = async (
{
xpubs,
}: {
xpubs: String[];
},
_fee: number | StdFee | "auto" = "auto",
_memo?: string,
_funds?: Coin[]
): Promise<ExecuteResult> => {
return await this.client.execute(
this.sender,
this.contractAddress,
{
update_foundation_keys: {
xpubs,
},
},
_fee,
_memo,
_funds
);
};
relayDeposit = async (
{
btcHeight,
Expand Down
8 changes: 7 additions & 1 deletion packages/contracts-sdk/src/AppBitcoin.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ export type ExecuteMsg =
| {
register_validator: {};
}
| {
update_foundation_keys: {
xpubs: String[];
};
}
| {
relay_deposit: {
btc_height: number;
Expand Down Expand Up @@ -113,6 +118,7 @@ export type ExecuteMsg =
val_addr: Addr;
};
};
export type String = string;
export type Binary = string;
export type Dest =
| {
Expand All @@ -122,7 +128,6 @@ export type Dest =
ibc: IbcDest;
};
export type Signature = number[];
export type String = string;
export interface Ratio {
denominator: number;
nominator: number;
Expand Down Expand Up @@ -356,6 +361,7 @@ export interface Coin {
}
export interface SignatorySet {
create_time: number;
foundation_signatories: Signatory[];
index: number;
possible_vp: number;
present_vp: number;
Expand Down
2 changes: 1 addition & 1 deletion packages/lib-js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"data/"
],
"dependencies": {
"@oraichain/bitcoin-bridge-contracts-sdk": "latest",
"@oraichain/bitcoin-bridge-contracts-sdk": "workspace:^",
"bitcoinjs-lib": "^6.0.1"
},
"publishConfig": {
Expand Down
2 changes: 1 addition & 1 deletion packages/lib-js/src/dest.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Dest as SdkDest } from "@oraichain/bitcoin-bridge-contracts-sdk/build/CwBitcoin.types";
import { Dest as SdkDest } from "@oraichain/bitcoin-bridge-contracts-sdk/build/AppBitcoin.types";

export interface IbcDest {
source_port: string;
Expand Down
41 changes: 40 additions & 1 deletion packages/lib-js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
CheckpointConfig,
Dest,
SignatorySet,
} from "@oraichain/bitcoin-bridge-contracts-sdk/build/CwBitcoin.types";
} from "@oraichain/bitcoin-bridge-contracts-sdk/build/AppBitcoin.types";
import * as btc from "bitcoinjs-lib";
import { convertSdkDestToWasmDest } from "./dest";
import { commitmentBytes } from "./wasm/cw_bitcoin_wasm";
Expand Down Expand Up @@ -151,6 +151,11 @@ export function redeemScript(
let truncatedVp = BigInt(firstSig.voting_power) >> truncation;

let script = [];
if (sigset.foundation_signatories) {
script.push(Buffer.from([0]));
script.push(op("OP_EQUAL"));
script.push(op("OP_IF"));
}
script.push(Buffer.from(firstSig.pubkey.bytes));
script.push(op("OP_CHECKSIG"));
script.push(op("OP_IF"));
Expand Down Expand Up @@ -179,6 +184,40 @@ export function redeemScript(
script.push(dest);
script.push(op("OP_DROP"));

if (sigset.foundation_signatories) {
if (sigset.foundation_signatories?.length > 0) {
let signatories = sigset.foundation_signatories;
let totalVotingPower = signatories[0].voting_power;
script.push(op("OP_ELSE"));
script.push(Buffer.from(signatories[0].pubkey.bytes));
script.push(op("OP_CHECKSIG"));
script.push(op("OP_IF"));
script.push(pushInt(BigInt(signatories[0].voting_power)));
script.push(op("OP_ELSE"));
script.push(pushInt(0n));
script.push(op("OP_ENDIF"));
for (let i = 1; i < signatories.length; i++) {
script.push(op("OP_SWAP"));
script.push(Buffer.from(signatories[i].pubkey.bytes));
script.push(op("OP_CHECKSIG"));
script.push(op("OP_IF"));
script.push(pushInt(BigInt(signatories[i].voting_power)));
script.push(op("OP_ADD"));
script.push(op("OP_ENDIF"));
totalVotingPower += signatories[i].voting_power;
}
let truncatedThreshold = Math.ceil(
(totalVotingPower * numerator) / denominator
);
script.push(pushInt(BigInt(truncatedThreshold)));
script.push(op("OP_GREATERTHANOREQUAL"));
} else {
script.push(op("OP_ELSE"));
script.push(op("OP_RETURN"));
}
script.push(op("OP_ENDIF"));
}

return btc.script.compile(script as any);
}

Expand Down
14 changes: 14 additions & 0 deletions packages/lib-js/src/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { generateDepositAddress } from ".";

const main = async () => {
const result = await generateDepositAddress({
dest: {
address: "orai1yzmjgpr08u7d9n9qqhvux9ckfgq32z77c04lkg",
},
relayers: ["http://127.0.0.1:8000"],
network: "bitcoin",
});
console.log(result);
};

main();
4 changes: 2 additions & 2 deletions packages/orchestrator/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ BTC_RPC_USERNAME=satoshi
BTC_RPC_PASSWORD=nakamoto
BTC_NETWORK=mainnet ## testnet or mainnet
COSMOS_RPC_URL=http://127.0.0.1:26657
LIGHT_CLIENT_BITCOIN_ADDRESS=orai1rdykz2uuepxhkarar8ql5ajj5j37pq8h8d4zarvgx2s8pg0af37qucldna
APP_BITCOIN_ADDRESS=orai12sxqkgsystjgd9faa48ghv3zmkfqc6qu05uy20mvv730vlzkpvls5zqxuz
LIGHT_CLIENT_BITCOIN_ADDRESS=orai1qvk2fwr3g5uaj86cjvncr2u5r4pfm92dj4lkz50sgrax45hmeurqy9tuyu
APP_BITCOIN_ADDRESS=orai1g90x3z2kss99wvmpkenjdelmpw4hf9l3yt420gpgqvpuz8lt79uq24arlv
STORAGE_DIR_NAME=.oraibtc-relayer
DUCKDB_DIR_NAME=watched_scripts.duckdb

Expand Down
2 changes: 1 addition & 1 deletion packages/orchestrator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"cors": "^2.8.5",
"discord.js": "^14.16.3",
"dotenv": "^16.4.5",
"duckdb-async": "^1.1.1",
"duckdb-async": "^1.1.3",
"express": "^4.19.2",
"hdkey": "^2.1.0",
"helmet": "^7.1.0",
Expand Down
7 changes: 4 additions & 3 deletions packages/orchestrator/src/apis/services/checkpoint.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ class CheckpointService {
};

getCheckpoint = async (index: number | undefined) => {
const checkpoint = index
? await this.appBitcoinQueryClient.checkpointByIndex({ index })
: await this.appBitcoinQueryClient.buildingCheckpoint();
const checkpoint =
index !== undefined
? await this.appBitcoinQueryClient.checkpointByIndex({ index })
: await this.appBitcoinQueryClient.buildingCheckpoint();

const checkpointTx = await this.appBitcoinQueryClient.checkpointTx({
index,
Expand Down
59 changes: 11 additions & 48 deletions packages/orchestrator/src/bin/test.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,20 @@
import { AppBitcoinClient } from "@oraichain/bitcoin-bridge-contracts-sdk";
import { encodeXpub } from "@oraichain/bitcoin-bridge-wasm-sdk";
import BIP32Factory from "bip32";
import { OraichainConfig } from "src/configs/networks";
import { initSignerClient } from "src/utils/cosmos";
import * as ecc from "tiny-secp256k1";
import env from "../configs/env";
import { getCurrentNetwork } from "../utils/bitcoin";
import { DuckDbNode } from "../services/db";
import { TableName } from "../utils/db";

const main = async () => {
let mnemonic = env.cosmos.mnemonic;
const xpriv = "";
const bip32 = BIP32Factory(ecc);
const node = bip32.fromBase58(xpriv, getCurrentNetwork("bitcoin"));
let xpub = node.neutered().toBase58();
console.log("Initilizing DuckDB...");
await DuckDbNode.create(env.duckdb.name);
console.log("Initilized DuckDB!");
console.log("Creating tables in DuckDB!");
await DuckDbNode.instances.createTable();
console.log("Tables are created in DuckDB!");

const { prefix, gasPrice } = OraichainConfig;
const { sender, client } = await initSignerClient(
env.cosmos.rpcUrl,
mnemonic,
prefix,
gasPrice
);
const appBitcoinClient = new AppBitcoinClient(
client,
sender,
env.cosmos.appBitcoin
);
let db = DuckDbNode.instances;

const realXpub = await appBitcoinClient.signatoryKey({
addr: sender,
});
console.log("Actually xpub:", { xpub }, "Expected xpub:", { xpub: realXpub });
const data = await db.select(TableName.RelayedSet, {});

const signTxs = await appBitcoinClient.signingTxsAtCheckpointIndex({
xpub,
checkpointIndex: 52,
});
let sigs = [];
for (const signTx of signTxs) {
const [msg, sigsetIndex] = signTx;

const key = node.derive(sigsetIndex);
const sig = key.sign(Buffer.from(msg));
sigs = [...sigs, Array.from(sig)];
}

const tx = await appBitcoinClient.submitCheckpointSignature({
btcHeight: 875383,
checkpointIndex: 52,
sigs,
xpub: encodeXpub({ key: xpub }),
});
console.log(`Signed checkpoint ${52} at ${tx.transactionHash}`);
console.log(data);
};

main();
38 changes: 19 additions & 19 deletions packages/orchestrator/src/configs/logger.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
import { EmbedBuilder, WebhookClient } from "discord.js";
import env from "./env";

const webhookClient = new WebhookClient({
url: env.logger.webhookUrl as string,
});
const webhookClient = env.logger.webhookUrl
? new WebhookClient({
url: env.logger.webhookUrl as string,
})
: undefined;

export const logger = (label: string, loglevel?: string): any => {
return {
info: (text: string) =>
console.info(`${new Date().toLocaleString()} [INFO] [${label}]: ${text}`),
error: (text: string, error: Error) => {
const embed = new EmbedBuilder({
title: text,
description: error?.stack || error?.message || "Something went wrong!",
})
.setColor("#0099ff")
.setImage(
"https://cdn.discordapp.com/attachments/1263547562120577058/1296729095975211050/demo.jpg?ex=67135894&is=67120714&hm=6020d73a3063554bd1eca81e81b3c378e3b84196d577c087d7311d53e6ee009a&"
);
// const embed = new Embed()
// .setTitle(text)
// .setDescription(error?.stack || error?.message || 'Something went wrong!')
// .setColor('#0099ff')
// .setImage('https://cdn.discordapp.com/attachments/1263547562120577058/1296729095975211050/demo.jpg?ex=67135894&is=67120714&hm=6020d73a3063554bd1eca81e81b3c378e3b84196d577c087d7311d53e6ee009a&');
webhookClient.send({
embeds: [embed],
});
if (webhookClient) {
const embed = new EmbedBuilder({
title: text,
description:
error?.stack || error?.message || "Something went wrong!",
})
.setColor("#0099ff")
.setImage(
"https://cdn.discordapp.com/attachments/1263547562120577058/1296729095975211050/demo.jpg?ex=67135894&is=67120714&hm=6020d73a3063554bd1eca81e81b3c378e3b84196d577c087d7311d53e6ee009a&"
);
webhookClient.send({
embeds: [embed],
});
}
console.error(
`${new Date().toLocaleString()} [ERROR] [${label}]: ${text}, ${error}`
);
Expand Down
4 changes: 2 additions & 2 deletions packages/orchestrator/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
export const RELAY_HEADER_BATCH_SIZE = 100;
export const SCAN_MEMPOOL_CHUNK_SIZE = 500;
export const SCAN_MEMPOOL_CHUNK_SIZE = 250;
export const SCAN_MEMPOOL_CHUNK_INTERVAL_DELAY = 250;
export const SCAN_BLOCKS_CHUNK_SIZE = 10;
export const SCAN_BLOCK_TXS_INTERVAL_DELAY = 100;
export const SCAN_BLOCK_TXS_INTERVAL_DELAY = 1100;
export const SUBMIT_RELAY_RECOVERY_TX_INTERVAL_DELAY = 100;
export const SUBMIT_RELAY_CHECKPOINT_INTERVAL_DELAY = 100;
export const RELAY_DEPOSIT_BLOCKS_SIZE = 1100; // 500 blocks
Expand Down
Loading

0 comments on commit fa88bf4

Please sign in to comment.