Skip to content

Commit

Permalink
feat: add lockHeight to stakingTx (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrwbabylonlab authored May 17, 2024
1 parent 4510f3a commit b7ada8b
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,21 @@ import { networks } from "bitcoinjs-lib";
// allowed by the Babylon system .
// - `magicBytes: Buffer`: The magic bytes that are appended to the data
// embed script that is used to identify the staking transaction on BTC.
// - `lockHeight: number`: Indicates the BTC height before which
// the transaction is considered invalid. This value can be derived from
// the `activationHeight` of the Babylon versioned global parameters
// where the current BTC height is. Note that if the
// `current BTC height + 1 + confirmationDepth` is going to be >=
// the next versioned `activationHeight`, then you should use the
// `activationHeight` from the next version of the global parameters.
// Below, these values are hardcoded, but they should be retrieved from the
// Babylon system.

const covenantPks: Buffer[] = covenant_pks.map((pk) => Buffer.from(pk, "hex"));
const covenantThreshold: number = 3;
const minUnbondingTime: number = 101;
const magicBytes: Buffer = Buffer.from("62627434", "hex"); // "bbt4" tag
// Optional field. Value coming from current global param activationHeight
const lockHeight: number = 0;

// 2. Define the user selected parameters of the staking contract:
// - `stakerPk: Buffer`: The public key without the coordinate of the
Expand Down Expand Up @@ -166,6 +174,7 @@ const unsignedStakingTx: Psbt = stakingTransaction(
network(),
btcWallet.isTaproot ? btcWallet.publicKeyNoCoord() : undefined,
dataEmbedScript,
lockHeight,
);

const stakingTx: Promise<Transaction> = await btcWallet.signTransaction(unsignedStakingTx: Psbt);
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "btc-staking-ts",
"version": "0.1.3",
"version": "0.1.4",
"description": "Library exposing methods for the creation and consumption of Bitcoin transactions pertaining to Babylon's Bitcoin Staking protocol. Experimental version, should not be used for production purposes or with real funds.",
"module": "dist/index.js",
"main": "dist/index.js",
Expand Down Expand Up @@ -40,4 +40,4 @@
"@bitcoin-js/tiny-secp256k1-asmjs": "^2.2.3",
"bitcoinjs-lib": "^6.1.5"
}
}
}
23 changes: 23 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,23 @@ import { UTXO } from "./types/UTXO";

export { initBTCCurve, StakingScriptData };

// https://bips.xyz/370
const BTC_LOCKTIME_HEIGHT_TIME_CUTOFF = 500000000;

// stakingTransaction constructs an unsigned BTC Staking transaction
// - Outputs:
// - The first one corresponds to the staking script with a certain amount
// - The second one corresponds to the change from spending the amount and the transaction fee
// - In case of data embed script, it will be added as the second output, fee as the third
// - Inputs:
// - timelockScript, unbondingScript, slashingScript: Scripts for different transaction types
// - amount, fee: Amount to stake and transaction fee
// - changeAddress: Address to send the change to
// - inputUTXOs: UTXOs to use as inputs for the transaction
// - network: Bitcoin network
// - publicKeyNoCoord: Public key if the wallet is in taproot mode
// - dataEmbedScript: Optional data embed script
// - lockHeight: Optional block height locktime to set for the transaction. i.e not mined until block height
export function stakingTransaction(
timelockScript: Buffer,
unbondingScript: Buffer,
Expand All @@ -31,6 +43,7 @@ export function stakingTransaction(
network: networks.Network,
publicKeyNoCoord?: Buffer,
dataEmbedScript?: Buffer,
lockHeight?: number,
): Psbt {
// Check that amount and fee are bigger than 0
if (amount <= 0 || fee <= 0) {
Expand Down Expand Up @@ -62,6 +75,7 @@ export function stakingTransaction(
},
// this is needed only if the wallet is in taproot mode
...(publicKeyNoCoord && { tapInternalKey: publicKeyNoCoord }),
sequence: 0xfffffffd, // Enable locktime by setting the sequence value to (RBF-able)
});
inputsSum += input.value;
}
Expand Down Expand Up @@ -107,6 +121,15 @@ export function stakingTransaction(
});
}

// Set the locktime field if provided. If not provided, the locktime will be set to 0 by default
// Only height based locktime is supported
if (lockHeight) {
if (lockHeight >= BTC_LOCKTIME_HEIGHT_TIME_CUTOFF) {
throw new Error("Invalid lock height");
}
psbt.setLocktime(lockHeight);
}

return psbt;
}

Expand Down

0 comments on commit b7ada8b

Please sign in to comment.