NAME
Bitcoin::Crypto::Manual - Module overview
DESCRIPTION
This module allows you to perform low-level tasks for Bitcoin such as:
creating extended keys and utilizing bip32 key derivation
creating private key / public key pairs
address generation (in legacy, compatibility and segwit formats)
importing / exporting using popular mediums (WIF, mnemonic, hex)
building, serializing and running transaction scripts
serializing, signing and verifying transactions
This module won't help you with:
handling Bitcoin blocks and the blockchain
using any Bitcoin CLI tools / clients
connecting to Bitcoin network
WHERE TO START?
Documentation and examples in this module assume you're already familiar with the basics of Bitcoin protocol and asymmetric cryptography. If that's not the case, start with reading about those topics.
If you like to learn by example, dive right into the examples directory.
There are many goals which you may want to achieve with this module. Common topics include:
create a key pair for signature or address generation
use Bitcoin::Crypto qw(btc_prv); # create a key pair from wif my $private = btc_prv->from_wif($wif_string); my $public = $private->get_public_key;
Start with Bitcoin::Crypto::Key::Private if you already have some data you want to use as a private key entropy (like Bitcoin's
WIF
format or hex data). If you'd like to generate list of words (a mnemonic) instead, see "generate_mnemonic" in Bitcoin::Crypto::Util and "from_mnemonic" in Bitcoin::Crypto::Key::ExtPrivate.generate many keys at once
use Bitcoin::Crypto qw(btc_extprv); use Bitcoin::Crypto::Util qw(generate_mnemonic); use Bitcoin::Crypto::BIP85; # generate a mnemonic and derive more mnemonics from it deterministically my $mnemonic = generate_mnemonic; my $generator = Bitcoin::Crypto::BIP85->new( key => btc_extprv->from_mnemonic($mnemonic), ); for my $i (0 .. 9) { my $new_mnemonic = $generator->derive_mnemonic(index => $i); }
Bitcoin::Crypto::BIP85 lets you derive mnemonics, private keys or just entropy from a single extended private key.
Bitcoin::Crypto::Key::ExtPrivate allows you to derive multiple keys from a master key, so you don't have to store multiple private keys. Bitcoin::Crypto::Key::ExtPublic can be then used to derive public keys lazily. (Note: storing extended public keys together with private keys in a hot storage will put your extended private key at risk!)
create a transaction object from scratch or from serialized transaction data
use Bitcoin::Crypto qw(btc_transaction); # create and dump a transaction my $tx = btc_transaction->new; $tx->add_input( utxo => [[hex => '9dd8d1ebba95d4ddc2b9fa21b9bc893385e9d5928d0d4835433f34b0ad4b9527'], 0], ); $tx->add_output( locking_script => [address => 'bc1p857ug9whvzapyhkxtjsha0376y2w2yc2dnegx4jlaqcftrfmnt0shkqj6h'], value => 1337, ); print $tx->dump;
utilize Bitcoin Script
use Bitcoin::Crypto qw(btc_script); # create a script by hand and run it btc_script ->new ->push($bytestring) ->add('OP_SIZE') ->add('OP_10') ->add('OP_EQUALVERIFY') ->run;
Bitcoin::Crypto::Script will help you build, de/serialize and run a script. Bitcoin::Crypto::Script::Runner gives you more control over script execution, including running the script step by step, stopping after each opcode.
work with Bitcoin-related encodings
use Bitcoin::Crypto::Bech32 qw(encode_bech32); # encode some data as bech32 my $encoded_str = encode_bech32('customdata', [25, 13, 31, 8, 0, 5]);
There are Bitcoin::Crypto::Base58 and Bitcoin::Crypto::Bech32. PSBT format is supported in Bitcoin::Crypto::PSBT. You can validate an address and get its type using "get_address_type" in Bitcoin::Crypto::Util.
work with other cryptocurrencies
use Bitcoin::Crypto::Network; # put module into single-network mode and choose testnet Bitcoin::Crypto::Network->get('bitcoin_testnet')->set_single;
You can work with any cryptocurrency as long as it is based on the same fundamentals as Bitcoin. You have to register a network in Bitcoin::Crypto::Network first, with the protocol data valid for your cryptocurrency. Also see "Support for other cryptocurrencies"
GENERAL INFORMATION
How to read the documentation?
Most functions in this documentation have a code line showcasing the arguments used by the function. These lines are not meant to be valid perl. They're there for you to understand what arguments the function expects.
Most packages in this module have the types of their thrown exceptions documented near the bottom of the document. The exceptions section may be useful to understand which types of exceptions can be thrown when using functions or methods from the package and what they mean. It is not meant to be a full list of exceptions a function can throw and unblessed errors may still be raised.
Class shortcuts
The most frequently used classes have their shortcuts starting with btc_
registered in Bitcoin::Crypto. Examples are btc_prv
for basic private key or btc_transaction
for transactions. These shortcuts can make the code more compact and avoid manually requiring too many classes, but they are completely optional. If this style does not sound reasonable to you, feel free to ignore it.
See "Exported interface" in Bitcoin::Crypto for details.
How to pass data to functions?
Many frequently used functions (like from_serialized
commonly used in keys, scripts and transactions) require you to pass in a string of bytes. Bytestring is a string in which each character has numeric value less than or equal to 255. It is the default way to pass in data to functions in Bitcoin::Crypto.
It is not rare that you may want to use some other format instead, like hex strings. To avoid duplicating functions for different formats or manually transforming data to a bytestring, the module uses data structures called format descriptions. In any place where a bytestring is used you may instead use an array reference with exactly two elements. The first element must be a name of the format, and the second element is the actual data in that format. For strings of hex data, this may look like this:
use Bitcoin::Crypto qw(btc_prv);
my $private = btc_prv->from_serialized([hex => '152a3f549597a2bef783']);
Currently supported values for the first argument are:
hex
(hexadecimal string, may be prefixed by0x
)base58
(base58-encoded string with the checksum)base64
(base64-encoded string)
It is also common for functions to return bytestrings (like to_serialized
). If you need help changing that output format you may use "to_format" in Bitcoin::Crypto::Util helper function, which does the reverse operation:
use Bitcoin::Crypto::Util qw(to_format);
print to_format [hex => $private->to_serialized];
How to pass commonly used script types to functions?
Similar to format descriptions, you may use a script description anywhere a script is expected. It is an array reference of two elements, where the first one is the short name of the script type, like P2WPKH
. The second one contains data specific to that script type, usually the address:
$transaction->add_output(
locking_script => [P2WPKH => 'bc1qr9htu5sy02q6kv6mx7axz2zdg3k9nrh8pe4l47'],
);
You may also leave address detection up to the module by using the string address
:
# the same thing
$transaction->add_output(
locking_script => [address => 'bc1qr9htu5sy02q6kv6mx7axz2zdg3k9nrh8pe4l47'],
);
Note that the script created like this always belongs to the currently set default network (bitcoin
by default). Passing address from the wrong network will result in an exception.
See "from_standard" in Bitcoin::Crypto::Script for more details.
Support for other cryptocurrencies
Bitcoin::Crypto has limited support for other cryptocurrency networks through Bitcoin::Crypto::Network. The network must be fully compatible with Bitcoin (a Bitcoin clone or a strict subset of Bitcoin features) - no extra cases will exist in the code, only constant values can differ between the networks. Lack of certain constant values can be used to mark feature unsupported in the given network, for example lack of segwit_hrp
network constant will be interpreted as network not supporting Segregated Witness. Note that Bitcoin testnet is also considered a separate network.
Networks can be set globally through default network or on per-object basis for basic and extended keys, and scripts. Other parts of the system does not support per-object setting of networks and rely on the currently set default network. Setting keys for every object separately is considered an outdated feature which is kept for backwards compatibility (and convenience, sometimes). If you want to make sure all your keys are in the same, default network, see single-network mode in "single_network" in Bitcoin::Crypto::Network. This mode will disallow creation of objects with other network than the default. It can come handy if you are de-serializing keys from non-constant strings, for example fetched from the Internet or entered by the user.
DISCLAIMER
Although the module was written with an extra care and appropriate tests are in place asserting compatibility with many Bitcoin standards, due to complexity of the subject some bugs may still be present. In the world of digital money, a single bug may lead to losing funds. I encourage anyone to test the module themselves, review the test cases and use the module with care. Suggestions for improvements and more edge cases to test will be gladly accepted, but there is no warranty on funds manipulated by this module.
TODO
I will gladly accept help working on these:
All listed in "Current known problems with transactions" in Bitcoin::Crypto::Manual::Transactions
All issues with
help wanted
tag on GitHubBetter error checking (edge cases etc.)
Better test coverage