2024-11-27 @0xdavid
Bitcoin Vault is a comprehensive solution for managing Bitcoin vault transactions, providing functionality for staking, unstaking, and covenant management on bitcoin network; it provides a rust library, wasm bindings, go ffi bindings, and a typescript sdk.
- Runs natively on Rust
- Other languages require bindings:
- Go: via FFI bindings
- Browser/Node.js: via WebAssembly
- TypeScript: via WebAssembly
The foundational Rust library implementing core Bitcoin vault functionality.
-
Staking transaction creation:
-
Create a staking output with supporting multiple taproot spend paths:
- P2TR with multi-signatures of covenant key holders
- P2TR with user and protocol signatures
- P2TR with user and multi-signature of covenant key holders
- P2TR with protocol and multi-signature of covenant key holders
-
Create a staking output just only covenant key holders spend path:
- P2TR with multi-signature of covenant key holders
-
-
Unstaking transaction management for:
- P2TR with multi-signatures of covenant key holders
- P2TR with user and protocol signatures
- P2TR with user and multi-signature of covenant key holders
- P2TR with protocol and multi-signature of covenant key holders
-
Signing:
- Signing with ECDSA
- Signing with Schnorr
-
PSBT:
- PSBT parsing
- PSBT signing
- PSBT dynamic finalization
-
Details:
- Supports RBF (Replace-By-Fee) for staking and unstaking transactions
- Supports musig and OP_CHECKSIGADD for covenant script with quorum-based approval system
- Supports segwit and p2tr addresses
-
Future development:
- Apply musig2 for covenants
- Apply OP_CAT
vault/
βββ src/
β βββ core/ # Core vault functionality
β βββ parser/ # Transaction parsing
β βββ types/ # Type definitions
β βββ lib.rs # Library entry point
βββ tests/ # Integration tests
- At the root of the project, run
./bitcoin.sh run
to start a bitcoin node - It will auto import the wif and generate the addresses for bond holder in
.bitcoin
directory - Please fill into
vault/.env.test
file, checkvault/.env.example
for more details - Navigate to
test
directory and run each test case only with commented script at the beginning of the file
Eg: cargo test --package bitcoin-vault --test mod -- test_e2e::test_staking --exact --show-output
Browser and Node.js compatible WebAssembly bindings for the vault library.
- Cross-platform compatibility
- Browser support
- Node.js support
- TypeScript definitions
- Binary Data Handling
- Efficient serialization
- Memory management
- Buffer conversions
wasm/
βββ src/ # Rust WASM source
βββ scripts/ # Build scripts
βββ dist/ # Output directory
βββ bitcoin-vault-node_bg.wasm # Node.js specific output
βββ bitcoin-vault-web_bg.wasm # Browser specific output
... other files
- Rust toolchain with wasm32 target:
rustup toolchain install stable --target wasm32-unknown-unknown
rustup target add wasm32-unknown-unknown
- Wasm pack:
cargo install wasm-pack
- Bun:
curl -fsSL https://bun.sh/install | bash
cd wasm && bun run build
- If you encounter the error like
error: linking with
ccfailed: exit status 1
, you can try to install clang:
brew install llvm
echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.zshrc
High-level JavaScript/TypeScript SDK for application integration.
- Transaction Management
- Staking transaction builder
- Unstaking workflow
- PSBT handling
- Fee estimation
- Network Support
- Mainnet support
- Testnet support
- Regtest capabilities
- Utility Functions
- Address validation
- Key management
// Initialize vault utils
const vault = VaultUtils.getInstance({
network: "testnet4",
tag: "SCALAR",
serviceTag: "pools",
version: 1,
});
// Create staking transaction
const { psbt: unsignedVaultPsbt, fee: estimatedFee } =
TestSuite.vaultUtils.buildStakingOutput({
stakingAmount: StaticEnv.STAKING_AMOUNT,
stakerPubkey: TestSuite.stakerPubKey,
stakerAddress: TestSuite.stakerAddress,
protocolPubkey: TestSuite.protocolPubkey,
custodialPubkeys: TestSuite.custodialPubkeys,
covenantQuorum: StaticEnv.CUSTODIAL_QUORUM,
haveOnlyCovenants: StaticEnv.HAVE_ONLY_CUSTODIAL,
destinationChain: new DestinationChain(
ChainType.EVM,
StaticEnv.DEST_CHAIN_ID
),
destinationContractAddress: hexToBytes(
StaticEnv.DEST_SMART_CONTRACT_ADDRESS
),
destinationRecipientAddress: hexToBytes(StaticEnv.DEST_USER_ADDRESS),
availableUTXOs: addressUtxos,
feeRate,
rbf: true,
});
// Create unstaking transaction
const params: TBuildUnsignedUnstakingUserProtocolPsbt = {
input,
output,
stakerPubkey: testSuite.stakerPubKey,
protocolPubkey: testSuite.protocolPubkey,
covenantPubkeys: testSuite.custodialPubkeys,
covenantQuorum: StaticEnv.CUSTODIAL_QUORUM,
haveOnlyCovenants: StaticEnv.HAVE_ONLY_CUSTODIAL,
feeRate: BigInt(feeRate),
rbf: true,
};
// Sign the psbt
const signedPsbt = await TestSuite.vaultUtils.signPsbt(
unsignedVaultPsbt,
TestSuite.stakerPrivKey
);
- More details can be found in
binding/test
Golang utilities for blockchain integration. This module is used as shared dependencies for other modules, including calculating payload hash for staking and unstaking transactions, formatting destination chain specific data.
go get github.com/scalarorg/bitcoin-vault/go-utils
Foreign Function Interface for language interoperability.
- Go
This module is used for vault library to interact with bitcoin network.
- PSBT signing
- Staking transaction parser
- Build the vault rust library
- Run
cargo build --release
inffi/
directory - Copy the output library to
ffi/go-vault/lib
directory - Run
cd ffi/go-vault && make test
go get github.com/scalarorg/bitcoin-vault/ffi
Add CGO_LDFLAGS="path/to/libbitcoin_vault_ffi.dylib" to your build command
MIT License - See LICENSE file for details This documentation provides a more structured overview of the Bitcoin Vault project without excessive code examples. Let me know if you'd like me to expand on any particular section!