You will need to install libreadline
, for example sudo apt-get install libreadline-dev
on Ubuntu.
cd ./config
- run
./build_bc.sh
A symlink to BC will be created in ./config/bin
- While still in
./config
, run:
for rtsh in $(echo bin/*.example); do \
cp $PWD/${rtsh} $PWD/${rtsh%.example}; \
chmod +x $PWD/${rtsh%.example}; \
done
cd ..
source activate.sh
See ./bc/
for some ec math and ecdsa tools.
Fun things to try:
rootmod(11, 3, curve_p)
Returns the cube roots of 11 mod the curve's p
balanced_length_mod((curve_n/2) + (curve_n/4), curve_p)
balanced_length_mod(curve_p-((curve_n/2) + (curve_n/4)), curve_n)
Returns balanced length multipliers for these two numbers
ecmul(12EF)
Multiplies 12EF
by the curve's generator and returns the point
ecadd(curve_g, 038282263212C609D9EA2A6E3E172DE238D8C39CABD5AC1CA10646E23FD5F51508)
ecmul(101)
Examples of 1 * G + 100 * G
and (1 + 100) * G
satoshi_pubkey = 0311DB93E1DCDB8A016B49840F8C53BC1EB68A382E97B1482ECAD7B148A6909A5C
block170_sighash = 7A05C6145F10101E9D6325494245ADF1297D80F8F38D4D576D57CDBA220BCB19
satoshi_sig = 304402204E45E16932B8AF514961A1D3A1A25FDF3F4F7732E9D624C6C61548AB5FB8CD410220181522EC8ECA07DE4860A4ACDD12909D831CC56CBBAC4622082221A8768D1D09
ecdsa_verify_der( block170_sighash, satoshi_pubkey, satoshi_sig )
- note that
bc
expects numbers in upper case base 16
See ./bitcoin/
for the main effort behind this project.
Lots of the supporting infrastructure is whatever you'll find in the
different directories, which might also be interesting.
The assumption is that regtest is used, and some global values are set to hold versions and such.
Functions of specific scope tend to have a common prefix, and more general functions have a non scoped name. The interface tries to keep to a sane interpretation of numbers (decimal or hexadecimal).
Some examples...
randhex 32
Returns a random 32 byte value
key_priv2wif "$(randhex 32)"
key_priv2wif "$(randhex 32)01"
Returns a random wif encoded private key
Appending 01
will return the compressed wif key
key_priv2pub 101
key_wif2pub cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN89W6SfaiTA
key_wif2pub 91avARGdfge8E4tZfYLoxeJ5sGBdNJQH4kvjJoQFacbhSh2hjwa
Returns the public point
spk_pay2mofn 2 "0237ACF3D1FBC3D8EB3F23367B12EEAA8AFB081EB21B579A95882F0C36B8C20E7F 03D2920160CCDB8D885B31AFAD20DAA806A6ADEE603A700D0005D223AE435124D4 033CBB01DAECB89937BF82DE986446E8BC0BBF11A89F41E0BABD3068DAFCBC8F5E"
spk_pay2wpkh "$(pub2addr 0290A80DB6EB294B9EAB0B4E8DDFA3EFE7263458CE2D07566DF4E6C58868FEEF23)"
Return the scripts
script_serialize "DUP HASH160 @FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF EQUALVERIFY CHECKSIG"
Serializes a script - @
means minimal push
secret="22A40F35E3ACF36C644C287A619749527B27009B3178E5C4DE6C78CA4E20E97A"
h_secret="$(hash160 ${secret})"
echo ${h_secret}
# 337CD7EEF868D5E8E1CC76CA0C2CC156276F9F85
alice_pub="02174D35691F461D141A10BD0B6BF13D26769EC062FCB5E8D4AAD923207E07F0F2"
carol_priv="F00DE6A284DE9CAD522615EC30D9C36879825022568695E8CB826257F6AEE993"
carol_pub="$(key_priv2pub ${carol_priv})"
spk_pay2shash "IF HASH160 @${h_secret} EQUALVERIFY @${carol_pub} CHECKSIG ELSE 100 CLTV DROP @${alice_pub} CHECKSIG ENDIF"
# HASH160 0x14 0x133DA6A707DFA29298AFF738064D370D6B1D936E EQUAL
rdm_script="$(script_serialize "IF HASH160 @${h_secret} EQUALVERIFY @${carol_pub} CHECKSIG ELSE 100 CLTV DROP @${alice_pub} CHECKSIG ENDIF")"
p2sh_script="$(script_serialize "HASH160 0x14 0x133DA6A707DFA29298AFF738064D370D6B1D936E EQUAL")"
pay_to="$(tx_mkout_p2wpkh 10.123 mfpm1nTTppvtzzgCgozarhGu7R7w33pxoV)"
txin0="$(tx_mkin_serialize 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F 12 "$((2**32-3))" "0x${rdm_script}")"
# '0x...' means the bytes are read literally (e.g. for a serialized script)
echo ${txin0}
# 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F0C0000006463A914337CD7EEF868D5E8E1CC76CA0C2CC156276F9F8588210393B6CA84177971DB77AC121360CAE355C3E7B3C7BF5B54A469C3B5F0EDA99434AC670164B1752102174D35691F461D141A10BD0B6BF13D26769EC062FCB5E8D4AAD923207E07F0F2AC68FDFFFFFF
unsigned="$(tx_build 2 "" "${txin0}" "${pay_to}" 0 | cleanhex)"
echo ${unsigned}
# 02000000011F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F0C0000006463A914337CD7EEF868D5E8E1CC76CA0C2CC156276F9F8588210393B6CA84177971DB77AC121360CAE355C3E7B3C7BF5B54A469C3B5F0EDA99434AC670164B1752102174D35691F461D141A10BD0B6BF13D26769EC062FCB5E8D4AAD923207E07F0F2AC68FDFFFFFF01E078563C00000000160014035E122123B4350416715C54F0CE5AD6E7D2B95C00000000
to_sign="${unsigned}01000000"
mid_hash="$(sha256 "${to_sign}")"
sign "${carol_priv}" "${mid_hash}"
# 3045022100FB13D6158B46F1BAD299826A14616598EB6B18F695541E26ACCBE5626FE479F50220078379EEC7FD763437F55603F6BF1913D784DDC728127C0638AE51863F4EAACC
sig_carol="3045022100FB13D6158B46F1BAD299826A14616598EB6B18F695541E26ACCBE5626FE479F50220078379EEC7FD763437F55603F6BF1913D784DDC728127C0638AE51863F4EAACC"
txin="$(tx_mkin_serialize 1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F 12 "$((2**32-3))" "@${sig_carol}01 @${secret} 1 @${rdm_script}")"
signed="$(tx_build 2 "" "${txin}" "${pay_to}" 0 | cleanhex)"
echo ${signed}
# 02000000011F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F0C000000D1483045022100FB13D6158B46F1BAD299826A14616598EB6B18F695541E26ACCBE5626FE479F50220078379EEC7FD763437F55603F6BF1913D784DDC728127C0638AE51863F4EAACC012022A40F35E3ACF36C644C287A619749527B27009B3178E5C4DE6C78CA4E20E97A514C6463A914337CD7EEF868D5E8E1CC76CA0C2CC156276F9F8588210393B6CA84177971DB77AC121360CAE355C3E7B3C7BF5B54A469C3B5F0EDA99434AC670164B1752102174D35691F461D141A10BD0B6BF13D26769EC062FCB5E8D4AAD923207E07F0F2AC68FDFFFFFF01E078563C00000000160014035E122123B4350416715C54F0CE5AD6E7D2B95C00000000
regtest-cli signrawtransaction ${signed} '[{"txid":"1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F1F","vout":12,"scriptPubKey":"A914133DA6A707DFA29298AFF738064D370D6B1D936E87","redeemScript":"63A914337CD7EEF868D5E8E1CC76CA0C2CC156276F9F8588210393B6CA84177971DB77AC121360CAE355C3E7B3C7BF5B54A469C3B5F0EDA99434AC670164B1752102174D35691F461D141A10BD0B6BF13D26769EC062FCB5E8D4AAD923207E07F0F2AC68"}]'
# true