2025-01-14 @0xdavid
Bitcoin Vault is a comprehensive solution for managing Bitcoin vault transactions, providing functionality for staking, unstaking, and custodian 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
Details in vault/README.md 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 custodian key holders
- P2TR with user and protocol signatures
- P2TR with user and multi-signature of custodian key holders
- P2TR with protocol and multi-signature of custodian key holders
-
Create a staking output just only custodian key holders spend path:
- P2TR with multi-signature of custodian key holders
-
-
Unstaking transaction management for:
- P2TR with multi-signatures of custodian key holders
- P2TR with user and protocol signatures
- P2TR with user and multi-signature of custodian key holders
- P2TR with protocol and multi-signature of custodian 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 custodian script with quorum-based approval system
- Supports segwit and p2tr addresses
-
Future development:
- Apply musig2 for custodians
- 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 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: BigInt(100000000),
stakerPubkey: Buffer.from("02...", "hex"),
stakerAddress: Buffer.from("bc1...", "hex"),
protocolPubkey: Buffer.from("02...", "hex"),
custodialPubkeys: [Buffer.from("02...", "hex"), ...].concat(),
custodianQuorum: 1,
haveOnlycustodians: false,
destinationChain: new DestinationChain(
ChainType.EVM,
11155111
),
destinationContractAddress: hexToBytes("0x..."),
destinationRecipientAddress: hexToBytes("0x..."),
availableUTXOs: addressUtxos,
feeRate,
rbf: true,
});
// Create unstaking transaction
const params: TBuildUnsignedUnstakingUserProtocolPsbt = {
input,
output,
stakerPubkey: Buffer.from("02...", "hex"),
protocolPubkey: Buffer.from("02...", "hex"),
custodianPubkeys: [Buffer.from("02...", "hex"), ...].concat(),
custodianQuorum: 1,
haveOnlycustodians: false,
feeRate: BigInt(feeRate),
rbf: true,
};
// Build the unsigned psbt
const psbtHex =
TestSuite.vaultUtils.buildUnsignedUnstakingUserProtocolPsbt(params);
- More details can be found in
binding/test
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!