blockchain-tools is a Solidity library for bitcoin-related functionality written in Solidity.
It implements encoding/decoding bitcoin addresses. Implementation is slightly optimized for Solidity (e.g. it uses the fact that uint256 is 256 bits). Currently, it supports:
- Segwit v0 address BIP-0173
- Segwit v1 address (taproot) BIP-0350
- Encoding/decoding returns specific error thus making debugging much easier
- Almost all tests from Python reference implementation are implemented
Solidity code for tests was generated automatically using scripts from python_ref dir. This scripts use test data and functions from Python reference implementation for BIP-0350.
It uses an excellent tool Foundry.
$ forge install --no-commit https://github.com/stroomnetwork/blockchain-toolsAdd the following line to file remappings.txt. If the file does not exist, create it.
blockchain-tools/=lib/blockchain-tools/src
import {Bech32m} from "blockchain-tools/Bech32m.sol";(uint8 witVer, bytes memory data, Bech32m.DecodeError err) = Bech32m.decodeSegwitAddress(bytes("tb"), bytes("tb1p5z8wl5tu7m0d79vzqqsl9gu0x4fkjug857fusx4fl4kfgwh5j25spa7245"));bytes memory btcAddr = Bech32m.encodeSegwitAddress(bytes("tb"), 1, hex"a08eefd17cf6dedf15820021f2a38f3553697107a793c81aa9fd6c943af492a9");It includes one sample contract which calculates bitcoin address given an ethereum address BTCDepositAddressDeriver. pk = pk1 * hash(pk1 || bytes(eth_address)) + pk2 * hash(pk2 || bytes(eth_address)). pk1 and pk2 are public keys corresponding to two Taproot addresses.
It deterministically generate individual bitcoin address for an eth address. It can be used to bridge Bitcoin and Ethereum.
By default anvil uses deterministic address generation from seed. So each launch of anvil will give the same addresses and private keys. For usability they are copy-pasted in env-anvil file.
Commands for deploying and interacting are slightly large, so they were put in Makefile. Most commands have form make <action>-<object>.
$ makeOR
$ make helpPrints help message with a list of available commands and some descriptions.
$ make buildbuilds the library.
$ make cleanCleans output cache. Sometimes when renaming files and/or changing submodules very strange errors appear. Most probably due to forge caching. This command deletes project related cache file. Basically it deletes cache and out directories.
NOTE: it is different from $ forge clean. I don't know why $ forge clean still leaves some files and thus it is not "complete" clean. Thus $ make clean was created.
$ make start-anvilstarts anvil with the default settings.
$ make deploy-on-anvildeploys BTCDepositAddressDeriver on the local anvil blockchain. It writes the deployed contract address to temp/BTCDepositAddressDeriver.31337.address.
$ make set-sample-seedSet seed for previously deployed BTCDepositAddressDeriver. Btc seed addresses are hardcoded so the operation is deterministic.
TODO: explain what contract address it uses.
$ make get-sample-btc-addressGenerate bitcoin address from an eth address. Eth address is hard-coded so this operation is deterministic.
$ make testRun unit-tests.
$ make test-sample-flowRun integration test. Deploy contract, set seed, generate btc address. Check that the address is correct.
Note: this command requires already running anvil.
$ make test-allRun both unit and integration tests.
Note: this command requires already running anvil.
Cast is a command line tool for interacting with smart contracts. It is a part of Foundry.
Private keys and RPC URL for default anvil configuration are stored in env-anvil. anvil uses deterministic key generation and thus keys are the same for different launches.
To import these values.
$ source env-anvilTo get value of btcAddr1 field.
$ cast call $(cat temp/BTCDepositAddressDeriver.31337.address) "btcAddr1()" --rpc-url $ANVIL_RPC_URLIt returns value of btcAddr field in hex.
To get the value of btcAddr as string:
$ cast --to-utf8 $(cast call $(cat temp/BTCDepositAddressDeriver.31337.address) "btcAddr1()" --rpc-url $ANVIL_RPC_URL)TODO: cast set-seed
TODO: cast get eth address
TODO: gas usage