Compare commits

...

305 Commits

Author SHA1 Message Date
Luke Dashjr
365df024bc Merge branch 'cbvalue_zero' 2018-02-19 23:37:29 +00:00
Luke Dashjr
c7388aacf8 Add blktemplate_t.has_cbvalue boolean to differentiate between cbvalue 0 being unknown or zero 2018-02-17 17:59:07 +00:00
Luke Dashjr
c1392f15be Merge branch '0.5.x' into cbvalue_zero 2018-02-17 17:59:01 +00:00
Luke Dashjr
05a975a424 Tree-Merge commit '366b8bc' 2018-02-17 17:57:07 +00:00
Luke Dashjr
cf68e084fe Merge branch '0.4.x' into 0.5.x 2018-02-17 17:52:18 +00:00
Luke Dashjr
b2dda538c8 blkmk_init_generation*: Correct output newcb value even in error conditions 2018-02-17 17:51:27 +00:00
Luke Dashjr
366b8bc358 Bugfix: blkmk_init_generation*: Check cbvalue is known before making a new generation transaction using it
Backported from 07ce01f57a
2018-02-17 17:51:24 +00:00
Luke Dashjr
2049056cfd
Merge pull request #10 from j0sh/patch-1
Update pkg-config file.
2018-01-15 08:47:24 +00:00
Josh Allmann
721ce42f57
Update pkg-config file.
Fixes issues with pkg-config oriented builds:
* The use of symbols in -l libs should come before any definitions.
* Add required jansson dependency.
2018-01-15 00:14:16 -08:00
Luke Dashjr
c7a1c1278b Bump versions for 0.6.0 2017-12-23 04:31:52 +00:00
Luke Dashjr
c2785585dc Merge branch 'tests' 2017-12-23 04:19:41 +00:00
Luke Dashjr
f94c40ff5c Merge branch 'segwit' 2017-12-23 04:19:03 +00:00
Luke Dashjr
47a494e113 Merge branch 'master' into segwit 2016-12-01 23:31:11 +00:00
Luke Dashjr
5e409f22fb Merge branch '0.5.x' 2016-12-01 23:30:20 +00:00
Luke Dashjr
835ed46634 Merge branch '0.4.x' into 0.5.x 2016-12-01 23:30:13 +00:00
Luke Dashjr
61deba379e Avoid memcpy with potentially NULL pointer if scriptsz is zero 2016-12-01 23:30:06 +00:00
Luke Dashjr
7f103073ad Merge commit '2a37933' 2016-12-01 23:19:49 +00:00
Luke Dashjr
2a37933698 Travis: Remove MemorySanitizer job for now, since it's broken with latest Linux kernel 2016-12-01 23:19:42 +00:00
Luke Dashjr
15f79c6f71 Travis: Bugfix: Explicitly make test program in case we run it directly 2016-12-01 23:19:36 +00:00
Luke Dashjr
b8055bd495 Travis: Set VERBOSE for make check 2016-12-01 23:19:32 +00:00
Luke Dashjr
7605755747 Bugfix: Wrap test program to ensure the exit code is always 0/pass or 1/fail 2016-12-01 23:19:23 +00:00
Luke Dashjr
8b28f02857 Merge branch 'master' into segwit 2016-11-22 11:02:04 +00:00
Luke Dashjr
f093ad8ee7 Merge commit 'fdb2a28' 2016-11-22 11:01:53 +00:00
Luke Dashjr
fdb2a280b0 Bugfix: Use check_PROGRAMS rather than noinst_PROGRAMS for test, so we don't try to build it before make check 2016-11-22 11:01:07 +00:00
Luke Dashjr
bea591911d Merge branch 'master' into segwit 2016-11-22 10:52:02 +00:00
Luke Dashjr
498221e0b1 Bugfix: blkmk_append_coinbase_safe: Check for an incomplete generation transaction 2016-08-15 21:58:14 +00:00
Luke Dashjr
76db08733f test: Check blkmk_append_coinbase_safe with incomplete generation transactions 2016-08-15 21:57:53 +00:00
Luke Dashjr
9d6b0d0649 Merge branch 'tests' 2016-08-13 09:36:57 +00:00
Luke Dashjr
0dcc8d8697 test: Use libgcrypt for SHA256 2016-08-13 08:35:37 +00:00
Luke Dashjr
f3659638d7 test: Check invalid and uppercase hex data 2016-08-13 08:35:37 +00:00
Luke Dashjr
18ece76f77 Travis: Build for Windows and test in WINE 2016-08-13 08:35:37 +00:00
Luke Dashjr
30ba82f339 test: Increase coverage of capabilities functions 2016-08-13 08:35:37 +00:00
Luke Dashjr
cdb5841c88 Travis: Run tests with -fsanitize={address,memory,undefined} -Wall -Werror 2016-08-13 08:35:37 +00:00
Luke Dashjr
31c1d2c168 test: Increase coverage of blkmk_init_generation 2016-08-13 08:35:37 +00:00
Luke Dashjr
970017ab38 test: Increase coverage of blkmk_count_sigops 2016-08-13 08:35:37 +00:00
Luke Dashjr
793d180847 test: Increase coverage of blkmk_address_to_script 2016-08-13 08:35:37 +00:00
Luke Dashjr
fd04e03c5d test: Check varint encoding within reason 2016-08-13 08:35:37 +00:00
Luke Dashjr
9bb03c6cf3 test: Check against sizelimit and sigoplimit for init_generation and append_coinbase_safe 2016-08-13 08:35:37 +00:00
Luke Dashjr
c1a159d417 test: Check blkmk_append_coinbase_safe 2016-08-13 08:35:37 +00:00
Luke Dashjr
4572fcb97b test: Check acceptance of float-looking numbers, and rejection of JSON missing fields 2016-08-13 08:35:37 +00:00
Luke Dashjr
07ce01f57a test: Check blkmk_init_generation 2016-08-13 08:35:37 +00:00
Luke Dashjr
04753c7257 test: Check blkmk_get_mdata 2016-08-13 08:35:37 +00:00
Luke Dashjr
bdb9519f1b test: Check blkmk_get_data 2016-08-13 08:35:37 +00:00
Luke Dashjr
cf8d325b30 test: Check blkmk_{time,work}_left 2016-08-13 08:35:37 +00:00
Luke Dashjr
0d94076671 test: Check blkmk_address_to_script 2016-08-13 08:35:37 +00:00
Luke Dashjr
136f2b5457 test: Check blkmk_supports_rule 2016-08-13 08:35:37 +00:00
Luke Dashjr
5c471cb3fe test: Check out mdata submissions 2016-08-13 08:35:37 +00:00
Luke Dashjr
c0f590e889 test: Check out submissions 2016-08-13 08:35:37 +00:00
Luke Dashjr
70a022e944 test: Check out block proposals 2016-08-13 08:35:37 +00:00
Luke Dashjr
bfd7d9469a Travis: Initial CI spec YML 2016-08-13 08:27:39 +00:00
Luke Dashjr
5a6bc0caec Initial unit tests covering template and parsing 2016-08-13 08:27:39 +00:00
Luke Dashjr
6c56da6a04 Bugfix: blkmk_append_coinbase_safe2: Check for unexpected larger values before subtracting (in sigop checks) 2016-08-13 08:26:46 +00:00
Luke Dashjr
f333f3c662 Merge branch '0.5.x' 2016-08-13 08:26:34 +00:00
Luke Dashjr
ea800f8be1 Merge branch '0.4.x' into 0.5.x 2016-08-13 08:26:02 +00:00
Luke Dashjr
9cfdca809c Bugfix: blkmk_append_coinbase_safe2: Check for unexpected larger values before subtracting 2016-08-13 08:24:59 +00:00
Luke Dashjr
5889aeab25 Merge commit '130cfbd' 2016-08-13 08:22:57 +00:00
Luke Dashjr
130cfbdb3e Bugfix: example: Deal with build and portability issues 2016-08-13 08:22:47 +00:00
Luke Dashjr
711b938fb8 gitignore: Various development-related files 2016-08-12 04:55:56 +00:00
Luke Dashjr
65b9f2dcd0 Document uselessness and future removal of blktemplate_t.{min,max}nonce 2016-08-12 03:38:02 +00:00
Luke Dashjr
963262af08 _blkmk_calculate_witness_mrklroot: Allocate heap space for hashes, rather than use the (potentially too small) stack 2016-08-12 01:20:46 +00:00
Luke Dashjr
147e86b466 Merge branch 'master' into segwit 2016-08-12 01:06:33 +00:00
Luke Dashjr
a9b3541a60 Merge branch '0.5.x' 2016-08-12 01:04:23 +00:00
Luke Dashjr
3d482768d6 Merge branch '0.4.x' into 0.5.x 2016-08-12 01:03:36 +00:00
Luke Dashjr
37cd25dfc1 Merge commit '5a88bc5' into 0.4.x 2016-08-12 01:03:06 +00:00
Luke Dashjr
5a88bc541a Allocate heap space for hashes, rather than use the (potentially too small) stack 2016-08-12 01:02:08 +00:00
Luke Dashjr
896dc34d47 Merge branch 'bugfix_sizelimit' into 0.5.x 2016-08-11 23:37:14 +00:00
Luke Dashjr
981b1dc4fe Bugfix: Include block header and transaction count in sizelimit checks 2016-08-11 23:37:00 +00:00
Luke Dashjr
aa74130c59 Bugfix: Handle unknown transaction weight by either calculating it (generation only) or ignoring the weightlimit 2016-08-11 22:10:53 +00:00
Luke Dashjr
28f39f440c Bugfix: Initialise weightlimit to INT64_MAX 2016-08-11 22:10:52 +00:00
Luke Dashjr
3280aab174 ABI break: Remove blktemplate_t.{min,max}nonce, since it was never supported and is unlikely to ever be useful 2016-08-11 09:12:35 +00:00
Luke Dashjr
f692fddffa ABI break: Return uint32_t from blktmpl_getcapability since "time" yields a combination of gbt_capabilities_t 2016-08-11 07:49:24 +00:00
Luke Dashjr
aaaa53e7d9 Merge branch '0.5.x' 2016-08-11 07:43:42 +00:00
Luke Dashjr
b2ff42e8b7 Merge branch '0.4.x' into 0.5.x 2016-08-11 07:43:37 +00:00
Luke Dashjr
6c1b8b2cba Merge commit '81f7ae1' into 0.5.x 2016-08-11 07:41:30 +00:00
Luke Dashjr
81f7ae1d1a jansson: When parsing, ignore fractional parts of times 2016-08-11 07:41:01 +00:00
Luke Dashjr
b41a0f11ee Merge commit '339f436' into 0.5.x 2016-08-11 07:40:13 +00:00
Luke Dashjr
128458fbd0 Merge branch 'bugfix_sizelimit' into 0.5.x 2016-08-11 07:39:45 +00:00
Luke Dashjr
33ce817739 Merge branch 'bip9_0.4.x' into 0.4.x 2016-08-11 07:39:22 +00:00
Luke Dashjr
acc9266d63 Merge commit '2cad5fd' into 0.4.x 2016-08-11 07:39:09 +00:00
Luke Dashjr
ce5125dc90 Merge commit '15745d4' into 0.4.x 2016-08-11 07:38:58 +00:00
Luke Dashjr
328300edbe Merge commit '4a01674' into 0.4.x 2016-08-11 07:38:45 +00:00
Luke Dashjr
1783777646 Merge commit 'ebd42b2' into 0.4.x 2016-08-11 07:38:31 +00:00
Luke Dashjr
7b1113110a Bugfix: Correct return type for blkmk_append_coinbase_safe2 hitting sizelimit 2016-08-11 07:37:57 +00:00
Luke Dashjr
4be60421c8 Bugfix: Refuse to accept an unparsable vbrequired 2016-08-11 07:36:42 +00:00
Luke Dashjr
2cad5fdadb Bugfix: Refuse to accept a template with neither coinbasetxn nor coinbasevalue 2016-08-11 07:35:41 +00:00
Luke Dashjr
15745d4a5f Bugfix: Ensure coinbase is always at least 4 bytes long 2016-08-11 07:34:34 +00:00
Luke Dashjr
4a01674cd0 Bugfix: blkmk_get_mdata must fail if we cannot append the coinbase 2016-08-11 07:29:31 +00:00
Luke Dashjr
ebd42b2461 Bugfix: Correct blkmk_work_left for single-work templates that have been used 2016-08-11 07:29:01 +00:00
Luke Dashjr
339f436170 Bugfix: Close memory leak in blktmpl_propose_jansson 2016-08-11 07:28:04 +00:00
Luke Dashjr
d594808495 Merge commit '723a7e5' into 0.4.x 2016-08-10 22:04:58 +00:00
Luke Dashjr
723a7e543b Bugfix: Correctly parse "generation" and "time" mutations 2016-08-10 22:04:41 +00:00
Luke Dashjr
1ff98a1199 gitignore autotools compile wrapper 2016-07-30 22:19:35 +00:00
Luke Dashjr
c9030312dc Revert Segnet support 2016-07-28 03:51:06 +00:00
Luke Dashjr
e1a1b1bd07 assemble_submission: Avoid magic number constants for sizes 2016-07-26 23:56:13 +00:00
Luke Dashjr
3ff3604939 Add "segwit" to supported rule list 2016-07-26 23:54:37 +00:00
Luke Dashjr
86c6f760bf Bugfix: assemble_submission: Enlarge block buffer for witness commitment 2016-07-26 23:54:14 +00:00
Luke Dashjr
7e10567263 Merge branch 'master' into segwit 2016-07-26 23:51:47 +00:00
Luke Dashjr
c524b0160d Merge branch '0.5.x' 2016-07-26 23:51:21 +00:00
Luke Dashjr
a697e39f43 Tree-Merge branch '0.4.x' into 0.5.x 2016-07-26 23:50:30 +00:00
Luke Dashjr
87ccb59726 Merge branch 'bip9' into 0.5.x 2016-07-26 23:50:26 +00:00
Luke Dashjr
1799d18d55 Merge commit '6002cb9' into 0.5.x (removing a line) 2016-07-26 23:49:42 +00:00
Luke Dashjr
99e710cb7f Merge commit '2eb3265' into 0.5.x 2016-07-26 23:48:49 +00:00
Luke Dashjr
6002cb96a0 assemble_submission: Include extranoncesz in buffer allocation
Missing this would result in a buffer overrun, except the varint is allocated 9 bytes, extranonce is rarely more than 4 or 5, and the varint itself can't realistically be more than 3 today
2016-07-26 23:44:17 +00:00
Luke Dashjr
2e0cc834fe Bugfix: blktxn_init: Initialise txid and weight 2016-07-26 23:30:31 +00:00
Luke Dashjr
28a2bb7f6b Add segwit commitment at the end, rather than the start of the output list 2016-07-26 17:20:55 +00:00
Luke Dashjr
5307b027f6 Implement weightlimit 2016-07-26 04:36:22 +00:00
Luke Dashjr
b5c6d97be7 Use new sigop counting (ie, quadrupled) when "segwit" in rules list 2016-07-26 04:24:46 +00:00
Luke Dashjr
048483d97c Parse template block version, rules, and mutations before time limits, transactions, and aux data 2016-07-26 04:24:30 +00:00
Luke Dashjr
1250b472f0 Merge branch 'master' into segwit 2016-07-26 04:23:36 +00:00
Luke Dashjr
871871ddd5 Merge branch 'sigoplimit' 2016-07-26 04:22:24 +00:00
Luke Dashjr
8f8110a7e4 Bugfix: Remove duplicate sigop tallying 2016-07-26 04:22:11 +00:00
Luke Dashjr
80c85d212a When possible, check sigoplimit before appending to the coinbase 2016-07-26 04:07:09 +00:00
Luke Dashjr
016aa307f5 Merge commit '2eb3265' 2016-07-26 03:43:17 +00:00
Luke Dashjr
2eb326525d Bugfix: Reject invalid coinbaseaux data 2016-07-26 03:42:54 +00:00
Luke Dashjr
1ba845f671 Merge commit '861bd06' 2016-07-26 03:33:05 +00:00
Luke Dashjr
861bd066fe Bugfix: Restore calloc despite blktxn_init; if we fail before completing parsing the transaction, we need to avoid uncleared pointers 2016-07-26 03:33:00 +00:00
Luke Dashjr
5ee6256cb4 Merge branch 'master' into segwit 2016-07-26 03:23:53 +00:00
Luke Dashjr
aef9cbc5a5 Merge branch 'master' (early part) into segwit 2016-07-26 03:22:35 +00:00
Luke Dashjr
5875a41d34 Merge branch 'bip9_0.4.x' into 0.4.x 2016-07-26 03:22:05 +00:00
Luke Dashjr
72d0d641b4 Merge branch 'bip9' 2016-07-26 03:21:43 +00:00
Luke Dashjr
c651bc036f Merge: Optionally build example.c with "make example" 2016-07-26 03:20:28 +00:00
Luke Dashjr
2d822c6bbc Minor fixups for "make example" 2016-07-26 03:20:08 +00:00
Luke Dashjr
651323c7c1 Merge branch 'master' into segwit 2016-07-26 03:13:43 +00:00
Luke Dashjr
7364be59db Merge branch 'master' (early part) into segwit 2016-07-26 03:13:18 +00:00
Luke Dashjr
4a1dcb5cb6 Merge branch 'sigoplimit' 2016-07-26 03:12:26 +00:00
Luke Dashjr
df9c3e9303 blkmk_init_generation*: If possible, check we are not overflowing sigoplimit 2016-07-26 03:11:46 +00:00
Luke Dashjr
3c7889fa23 Keep a tally of total sigops in blktmpl_t->txns (if known) 2016-07-26 03:11:18 +00:00
Luke Dashjr
e37ae9022b Implement blkmk_count_sigops 2016-07-26 03:11:18 +00:00
Luke Dashjr
1cf20a8348 Merge integer unpacking code 2016-07-26 02:51:12 +00:00
Luke Dashjr
1a3cdfd792 Merge branch 'master' into segwit 2016-07-26 02:32:36 +00:00
Luke Dashjr
cd1ae36d0d Merge branch 'populate_txn' 2016-07-26 02:30:48 +00:00
Luke Dashjr
56187b6710 Parse transaction sigops 2016-07-26 02:19:00 +00:00
Luke Dashjr
ba398a34e7 Parse transaction required-flag 2016-07-26 02:19:00 +00:00
Luke Dashjr
b05c2c50de Parse transaction fee 2016-07-26 02:19:00 +00:00
Luke Dashjr
4babc68a5f Parse transaction depends list 2016-07-26 02:19:00 +00:00
Luke Dashjr
12db22114d API break: Represent unknown txn {dependscount,fee_,sigops_} as -1 instead of 0
Also renamed the fields to break code relying on old interpretation
2016-07-26 02:18:37 +00:00
Luke Dashjr
7e7f376aa3 Merge branch '0.4.x' 2016-07-26 02:18:13 +00:00
Luke Dashjr
8f11886982 Null-Merge branch '0.4.x' (early part) 2016-07-26 02:18:05 +00:00
Luke Dashjr
89c06f9a31 Merge branch '0.4.x' (early part) 2016-07-26 02:17:55 +00:00
Luke Dashjr
9f58bcb4aa Bugfix: Check range of number values
Ensure they survive the round-trip from double to their native type and (implicitly) back
2016-07-26 02:17:05 +00:00
Luke Dashjr
5016f8d86a Parse transaction weights into blktxn_t structure
ABI break: sizeof(blktxn_t) has been increased, so accesses to blktmpl_t->txns[>0] use a different offset (aside, hash_ and txid are moved)
New ABI supports up to 512 MB transactions (with a max weight-per-bytes of 4), and library gracefully interprets larger weight values as -1 (unknown)
2016-07-23 21:25:38 +00:00
Luke Dashjr
3be2fadaca AUTHORS: Add Cory Fields 2016-07-23 21:08:17 +00:00
Luke Dashjr
7e0d27119c libblkmaker 0.5.3
-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQQcBAABCAAGBQJW9YUnAAoJEL0ClCQh9IifGT0f/0YM3IfoeFFc2cNX/tJvyAeM
 MTmgne3rhzqo9sMI8XXZTL7G5zKIst2MtlVS/pGJ0RbbvG/SaoZruIf/mGE6fDxX
 R/E00EoSnVPZXPPYmAWyP6Ya2pLkSzYpvpJ301avLJXC/ICNDa9Xcnd8/e9emHxE
 0WQvu45OFBZKjn5nwgsZnuwneCHGSGYvkvmYVnhfyBHS+gHHspv0gp/046KklD3o
 CJOWWTQYubGXp26cZ6bZbHW+SybixMwo59uRKLOCU9dgMwxtUDYinVEBUDua+2W+
 /faMu9tGr9Dah4v7AHOyn6kcU444kfg5U8wBcQaITPDAdexq5yJTbr56CeX1R8uq
 aw71OApIDEwUAjq6wwTixe7or6ZyXePIrJc4oMMm43pia5gM1ZjPeylrt03FLhux
 +FHZPqDHRHe/cQsRB6kENr91tdS7CiehgtJPzQRvsDLCSyO3PPb600NfcGNOOILp
 De9cQGN3RHOcq+4PcwB878CYXao8QC+DOiodOA+XAP4s64E1fOtXNnQzCWPKwF/n
 asLSqg7kEbOhX36IGzZaBLbRsyJOKHWbAPHFr52sFWXkje1yq9PrBR6IieuMJtqS
 IOGkvflkYkxJJ/xEbhaiy+4R7IVlVH32puj2xswKtvMOcm7KcL614RzwRRTmT9EQ
 mWYGZrypsG6XHMLFLKE9wooCZ5hd1tZm2zpIPSPKVFV7lXWzC4hWSsCjpynJj9FQ
 zLY4xQRcgnKlnx5Lz5nwuuymQoCJ09xxCm/YvLtuO9e4N4FlPUY3XegRRAh4g2Cy
 nsw+szmpxS6JrXmNwa0DSgvLj7YG/sednCqW5eGemnDeBpjiwjx6T9KasTU1EEs5
 GGyro8dFFak3s9Mdy2eTe6dPXxN4X4egk+ai+FEIMY0HmrrPHSdGzEiQZmw5ov/Z
 uVmAZJpxp48m1Ho/XU4QoUuEnGqa9JO6RZnUcefeznlgvlIVypuTqM9OI2vMPQ0t
 gtAb0YCVN5g6ISffip3VEgx4gHAbhOvpy8tcWUhuhz5+nkT6M7srzyoiIhw3d13E
 vtzNLNyUOztzrf+yZGSwOK9Urf3+krvN2C65g4I0RbTedmzManGuUvKwg2oo8B75
 lPoy612CrMv+2SBPSUipe+XEWBbtghf0mDPqmm886BM3ZMDO6HCW0DqcnkHcELzA
 bea5Qb7VIX0K568OknmUMi0Omozk0r2Minxr/QHcw7M/z58h3PvpB7O009NEi3o/
 iDC0IZbM+Hl01s//cOcDeQxnSlrik8gbKQUeQsmBakz5zQtwDR4et9P+nG4Pgx8C
 hHUwxY3NDvMRTP72JUQyHT9Iommh8jomaCikJlqj3xOxSdN3AftAmuLQ7pwuML4=
 =P5YU
 -----END PGP SIGNATURE-----

Merge tag 'v0.5.3' into segwit

libblkmaker 0.5.3
2016-07-23 20:26:07 +00:00
Luke Dashjr
d5a43949b1 Merge bugfix_sizelimit into segwit 2016-07-23 20:25:32 +00:00
Luke Dashjr
382e864589 Merge into segwit 2016-07-23 20:10:39 +00:00
Geremia
d0a9367017 "make example" builds example.c if libgcrypt present
using AM_PATH_LIBGCRYPT to check for libgcrypt

removed AC_MSG_RESULT in configure.ac; added phony "example" target in Makefile.am if libcrypt not found
2016-06-22 13:03:18 -07:00
Luke Dashjr
cc07c06238 jansson: Read time header mutation parameters 2016-05-27 17:24:47 +00:00
Luke Dashjr
24633a987f Bugfix: Use json_number_value in case jansson decided to parse numbers as a "real" 2016-05-27 17:23:30 +00:00
Luke Dashjr
0d8212c1dc Make new BIP 9 features public 2016-05-25 03:55:31 +00:00
Luke Dashjr
676d9ab5eb Merge branch 'bip9_0.4.x' into bip9 2016-05-25 03:54:21 +00:00
Luke Dashjr
f658eabf5e "csv" deployment requires no particular changes, so add it to supported rules 2016-05-25 03:51:52 +00:00
Luke Dashjr
ae7055df8b Parse BIP 9 template fields, and implement handling of unrecognised rules 2016-05-25 03:51:52 +00:00
Luke Dashjr
1e49556078 Implement BIP 9 template request "rules" parameter 2016-05-25 03:49:05 +00:00
Luke Dashjr
d2dde7a9ed Bump versions for 0.5.3 2016-03-25 18:36:16 +00:00
Luke Dashjr
2772cd22cc Update copyrights 2016-03-25 18:28:37 +00:00
Luke Dashjr
d9a0755029 Merge branch 'bugfix_sizelimit' 2016-01-27 07:14:07 +00:00
Luke Dashjr
5f16acdcc4 Merge branch '0.4.x' 2016-01-27 07:13:20 +00:00
Luke Dashjr
4bebe501ad Update for current feature test macros 2016-01-27 07:13:14 +00:00
Luke Dashjr
c94e438c91 Bugfix: Always avoid data/mdata size conflict in blkmk_append_coinbase_safe2 since nothing else checks merkle_only (nor has it available to check) 2016-01-26 04:47:25 +00:00
Luke Dashjr
7bf7e80a6a Bugfix: Expose blkmk_submitm_jansson for submitting results for blkmk_get_mdata 2016-01-26 04:41:39 +00:00
Luke Dashjr
58aa6a3573 Refactor to eliminate blkmk_assemble_submission_ wrapper 2016-01-26 04:41:16 +00:00
Luke Dashjr
e3465d35aa Refactor blkmk_assemble_submission2_ to work with either extranonce/mdata or dataid/data 2016-01-26 04:35:10 +00:00
Luke Dashjr
a22129364a Refactor construction of block submissions to allow for results from get_mdata 2016-01-26 04:26:02 +00:00
Luke Dashjr
24aabb0e55 Bugfix: Allocate temporary space on the heap rather than the stack, and use the actual transaction data size for the buffer 2016-01-26 04:13:43 +00:00
Luke Dashjr
f1ede0aec7 Bugfix: Check full block size against limit when creating/appending the coinbase 2016-01-26 04:13:43 +00:00
Luke Dashjr
ef78f03a58 Make an abstract size variable for libblkmaker_coinbase_size_limit 2016-01-26 04:13:43 +00:00
Luke Dashjr
2763aba114 Keep a count of total size of all non-generation transactions in templates 2016-01-26 00:23:30 +00:00
Cory Fields
9a5799891e segwit: fix witness merkle root creation 2016-01-25 11:51:50 -05:00
Cory Fields
15e2c35bf6 segwit: hash with witness nonce, null for now 2016-01-24 22:40:22 -05:00
Cory Fields
22f6e42844 segwit: fix commitment offsets 2016-01-23 22:33:24 -05:00
Luke Dashjr
c70cc4f116 Segnet support (witness magic, address versions, and block version bump) 2016-01-20 01:45:23 +00:00
Luke Dashjr
29f6df9585 Support for segregated witness commitments when server provides "txid" that does not match "hash" 2016-01-09 21:21:08 +00:00
Luke Dashjr
a1dbe722fa private: Unpack utility functions (upk_u{16,32,64}le) 2016-01-09 21:18:48 +00:00
Huang Le
74e674632e Import varintDecode from BFGMiner 2016-01-09 21:18:48 +00:00
Luke Dashjr
a336d9a70c Move varintEncode earlier in file 2016-01-09 21:13:44 +00:00
Luke Dashjr
cc0f35fb8a Bump versions for 0.5.2 2015-11-09 05:55:59 +00:00
Luke Dashjr
93a91696a5 Merge branch '0.4.x' 2015-11-09 05:55:32 +00:00
Luke Dashjr
1fe058443f Bump versions for 0.4.3 2015-11-09 05:33:41 +00:00
Luke Dashjr
5c535ed092 Support for BIP65 version 4 blocks 2015-11-09 05:32:40 +00:00
Luke Dashjr
e9cd82be93 Bump versions for 0.5.1 2015-02-08 06:24:04 +00:00
Luke Dashjr
76a82009ad Bump versions for 0.4.2 2015-02-08 06:22:55 +00:00
Luke Dashjr
9315e34959 Merge branch '0.4.x'
Conflicts:
	blkmaker.h
2015-02-08 05:45:52 +00:00
Luke Dashjr
54cab99423 Support for BIP66 version 3 blocks 2015-02-08 05:45:04 +00:00
Luke Dashjr
335d42b722 Merge branch '0.4.x' 2014-11-21 23:47:59 +00:00
aalness
f0aff19787 AUTHORS: Add myself 2014-11-21 23:47:44 +00:00
Luke Dashjr
4c4fec0da9 Merge branch '0.4.x' (early part)
Conflicts:
	configure.ac
2014-11-21 23:46:30 +00:00
Luke Dashjr
eeb1599b07 Merge commit '6aa007d' into 0.4.x 2014-11-21 23:45:36 +00:00
aalness
6aa007da0c blktmpl_getcapability: Treat "transactions" mutation the same as "transactions/add" per BIP 0023 2014-11-21 23:43:21 +00:00
Luke Dashjr
653ee225f7 pc: Add libbase58 to Requires.private 2014-11-21 23:10:39 +00:00
Luke Dashjr
35e660860e Bump versions for 0.4.1 2014-11-18 21:27:46 +00:00
Luke Dashjr
9933c42610 Bump versions for 0.5.0 2014-09-10 03:09:53 +00:00
Luke Dashjr
47fa1ce9fb jansson: Read time header mutation parameters 2014-09-02 17:17:52 +00:00
Luke Dashjr
f58db44275 Read tmpl->target as an optional hash (breaks ABI) 2014-09-02 17:14:32 +00:00
Luke Dashjr
62b721ee15 Bugfix: example: Set b58_sha256_impl 2014-09-02 17:13:36 +00:00
Luke Dashjr
41af7e2b7b Remove unused blktemplate_t fields (breaks ABI) 2014-09-02 17:06:01 +00:00
Luke Dashjr
b04e6f3f69 NULL-Merge commit '5a9a96a'
Conflicts:
	blkmaker_jansson.c
	blktemplate.h
2014-09-02 16:55:47 +00:00
Luke Dashjr
902492eccb Merge commit 'e86fe28' 2014-09-02 16:55:23 +00:00
Luke Dashjr
23a429b5b5 NULL-Merge commit '09921de' 2014-09-02 16:55:16 +00:00
Luke Dashjr
5a9a96a306 Merge branch '0.4.x' 2014-09-02 16:53:41 +00:00
Luke Dashjr
62e2f6178b Keep correct ordered hash in txn->hash[1] for use internally while remaining ABI-safe 2014-09-02 16:53:02 +00:00
Luke Dashjr
e86fe28fa0 blktemplate.h: Add warning against allocating blktemplate_t 2014-09-02 16:39:10 +00:00
Luke Dashjr
09921dee12 Merge branch '0.3.x' into 0.4.x 2014-09-02 16:37:18 +00:00
Luke Dashjr
adb6106f89 Merge branch '0.2.x' into 0.3.x 2014-09-02 16:37:06 +00:00
Luke Dashjr
7ad8147482 Merge branch '0.1.x' into 0.2.x 2014-09-02 16:36:54 +00:00
Luke Dashjr
5f463594b1 Revert "Bugfix: Provide correctly-ordered transaction hash (using new key hash_ for backward compatibility)" (broke ABI)
This reverts commit b9572db7d5.
2014-09-02 16:36:32 +00:00
Luke Dashjr
4fe973a101 Bugfix: enum types are not guaranteed to be large enough for a bitmask, so explicitly use uint32_t for gbt_capabilities_t/blkmutations_t bitmasks (this breaks ABI) 2014-09-02 16:20:23 +00:00
Luke Dashjr
20ba4ab64a Merge branch 'proposals' 2014-09-01 20:51:33 +00:00
Luke Dashjr
d95cce298a Merge branch 'aux'
Conflicts:
	blkmaker.c
2014-09-01 20:50:18 +00:00
Luke Dashjr
1a54db48c4 Merge branch '0.4.x' 2014-09-01 20:34:22 +00:00
Luke Dashjr
136a8ee229 Merge branch '0.3.x' into 0.4.x 2014-09-01 20:34:15 +00:00
Luke Dashjr
856f5b0d13 Merge branch '0.2.x' into 0.3.x 2014-09-01 20:34:08 +00:00
Luke Dashjr
d7ce09ca03 Bugfix: blkmk_init_generation: Fail if scriptsz is longer than we properly handle, rather than creating an invalid block 2014-09-01 20:11:46 +00:00
Luke Dashjr
5d14babebc Parse and use coinbaseaux 2014-09-01 19:53:15 +00:00
Luke Dashjr
b549d6ce6b blkmaker_jansson: Support for constructing BIP 23 block proposals 2014-09-01 17:39:37 +00:00
Luke Dashjr
c06ea142ae base58: Remove now-unused b58digits array 2014-08-29 15:50:01 +00:00
Luke Dashjr
d46062c7e6 Use libbase58 for base58 decoding 2014-08-29 01:46:08 +00:00
Luke Dashjr
4b87cfeeaa configure: Require only automake 1.11, since that is sufficient 2014-08-29 01:46:04 +00:00
Luke Dashjr
75d4da0d9b Move submission block assembly code to base libblkmaker 2014-08-24 19:36:20 +00:00
Luke Dashjr
cd1b78f508 Merge branch '0.4.x' 2014-08-22 18:40:22 +00:00
Luke Dashjr
e407661000 Merge branch '0.3.x' into 0.4.x 2014-08-22 18:40:14 +00:00
Luke Dashjr
fe5717762a Merge branch '0.2.x' into 0.3.x 2014-08-22 18:40:00 +00:00
Luke Dashjr
37ed1a8680 Bugfix: b58tobin: Correct zeromask for multiple-of-four binary buffer sizes 2014-08-22 18:39:45 +00:00
Luke Dashjr
628b158a20 Avoid unsafe casting 2014-08-22 18:39:01 +00:00
Luke Dashjr
a7cff7ff18 Include extern "C" wrapper in headers so they can be used from C++ code 2014-08-22 18:36:07 +00:00
Luke Dashjr
4774e2c59f b58check: Check binsz is long enough for checksum 2014-08-22 18:26:49 +00:00
Luke Dashjr
a2d4f33563 Switch to tar.xz dist 2014-08-22 17:58:45 +00:00
Luke Dashjr
c469e805e0 Merge branch '0.4.x' 2014-08-22 17:55:35 +00:00
Luke Dashjr
12acb40d47 Merge branch '0.3.x' into 0.4.x
Conflicts:
	configure.ac
2014-08-22 17:55:27 +00:00
Luke Dashjr
625e04d9df Merge branch '0.2.x' into 0.3.x 2014-08-22 17:53:26 +00:00
Luke Dashjr
948c869356 Bugfix: Include private.h in SOURCES 2014-08-22 17:52:26 +00:00
Luke Dashjr
b253c0b00c Merge branch '0.1.x' into 0.2.x 2014-08-22 17:51:57 +00:00
Luke Dashjr
f9eff703a7 Bugfix: Include documents in "make dist" output 2014-08-22 17:51:51 +00:00
Luke Dashjr
e847c3b10a No longer call configure from autogen.sh 2014-08-22 17:43:04 +00:00
Luke Dashjr
9f831dfbd2 Bump libtool version for 0.3.3 2014-05-26 19:24:48 +00:00
Luke Dashjr
6cc0258704 Merge commit '1cbe9c3' 2014-05-26 06:33:46 +00:00
Luke Dashjr
1cbe9c3d70 Bugfix: Optimise building merkle branches for no-transactions case, avoiding a malloc(0) 2014-05-26 06:32:26 +00:00
Luke Dashjr
385f2ddd7c Bump versions for 0.4.0 2014-05-07 22:30:31 +00:00
Luke Dashjr
3c59c93d42 Merge branch 'work2d' 2014-05-03 23:14:04 +00:00
Luke Dashjr
28b2ff0230 blkmk_get_mdata: Accept can_roll_ntime as an argument 2014-05-03 22:37:08 +00:00
Luke Dashjr
9f5e949f7e Add blkmk_append_coinbase_safe2 which can understand mdata use 2014-02-28 05:21:41 +00:00
Luke Dashjr
847b04d030 Add blkmk_get_mdata function for miners which need to build the merkle root themselves 2014-02-28 05:20:59 +00:00
Luke Dashjr
83daccfeef Optimise merkle root creation by reusing a merkle branch 2014-02-27 16:58:57 +00:00
Luke Dashjr
0299bfc068 Internal code abstraction into blkmk_set_times 2014-02-27 16:48:01 +00:00
Luke Dashjr
93b76398c1 Merge branch '0.3.x' 2014-02-27 16:44:09 +00:00
Luke Dashjr
350229b16b Merge branch '0.2.x' into 0.3.x 2014-02-27 16:44:04 +00:00
Luke Dashjr
300180210e Merge branch '0.1.x' into 0.2.x 2014-02-27 16:43:55 +00:00
Luke Dashjr
ebe52b71c8 Implement blkmk_get_data's out_expire argument 2014-02-27 16:43:37 +00:00
Luke Dashjr
510ab33115 Merge branch '0.3.x' 2014-02-24 06:34:15 +00:00
Luke Dashjr
8dab96e425 Merge branch '0.2.x' into 0.3.x 2014-02-24 06:32:39 +00:00
Luke Dashjr
07fe5b155a Merge branch '0.1.x' into 0.2.x 2014-02-24 06:32:27 +00:00
Luke Dashjr
b9572db7d5 Bugfix: Provide correctly-ordered transaction hash (using new key hash_ for backward compatibility) 2014-02-24 06:32:22 +00:00
Luke Dashjr
eb33f9c8e4 Update copyright headers 2014-01-19 04:46:54 +00:00
Luke Dashjr
2504f48b6c Merge branch '0.3.x'
Conflicts:
	configure.ac
2014-01-19 04:46:20 +00:00
Luke Dashjr
47234b81e6 Merge branch '0.3.x' (early part) 2014-01-19 04:45:57 +00:00
Luke Dashjr
436632ec5b Merge branch '0.3.x' (early part) 2014-01-19 04:45:41 +00:00
Luke Dashjr
15e3d91ccc Merge branch '0.2.x' into 0.3.x
Conflicts:
	blkmaker_jansson.c
2014-01-19 04:44:58 +00:00
Luke Dashjr
11284db136 Merge branch '0.2.x' (early part) into 0.3.x 2014-01-19 04:44:36 +00:00
Luke Dashjr
4282562adf Null-Merge branch '0.2.x' (early part) into 0.3.x
Conflicts:
	configure.ac
2014-01-19 04:44:22 +00:00
Luke Dashjr
7468316108 Merge branch '0.1.x' into 0.2.x 2014-01-19 04:43:15 +00:00
Luke Dashjr
0b052e37a7 Merge branch '0.1.x' (early part) into 0.2.x 2014-01-19 04:43:02 +00:00
Luke Dashjr
cc4f0fa86e libblkmaker 0.1.5
-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.20 (GNU/Linux)
 
 iQQcBAABCAAGBQJSOn5wAAoJEL0ClCQh9Iifrbkf/AvCexni9MV6QeVy/GCQNOW4
 UOhhlqsBUc6llg4OJ/ZPPZxYe6OBm219n8uHkz+nAI2punKUgb43htmOeXusPrJW
 bP6mkDSUJvicDXUwUI1Ep41VPwRfR/P8S38QqadKiP2U01NdpjyYQujJsLAAtC3w
 bhJdVx3SbqfhZfpebI/cjPRyraJ9gUQuZEfMdHfv02WDzmjH8ZH6rhxc8OhBKtVe
 m0H+V9swLadfDqaG/nqJZwC7xrqH/P6akMSiz/0p7yH0UGuwVFMDsxXEiL1j4A6+
 Fs0aN0o+F929aZH5YHlUPU6VxDRmxcwbVD9gYxOnCAHw7W1jL47Y9+BNPFv6wGn0
 PsAcqIVY/td7tsa2prVNpDgVO7iCREYIUEn8esGySDbW4tL4bueGllnIlTYPnCOU
 T9lfEg2ojj+wWJDl3/DarXu+16PytR6rmutIJOz1svJrEksxKc+/rxRZB+6uRe2L
 Be1cJzyKFwCmbCxRvoAbLFXpb02CT4WrVrJJWf7XgvkXlF35BZPM3mdgv9Dp4shI
 +PJBf0HED6x+HrkSOS0CiBzqP5BCqxDpcPiBQ1kk4tsJsrJD8CW+oNwFgBUoLV+N
 DdvhtdxD9Cv5cMzZ69Scq0BXJTTL3JGcwl4eMhG8ILeKkTxGnIUE77yJZU3sPcvN
 8idvpurH9KIeSIzTwmFR+D/xbTijncuOq1Yr4wyrw61QHDhQ+xaWeVoIVvFbuiyf
 4OOMQpxdY5FAe3pbOs6dmDi00ooJHSTLrhXM38bEeSTIgymxrDraSnPAtSZ+WE28
 bLjC/nMrShXBN5GLd0kLXH/xWen+T+VaehJ5yiSbk5gf/zVG/WlPtTZzp1d8NstA
 1xxHuO9+w/LUvwh9sWd+dABDH1pz+QMFM1vbHJ7SD2i+U3GnNA5yfIhWq3h3xV4m
 jBkbd4DdVp6Wanq23pyhZD9O7fH56elnStPmZ+OFOo+RceT2Z71zk9eUILipyCvK
 DeavTThO1kDdDWM/ocv3v2ihaa8vUOoHjgQsfGAGkM+jw5NtDG0JxZB2Wz8rDBu2
 RpLVkkhPojTWAAhi7o4IdfmWuZD/QH9gyWf6ILjD23EM+03HTlYGO/cJIs9GN3rY
 ylHh38ayuaAo+WP+fiLyClaCa0pRBUlaSYQ+0eTjY8v3tmgqK69tzs+oMm95Loiz
 /OV7PMc0CG6l9LccIHpFDEz/0ZsF4NbUoh3QvDyGRHrImw0+r5GrgLHYDOSLR69p
 mJE0R7+2mDZGkol8yPAfCcZTet36MiplRkxzvp9ZmjKH4RcYL2cQh+yHeLBsk8Oq
 ZAOPTP0nhtWJAizGmiiKtY93zEubj0eI8xIqstRCNA/30ftUa+etI7jjzuAXVFk=
 =tLQI
 -----END PGP SIGNATURE-----

Null-Merge tag 'v0.1.5' into 0.2.x

libblkmaker 0.1.5

Conflicts:
	configure.ac
2014-01-19 04:42:52 +00:00
Luke Dashjr
d6002f955f Update copyright headers 2014-01-19 04:42:16 +00:00
Luke Dashjr
cd4badb1c7 Remove autogenerated INSTALL and unused ChangeLog/NEWS files from git 2014-01-19 04:39:21 +00:00
Luke Dashjr
9a5a191e3c COPYING: Update copyright year to 2014 2014-01-19 04:36:06 +00:00
Luke Dashjr
c13ea0903a Build silently when supported by automake 2014-01-19 04:30:48 +00:00
Luke Dashjr
2f899db363 Bugfix: blkmk_init_generation2 needs a return value 2014-01-19 04:29:25 +00:00
Luke Dashjr
8811805155 Bugfix: Avoid breaking strict aliasing rules by copying nonce with memcpy 2014-01-14 21:43:46 +00:00
Luke Dashjr
8d19469301 Merge branch '0.3.x' 2013-08-28 02:49:41 +00:00
Luke Dashjr
bca8f6f5e5 Bump libtool version for 0.3.2 2013-08-24 17:47:39 +00:00
Luke Dashjr
01f4f6b5ef Bump libtool version for 0.2.4 2013-08-24 17:46:34 +00:00
Luke Dashjr
f6f0e617d5 Bump libtool version for 0.1.5 2013-08-24 17:45:20 +00:00
Luke Dashjr
b84806651c blkmk_init_generation3 capable of overriding a provided coinbasetxn if the generation mutation is allowed 2013-08-24 16:54:03 +00:00
Luke Dashjr
5c704c60d6 Merge branch '0.2.x' into 0.3.x 2013-08-24 16:43:19 +00:00
Luke Dashjr
ee639a9b54 Merge branch '0.1.x' into 0.2.x 2013-08-24 16:42:27 +00:00
Luke Dashjr
1bbe9b9162 Merge commit '57f81f1' into 0.1.x 2013-08-24 16:42:19 +00:00
Luke Dashjr
57f81f1702 Bugfix: Advertise support for version/* mutations and submit/{coinbase,truncate} abbreviations 2013-08-24 16:42:11 +00:00
Luke Dashjr
e7d36757ef Merge branch '0.2.x' into 0.3.x 2013-06-25 00:15:33 +00:00
Luke Dashjr
0a47d4c1fa Null-Merge branch '0.2.x' (early part) into 0.3.x
Conflicts:
	blkmaker_jansson.c
2013-06-25 00:15:29 +00:00
Luke Dashjr
f7ad5a4b97 Merge branch '0.1.x' into 0.2.x 2013-06-25 00:14:12 +00:00
Luke Dashjr
a6c23b842d Null-Merge branch '0.1.x' (early part) into 0.2.x
Conflicts:
	configure.ac
2013-06-25 00:14:06 +00:00
Luke Dashjr
9044a62894 Merge commit '17d6193' into 0.1.x 2013-06-25 00:12:51 +00:00
Luke Dashjr
17d6193b07 Bugfix: blktmpl_add_* returns a const char * for errors, not false (for template already populated) 2013-06-25 00:12:40 +00:00
Luke Dashjr
d1a048dd2b Bump libtool version for 0.1.4 2013-06-13 07:30:04 +00:00
Luke Dashjr
8b57005cf1 Add missing copyright headers 2013-06-13 07:26:54 +00:00
Luke Dashjr
e0d2b2d119 Add missing copyright headers 2013-06-13 07:25:49 +00:00
Luke Dashjr
8f4bb3ee9f Add missing copyright headers 2013-06-01 14:51:23 +00:00
Luke Dashjr
1ee3475d2c Merge branch '0.2.x' 2013-05-01 05:39:06 +00:00
Luke Dashjr
3d34fa30a9 Merge branch '0.1.x' into 0.2.x 2013-05-01 05:38:57 +00:00
Luke Dashjr
fb9e98690b Bugfix: Install header for libblkmaker_jansson 2013-05-01 05:38:49 +00:00
Luke Dashjr
ff6a4caa08 Merge commit 'e39b2ac' into 0.1.x 2013-05-01 05:38:18 +00:00
Luke Dashjr
7114d5ee8a Bump libtool version and BLKMAKER_VERSION for 0.3.0 2013-04-05 15:09:36 +00:00
Luke Dashjr
3448695ff4 Add "foreign" submit function to create a call suitable for a local bitcoind 2013-04-05 14:44:55 +00:00
Luke Dashjr
482b48bbd5 Merge commit 'e39b2ac' 2013-04-03 16:48:42 +00:00
Luke Dashjr
e39b2ac972 Support for finding jansson with pkg-config 2013-04-03 16:48:35 +00:00
Luke Dashjr
19847fbab0 Bump libtool version for 0.2.2 2013-01-22 00:14:13 +00:00
Luke Dashjr
86359a8506 Merge branch 'bugfix_b58_padcheck' 2012-12-29 02:34:23 +00:00
Luke Dashjr
5ab4fdff16 Bugfix: _blkmk_b58check: Check that zero-padding on base58check input matches output
This is needed to properly reject addresses with too many or too few prefix/pad '1's.
2012-12-29 02:33:25 +00:00
Luke Dashjr
5f3ad2a1ed Bump libtool version for 0.2.1 2012-12-04 03:04:57 +00:00
Luke Dashjr
f05574db48 blkmk_init_generation2 can assign a boolean on whether it had to create a new coinbase transaction 2012-12-04 01:46:19 +00:00
Luke Dashjr
0d07a57007 Merge branch 'bugfix_generate_append' 2012-12-04 00:10:20 +00:00
Luke Dashjr
b5ab89e0af Bugfix: When providing our own coinbase transaction, enable coinbase mutations 2012-12-04 00:08:27 +00:00
Luke Dashjr
1735818bdc Merge branch 'bugfix_limits_opt' 2012-11-17 20:34:30 +00:00
Luke Dashjr
338e396678 Merge branch 'bugfix_limits_opt' into 0.1.x 2012-11-17 20:31:29 +00:00
Luke Dashjr
dd25439b04 Bugfix: sigoplimit and sizelimit should be optional 2012-11-17 20:26:48 +00:00
Luke Dashjr
6d74cfc8e7 Abstract GETNUM_O and GETNUM_O2 (read optional number) macros 2012-11-03 19:19:01 +00:00
25 changed files with 2969 additions and 648 deletions

13
.gitignore vendored
View File

@ -1,3 +1,10 @@
*.gcov
*.gcda
*.gcno
vgcore*
core*
*.orig
*.rej
*~
*.so
*.o
@ -23,3 +30,9 @@ autom4te.cache
config.*
ii
ar-lib
compile
test-driver
test
test-suite.log
test.log
test.trs

129
.travis.yml Normal file
View File

@ -0,0 +1,129 @@
os: linux
language: c
compiler: gcc
sudo: false
env:
global:
- PKG_CONFIG_LIBDIR="$HOME/lib/pkgconfig"
- OPTS="--prefix=$HOME"
matrix:
include:
# Normal build
- addons:
apt:
packages:
- build-essential
- libjansson-dev
- libgcrypt11-dev
env: CFLAGS="-Wall" AM_CFLAGS='-Werror'
# clang
- compiler: clang
addons:
apt:
packages:
- build-essential
- libjansson-dev
- libgcrypt11-dev
env: CFLAGS="-Wall -fsanitize=undefined -fno-sanitize-recover -fsanitize=address"
# w/o libgcrypt
- addons:
apt:
packages:
- build-essential
- libjansson-dev
# Win32
- addons:
apt:
packages:
- gcc-mingw-w64-i686
- binutils-mingw-w64-i686
- mingw-w64-dev
- wine
env:
- CROSS_TARGET=i686-w64-mingw32
EXEEXT=.exe
BUILD_LIBS=1
WINE_TESTS=1
OPTS="$OPTS --disable-static"
JANSSON_VERSION=v2.4
# Win64
- addons:
apt:
packages:
- gcc-mingw-w64-x86-64
- binutils-mingw-w64-x86-64
- mingw-w64-dev
- wine
env:
- CROSS_TARGET=x86_64-w64-mingw32
EXEEXT=.exe
BUILD_LIBS=1
WINE_TESTS=1
OPTS="$OPTS --disable-static"
JANSSON_VERSION=v2.4
exclude:
- compiler: gcc
# TODO: Linux32 (or 64) & OS X
script:
- if [ -n "$CROSS_TARGET" ]; then
unset CC;
TARGET_OPTS="$TARGET_OPTS --host=$CROSS_TARGET";
fi
- if [ -n "$BUILD_LIBS" ]; then
OPTS="$OPTS --with-gpg-error-prefix=$HOME";
git clone git://git.gnupg.org/libgpg-error.git -b libgpg-error-1.13 --depth 1;
pushd libgpg-error;
./autogen.sh;
./configure $TARGET_OPTS $OPTS --disable-languages --disable-doc;
make;
if [ -z "$WINE_TESTS" ]; then
LD_LIBRARY_PATH="$HOME/lib" make check;
fi;
make install;
popd;
OPTS="$OPTS --with-libgcrypt-prefix=$HOME";
git clone git://git.gnupg.org/libgcrypt.git -b libgcrypt-1.5.4 --depth 1;
pushd libgcrypt;
./autogen.sh;
./configure $TARGET_OPTS $OPTS --disable-ciphers --disable-pubkey-ciphers --disable-random --disable-asm;
make;
if [ -z "$WINE_TESTS" ]; then
LD_LIBRARY_PATH="$HOME/lib" make check;
fi;
make install;
popd;
git clone https://github.com/akheron/jansson.git -b "$JANSSON_VERSION" --depth 1;
pushd jansson;
autoreconf -f -i;
./configure $TARGET_OPTS $OPTS;
make AM_CFLAGS= ;
if [ -z "$WINE_TESTS" ]; then
LD_LIBRARY_PATH="$HOME/lib" make check;
fi;
make install;
popd;
fi
- git clone git://github.com/bitcoin/libbase58 -b v0.1.4 --depth 1
- pushd libbase58
- ./autogen.sh
- ./configure $TARGET_OPTS $OPTS
- make
- if [ -z "$WINE_TESTS" ]; then
LD_LIBRARY_PATH="$HOME/lib" make check VERBOSE=1;
fi
- make install
- popd
-
- ./autogen.sh
- ./configure $TARGET_OPTS $OPTS $CONFIGURE_OPTS || { tail -n 1000 config.log; false; };
- make
- make example$EXEEXT
- make test$EXEEXT
- if [ -z "$WINE_TESTS" ]; then
LSAN_OPTIONS=1 LD_LIBRARY_PATH="$HOME/lib" make check VERBOSE=1;
else
ln -s $HOME/bin/*.dll .libs/;
LSAN_OPTIONS=1 WINEDLLPATH="$PWD/.libs" wine .libs/test.exe;
fi
- make install

View File

@ -1 +1,4 @@
Luke Dashjr <luke_libblkmaker@dashjr.org>
Andy Alness <andy.alness@gmail.com>
Huang Le <4tarhl@gmail.com>
Cory Fields <cory-nospam-@coryfields.com>

View File

@ -1,4 +1,4 @@
Copyright (c) 2012 Luke Dashjr
Copyright 2012-2014 Luke Dashjr
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

370
INSTALL
View File

@ -1,370 +0,0 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share,
you can create a site shell script called `config.site' that gives
default values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@ -1,3 +1,8 @@
# Copyright 2012-2013 Luke Dashjr
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the standard MIT license. See COPYING for more details.
lib_LTLIBRARIES = \
libblkmaker_jansson-@LIBBLKMAKER_API_VERSION@.la \
libblkmaker-@LIBBLKMAKER_API_VERSION@.la
@ -7,9 +12,15 @@ libblkmaker_@LIBBLKMAKER_API_VERSION@_la_SOURCES = \
base58.c \
blkmaker.c \
blktemplate.c \
hex.c
hex.c \
private.h
libblkmaker_@LIBBLKMAKER_API_VERSION@_la_LDFLAGS = -version-info $(LIBBLKMAKER_SO_VERSION) -no-undefined
libblkmaker_@LIBBLKMAKER_API_VERSION@_la_CFLAGS = \
$(libbase58_CFLAGS)
libblkmaker_@LIBBLKMAKER_API_VERSION@_la_LDFLAGS = \
$(libbase58_LIBS) \
-no-undefined \
-version-info $(LIBBLKMAKER_SO_VERSION)
libblkmaker_includedir = $(includedir)/libblkmaker-$(LIBBLKMAKER_API_VERSION)
libblkmaker_include_HEADERS = \
@ -18,16 +29,41 @@ libblkmaker_include_HEADERS = \
libblkmaker_jansson_@LIBBLKMAKER_API_VERSION@_la_SOURCES = blkmaker_jansson.c
libblkmaker_jansson_@LIBBLKMAKER_API_VERSION@_la_DEPENDENCIES = libblkmaker-$(LIBBLKMAKER_API_VERSION).la
libblkmaker_jansson_@LIBBLKMAKER_API_VERSION@_la_CFLAGS = $(JANSSON_CFLAGS)
libblkmaker_jansson_@LIBBLKMAKER_API_VERSION@_la_LDFLAGS = \
-L.libs \
-lblkmaker-$(LIBBLKMAKER_API_VERSION) \
-ljansson \
$(JANSSON_LIBS) \
-no-undefined \
-version-info $(LIBBLKMAKER_SO_VERSION)
libblkmaker_jansson_includedir = $(includedir)/libblkmaker-$(LIBBLKMAKER_API_VERSION)
libblkmaker_jansson_include_HEADERS = \
blkmaker_jansson.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
libblkmaker_jansson-$(LIBBLKMAKER_API_VERSION).pc
dist_noinst_SCRIPTS = autogen.sh
dist_noinst_SCRIPTS = autogen.sh test.sh
dist_noinst_DATA = \
AUTHORS COPYING README \
example.c \
testinput.c
if HAVE_LIBGCRYPT
check_PROGRAMS = test
test_SOURCES = test.c
test_CFLAGS = $(libbase58_CFLAGS) $(JANSSON_CFLAGS) $(LIBGCRYPT_CFLAGS)
test_LDADD = $(libbase58_LIBS) libblkmaker-@LIBBLKMAKER_API_VERSION@.la libblkmaker_jansson-@LIBBLKMAKER_API_VERSION@.la $(JANSSON_LIBS) $(LIBGCRYPT_LIBS)
TESTS = test.sh
EXTRA_PROGRAMS = example
example_SOURCES = example.c
example_CFLAGS = $(libbase58_CFLAGS) $(JANSSON_CFLAGS) $(LIBGCRYPT_CFLAGS)
example_LDADD = $(libbase58_LIBS) libblkmaker-@LIBBLKMAKER_API_VERSION@.la libblkmaker_jansson-@LIBBLKMAKER_API_VERSION@.la $(JANSSON_LIBS) $(LIBGCRYPT_LIBS)
else
example:
@echo "libgcrypt is required to build the example, but was not found"
.PHONY: example
endif

0
NEWS
View File

17
README
View File

@ -5,12 +5,19 @@ Example dependencies:
Jansson 2.1 (to read JSON from stdin)
libgcrypt (for SHA256)
For usage, check out example.c
For usage, check out example.c. Run "make example" to build it.
Note that you must assign blkmk_sha256_impl to a function pointer:
bool mysha256(void *hash_out, const void *data, size_t datasz)
hash_out must be able to overlap with data!
Also note that you should NOT roll ntime for data retrieved; while it will
probably work, there is no guarantee it won't fall outside the maxtime limits
for the blocktemplate. It is usually best to simply get more data as often
as it is needed.
Also note that you should NOT roll ntime for data retrieved without explicitly
checking that it falls within the template's limitations (mintime, maxtime,
mintimeoff, and maxtimeoff); read the BIP 23 specification in detail to
understand how they work. It is usually best to simply get more data as often
as it is needed. For blkmk_get_mdata, you may specify that you intend to roll
the ntime header exactly once per second past usetime - it will then set
*out_expires such that the expiration occurs before you roll beyond any ntime
limits. If you are rolling ntime at any rate other than once per second, you
should NOT specify can_roll_ntime to blkmk_get_mdata, and must check that your
usage falls within the explicit template limits yourself.

View File

@ -1,4 +1,7 @@
#!/bin/sh -e
# Written by Luke Dashjr in 2012
# This program is released under the terms of the Creative Commons "CC0 1.0 Universal" license and/or copyright waiver.
if test -z "$srcdir"; then
srcdir=`dirname "$0"`
if test -z "$srcdir"; then
@ -6,4 +9,3 @@ if test -z "$srcdir"; then
fi
fi
autoreconf --force --install --verbose "$srcdir"
test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"

View File

@ -1,3 +1,10 @@
/*
* Copyright 2012 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#ifndef WIN32
#include <arpa/inet.h>
#else
@ -8,100 +15,35 @@
#include <stdint.h>
#include <string.h>
#include <libbase58.h>
#include <blkmaker.h>
#include "private.h"
static const int8_t b58digits[] = {
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8,-1,-1,-1,-1,-1,-1,
-1, 9,10,11,12,13,14,15, 16,-1,17,18,19,20,21,-1,
22,23,24,25,26,27,28,29, 30,31,32,-1,-1,-1,-1,-1,
-1,33,34,35,36,37,38,39, 40,41,42,43,-1,44,45,46,
47,48,49,50,51,52,53,54, 55,56,57,-1,-1,-1,-1,-1,
};
bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz) {
const unsigned char *b58u = (void*)b58;
unsigned char *binu = bin;
size_t outisz = (binsz + 3) / 4;
uint32_t outi[outisz];
uint64_t t;
uint32_t c;
size_t i, j;
uint8_t bytesleft = binsz % 4;
uint32_t zeromask = ~((1 << ((bytesleft) * 8)) - 1);
if (!b58sz)
b58sz = strlen(b58);
memset(outi, 0, outisz * sizeof(*outi));
for (i = 0; i < b58sz; ++i)
{
if (b58u[i] & 0x80)
// High-bit set on invalid digit
return false;
if (b58digits[b58u[i]] == -1)
// Invalid base58 digit
return false;
c = b58digits[b58u[i]];
for (j = outisz; j--; )
{
t = ((uint64_t)outi[j]) * 58 + c;
c = (t & 0x3f00000000) >> 32;
outi[j] = t & 0xffffffff;
}
if (c)
// Output number too big (carry to the next int32)
return false;
if (outi[0] & zeromask)
// Output number too big (last int32 filled too far)
return false;
}
j = 0;
switch (bytesleft) {
case 3:
*(binu++) = (outi[0] & 0xff0000) >> 16;
case 2:
*(binu++) = (outi[0] & 0xff00) >> 8;
case 1:
*(binu++) = (outi[0] & 0xff);
++j;
default:
break;
}
for (; j < outisz; ++j)
{
*((uint32_t*)binu) = htonl(outi[j]);
binu += sizeof(uint32_t);
}
return true;
return b58tobin(bin, &binsz, b58, b58sz);
}
int _blkmk_b58check(void *bin, size_t binsz) {
unsigned char buf[32];
unsigned char *binc = bin;
if (!_blkmk_dblsha256(buf, bin, binsz - 4))
return -2;
if (memcmp(&binc[binsz - 4], buf, 4))
return -1;
return binc[0];
int _blkmk_b58check(void *bin, size_t binsz, const char *base58str) {
if (!b58_sha256_impl)
b58_sha256_impl = blkmk_sha256_impl;
return b58check(bin, binsz, base58str, 34);
}
size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr) {
unsigned char addrbin[25];
unsigned char *cout = out;
const size_t b58sz = strlen(addr);
int addrver;
size_t rv;
if (!_blkmk_b58tobin(addrbin, sizeof(addrbin), addr, 0))
rv = sizeof(addrbin);
if (!b58_sha256_impl)
b58_sha256_impl = blkmk_sha256_impl;
if (!b58tobin(addrbin, &rv, addr, b58sz))
return 0;
addrver = _blkmk_b58check(addrbin, sizeof(addrbin));
addrver = b58check(addrbin, sizeof(addrbin), addr, b58sz);
switch (addrver) {
case 0: // Bitcoin pubkey hash
case 111: // Testnet pubkey hash

View File

@ -1,3 +1,10 @@
/*
* Copyright 2012-2016 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
@ -6,11 +13,32 @@
#include <time.h>
#include <unistd.h>
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif
#include <blkmaker.h>
#include <blktemplate.h>
#include "private.h"
const char *blkmk_supported_rules[] = {
"csv",
"segwit",
NULL
};
bool blkmk_supports_rule(const char * const rulename) {
for (const char **r = blkmk_supported_rules; *r; ++r) {
if (!strcmp(rulename, *r)) {
return true;
}
}
return false;
}
static inline
void my_htole32(unsigned char *buf, uint32_t n) {
buf[0] = (n >> 0) % 256;
@ -34,12 +62,131 @@ bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz) {
#define dblsha256 _blkmk_dblsha256
uint64_t blkmk_init_generation(blktemplate_t *tmpl, void *script, size_t scriptsz) {
if (tmpl->cbtxn)
static
size_t varintDecode(const uint8_t *p, size_t size, uint64_t *n)
{
if (size > 8 && p[0] == 0xff)
{
*n = upk_u64le(p, 1);
return 9;
}
if (size > 4 && p[0] == 0xfe)
{
*n = upk_u32le(p, 1);
return 5;
}
if (size > 2 && p[0] == 0xfd)
{
*n = upk_u16le(p, 1);
return 3;
}
if (size > 0 && p[0] <= 0xfc)
{
*n = p[0];
return 1;
}
return 0;
}
#define max_varint_size (9)
static
char varintEncode(unsigned char *out, uint64_t n) {
if (n < 0xfd)
{
out[0] = n;
return 1;
}
char L;
if (n <= 0xffff)
{
out[0] = '\xfd';
L = 3;
}
else
if (n <= 0xffffffff)
{
out[0] = '\xfe';
L = 5;
}
else
{
out[0] = '\xff';
L = 9;
}
for (unsigned char i = 1; i < L; ++i)
out[i] = (n >> ((i - 1) * 8)) % 256;
return L;
}
static uint8_t blkmk_varint_encode_size(const uint64_t n) {
uint8_t dummy[max_varint_size];
return varintEncode(dummy, n);
}
static
int16_t blkmk_count_sigops(const uint8_t * const script, const size_t scriptsz, const bool bip141) {
int16_t sigops = 0;
for (size_t i = 0; i < scriptsz; ++i) {
if (script[i] <= 0x4c /* OP_PUSHDATA1 */) {
if (script[i] == 0x4c) {
if (i + 1 >= scriptsz) {
break;
}
++i;
}
i += script[i];
} else if (script[i] == 0x4d /* OP_PUSHDATA2 */) {
if (i + 2 >= scriptsz) {
break;
}
i += 2 + upk_u16le(script, i + 1);
} else if (script[i] == 0x4e /* OP_PUSHDATA4 */) {
if (i + 4 >= scriptsz) {
break;
}
i += 4 + upk_u32le(script, i + 1);
} else if (script[i] == 0xac /* OP_CHECKSIG */ || script[i] == 0xad /* OP_CHECKSIGVERIFY */) {
++sigops;
} else if (script[i] == 0xae /* OP_CHECKMULTISIG */ || script[i] == 0xaf /* OP_CHECKMULTISIGVERIFY */) {
sigops += 20;
}
}
if (bip141) {
sigops *= 4;
}
return sigops;
}
static int64_t blkmk_calc_gentx_weight(const void * const data, const size_t datasz) {
return (datasz * 4) + 2 /* marker & flag */ + 1 /* witness stack count */ + 1 /* stack item size */ + 32 /* stack item: nonce */;
}
static int64_t blktxn_set_gentx_weight(struct blktxn_t * const gentx) {
if (gentx->weight < 0) {
gentx->weight = blkmk_calc_gentx_weight(gentx->data, gentx->datasz);
}
return gentx->weight;
}
uint64_t blkmk_init_generation3(blktemplate_t * const tmpl, const void * const script, const size_t scriptsz, bool * const inout_newcb) {
const bool replace_existing = *inout_newcb;
*inout_newcb = false;
if (tmpl->cbtxn && !(replace_existing && (tmpl->mutations & BMM_GENERATE)))
{
return 0;
}
if (!tmpl->has_cbvalue) {
// TODO: Figure it out from the existing cbtxn
return 0;
}
if (scriptsz >= 0xfd)
return 0;
size_t datasz = 62 + sizeof(blkheight_t) + scriptsz;
unsigned char *data = malloc(datasz);
unsigned char *data = malloc(168 + scriptsz);
size_t off = 0;
if (!data)
return 0;
@ -64,6 +211,27 @@ uint64_t blkmk_init_generation(blktemplate_t *tmpl, void *script, size_t scripts
data[off++] = h;
data[42] = data[41] - 1;
if (tmpl->aux_count)
{
unsigned auxsz = off++;
data[auxsz] = 0;
++data[41];
for (unsigned i = 0; i < tmpl->aux_count; ++i)
{
struct blkaux_t * const aux = &tmpl->auxs[i];
if ((size_t)data[41] + aux->datasz > libblkmaker_coinbase_size_limit)
{
free(data);
return 0;
}
memcpy(&data[off], tmpl->auxs[i].data, aux->datasz);
data[41] += aux->datasz;
data[auxsz] += aux->datasz;
off += aux->datasz;
}
}
memcpy(&data[off],
"\xff\xff\xff\xff" // sequence
"\x01" // output count
@ -72,48 +240,162 @@ uint64_t blkmk_init_generation(blktemplate_t *tmpl, void *script, size_t scripts
my_htole64(&data[off], tmpl->cbvalue);
off += 8;
data[off++] = scriptsz;
memcpy(&data[off], script, scriptsz);
off += scriptsz;
if (scriptsz) {
memcpy(&data[off], script, scriptsz);
off += scriptsz;
}
memset(&data[off], 0, 4); // lock time
off += 4;
struct blktxn_t *txn = calloc(1, sizeof(*tmpl->cbtxn));
const unsigned long pretx_size = libblkmaker_blkheader_size + blkmk_varint_encode_size(1 + tmpl->txncount);
const int16_t sigops_counted = blkmk_count_sigops(script, scriptsz, tmpl->_bip141_sigops);
const int64_t gentx_weight = blkmk_calc_gentx_weight(data, off);
if (pretx_size + tmpl->txns_datasz + off > tmpl->sizelimit
|| (tmpl->txns_weight >= 0 && tmpl->txns_weight + gentx_weight > tmpl->weightlimit)
|| (tmpl->txns_sigops >= 0 && tmpl->txns_sigops + sigops_counted > tmpl->sigoplimit)) {
free(data);
return 0;
}
struct blktxn_t *txn = malloc(sizeof(*tmpl->cbtxn));
if (!txn)
{
free(data);
return 0;
}
blktxn_init(txn);
txn->data = data;
txn->datasz = off;
txn->sigops_ = sigops_counted;
txn->weight = gentx_weight;
if (tmpl->cbtxn)
{
blktxn_clean(tmpl->cbtxn);
free(tmpl->cbtxn);
}
tmpl->cbtxn = txn;
tmpl->mutations |= BMM_CBAPPEND | BMM_CBSET | BMM_GENERATE;
*inout_newcb = true;
return tmpl->cbvalue;
}
uint64_t blkmk_init_generation2(blktemplate_t *tmpl, void *script, size_t scriptsz, bool *out_newcb) {
bool tmp;
if (!out_newcb)
out_newcb = &tmp;
*out_newcb = false;
return blkmk_init_generation3(tmpl, script, scriptsz, out_newcb);
}
uint64_t blkmk_init_generation(blktemplate_t *tmpl, void *script, size_t scriptsz) {
return blkmk_init_generation2(tmpl, script, scriptsz, NULL);
}
static
bool blkmk_hash_transactions(blktemplate_t * const tmpl)
{
for (unsigned long i = 0; i < tmpl->txncount; ++i)
{
struct blktxn_t * const txn = &tmpl->txns[i];
if (txn->hash_)
continue;
txn->hash_ = malloc(sizeof(*txn->hash_));
if (!dblsha256(txn->hash_, txn->data, txn->datasz))
{
free(txn->hash_);
return false;
}
}
return true;
}
static
bool blkmk_build_merkle_branches(blktemplate_t * const tmpl)
{
int branchcount, i;
libblkmaker_hash_t *branches;
if (tmpl->_mrklbranch)
return true;
if (!blkmk_hash_transactions(tmpl))
return false;
branchcount = blkmk_flsl(tmpl->txncount);
if (!branchcount)
{
tmpl->_mrklbranchcount = 0;
tmpl->_mrklbranch = NULL;
return true;
}
branches = malloc(branchcount * sizeof(*branches));
if (!branches) {
return false;
}
size_t hashcount = tmpl->txncount + 1;
libblkmaker_hash_t * const hashes = malloc((hashcount + 1) * sizeof(*hashes)); // +1 for when the last needs duplicating
if (!hashes) {
free(branches);
return false;
}
for (i = 0; i < tmpl->txncount; ++i)
{
struct blktxn_t * const txn = &tmpl->txns[i];
txnhash_t * const txid = txn->txid ? txn->txid : txn->hash_;
memcpy(&hashes[i + 1], txid, sizeof(*hashes));
}
for (i = 0; i < branchcount; ++i)
{
memcpy(&branches[i], &hashes[1], sizeof(*hashes));
if (hashcount % 2)
{
memcpy(&hashes[hashcount], &hashes[hashcount - 1], sizeof(*hashes));
++hashcount;
}
for (size_t i = 2; i < hashcount; i += 2)
// This is where we overlap input and output, on the first pair
if (!dblsha256(&hashes[i / 2], &hashes[i], sizeof(*hashes) * 2))
{
free(branches);
free(hashes);
return false;
}
hashcount /= 2;
}
free(hashes);
tmpl->_mrklbranch = branches;
tmpl->_mrklbranchcount = branchcount;
return true;
}
static
bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigned char *cbtxndata, size_t cbtxndatasz) {
size_t hashcount = tmpl->txncount + 1;
unsigned char hashes[(hashcount + 1) * 32];
int i;
libblkmaker_hash_t hashes[0x40];
if (!blkmk_build_merkle_branches(tmpl))
return false;
if (!dblsha256(&hashes[0], cbtxndata, cbtxndatasz))
return false;
for (unsigned long i = 0; i < tmpl->txncount; ++i)
if (!dblsha256(&hashes[32 * (i + 1)], tmpl->txns[i].data, tmpl->txns[i].datasz))
return false;
while (hashcount > 1)
for (i = 0; i < tmpl->_mrklbranchcount; ++i)
{
if (hashcount % 2)
{
memcpy(&hashes[32 * hashcount], &hashes[32 * (hashcount - 1)], 32);
++hashcount;
}
for (size_t i = 0; i < hashcount; i += 2)
// This is where we overlap input and output, on the first pair
if (!dblsha256(&hashes[i / 2 * 32], &hashes[32 * i], 64))
return false;
hashcount /= 2;
memcpy(&hashes[1], tmpl->_mrklbranch[i], 0x20);
// This is where we overlap input and output, on the first pair
if (!dblsha256(&hashes[0], &hashes[0], 0x40))
return false;
}
memcpy(mrklroot_out, &hashes[0], 32);
@ -121,18 +403,101 @@ bool build_merkle_root(unsigned char *mrklroot_out, blktemplate_t *tmpl, unsigne
return true;
}
static
bool _blkmk_calculate_witness_mrklroot(blktemplate_t * const tmpl, libblkmaker_hash_t * const out, bool * const witness_needed) {
if (!blkmk_hash_transactions(tmpl))
return false;
// Step 1: Populate hashes with the witness hashes for all transactions
size_t hashcount = tmpl->txncount + 1;
libblkmaker_hash_t * const hashes = malloc((hashcount + 1) * sizeof(*hashes)); // +1 for when the last needs duplicating
if (!hashes) {
return false;
}
memset(&hashes[0], 0, sizeof(hashes[0])); // Gen tx gets a null entry
*witness_needed = false;
for (unsigned long i = 0; i < tmpl->txncount; ++i) {
struct blktxn_t * const txn = &tmpl->txns[i];
if (txn->txid && memcmp(txn->hash_, txn->txid, sizeof(*txn->txid))) {
*witness_needed = true;
}
memcpy(&hashes[i + 1], txn->hash_, sizeof(*hashes));
}
if (!*witness_needed) {
free(hashes);
return true;
}
// Step 2: Reduce it to a merkle root
for ( ; hashcount > 1 ; hashcount /= 2) {
if (hashcount % 2 == 1) {
// Odd number, duplicate the last
memcpy(&hashes[hashcount], &hashes[hashcount - 1], sizeof(*hashes));
++hashcount;
}
for (size_t i = 0; i < hashcount; i += 2) {
// We overlap input and output here, on the first pair
if (!dblsha256(&hashes[i / 2], &hashes[i], sizeof(*hashes) * 2)) {
free(hashes);
return false;
}
}
}
memcpy(out, hashes, sizeof(*out));
free(hashes);
return true;
}
static
bool _blkmk_witness_mrklroot(blktemplate_t * const tmpl) {
if (tmpl->_calculated_witness) {
// Already calculated
return true;
}
tmpl->_witnessmrklroot = malloc(sizeof(libblkmaker_hash_t));
if (!tmpl->_witnessmrklroot) {
return false;
}
bool witness_needed;
if (!_blkmk_calculate_witness_mrklroot(tmpl, tmpl->_witnessmrklroot, &witness_needed)) {
free(tmpl->_witnessmrklroot);
tmpl->_witnessmrklroot = NULL;
return false;
}
if (!witness_needed) {
free(tmpl->_witnessmrklroot);
tmpl->_witnessmrklroot = NULL;
}
tmpl->_calculated_witness = true;
return true;
}
static const int cbScriptSigLen = 4 + 1 + 36;
static
bool _blkmk_append_cb(blktemplate_t *tmpl, void *vout, const void *append, size_t appendsz) {
bool _blkmk_append_cb(blktemplate_t * const tmpl, void * const vout, const void * const append, const size_t appendsz, size_t * const appended_at_offset, int16_t * const sigops_counted_p) {
unsigned char *out = vout;
unsigned char *in = tmpl->cbtxn->data;
size_t insz = tmpl->cbtxn->datasz;
if (in[cbScriptSigLen] > 100 - appendsz)
if (appendsz > libblkmaker_coinbase_size_limit || in[cbScriptSigLen] > libblkmaker_coinbase_size_limit - appendsz) {
return false;
}
const unsigned long pretx_size = libblkmaker_blkheader_size + blkmk_varint_encode_size(1 + tmpl->txncount);
if (pretx_size + tmpl->cbtxn->datasz + tmpl->txns_datasz + appendsz > tmpl->sizelimit) {
return false;
}
if (tmpl->txns_weight >= 0 && (blktxn_set_gentx_weight(tmpl->cbtxn) + tmpl->txns_weight + (appendsz * 4) > tmpl->weightlimit)) {
return false;
}
const int16_t orig_scriptSig_sigops = blkmk_count_sigops(&in[cbScriptSigLen + 1], in[cbScriptSigLen], tmpl->_bip141_sigops);
int cbPostScriptSig = cbScriptSigLen + 1 + in[cbScriptSigLen];
if (appended_at_offset)
*appended_at_offset = cbPostScriptSig;
unsigned char *outPostScriptSig = &out[cbPostScriptSig];
void *outExtranonce = (void*)outPostScriptSig;
outPostScriptSig += appendsz;
@ -148,15 +513,66 @@ bool _blkmk_append_cb(blktemplate_t *tmpl, void *vout, const void *append, size_
out[cbScriptSigLen] += appendsz;
memcpy(outExtranonce, append, appendsz);
const int16_t sigops_counted = tmpl->cbtxn->sigops_ + blkmk_count_sigops(&out[cbScriptSigLen + 1], out[cbScriptSigLen], tmpl->_bip141_sigops) - orig_scriptSig_sigops;
if (tmpl->txns_sigops >= 0 && tmpl->txns_sigops + sigops_counted > tmpl->sigoplimit) {
// Overflowed :(
if (out == in) {
// Revert it!
out[cbScriptSigLen] -= appendsz;
memmove(&out[cbPostScriptSig], outPostScriptSig, insz - cbPostScriptSig);
}
return false;
}
if (sigops_counted_p) {
*sigops_counted_p = sigops_counted;
}
return true;
}
ssize_t blkmk_append_coinbase_safe(blktemplate_t *tmpl, const void *append, size_t appendsz) {
ssize_t blkmk_append_coinbase_safe2(blktemplate_t * const tmpl, const void * const append, const size_t appendsz, int extranoncesz, const bool merkle_only)
{
if (!(tmpl->mutations & (BMM_CBAPPEND | BMM_CBSET)))
return -1;
size_t datasz = tmpl->cbtxn->datasz;
size_t availsz = 100 - sizeof(unsigned int) - tmpl->cbtxn->data[cbScriptSigLen];
if (extranoncesz == sizeof(unsigned int)) {
++extranoncesz;
} else
if (!merkle_only)
{
if (extranoncesz < sizeof(unsigned int))
extranoncesz = sizeof(unsigned int);
}
if (tmpl->cbtxn->datasz <= cbScriptSigLen || tmpl->cbtxn->datasz <= cbScriptSigLen + tmpl->cbtxn->data[cbScriptSigLen]) {
return -6;
}
if (extranoncesz > libblkmaker_coinbase_size_limit || tmpl->cbtxn->data[cbScriptSigLen] > libblkmaker_coinbase_size_limit || extranoncesz + tmpl->cbtxn->data[cbScriptSigLen] > libblkmaker_coinbase_size_limit) {
return -5;
}
size_t availsz = libblkmaker_coinbase_size_limit - extranoncesz - tmpl->cbtxn->data[cbScriptSigLen];
{
const unsigned long pretx_size = libblkmaker_blkheader_size + blkmk_varint_encode_size(1 + tmpl->txncount);
const size_t current_blocksize = pretx_size + tmpl->cbtxn->datasz + tmpl->txns_datasz;
if (current_blocksize > tmpl->sizelimit) {
return -4;
}
const size_t availsz2 = tmpl->sizelimit - current_blocksize;
if (availsz2 < availsz) {
availsz = availsz2;
}
}
if (tmpl->txns_weight >= 0) {
const size_t current_blockweight = blktxn_set_gentx_weight(tmpl->cbtxn) + tmpl->txns_weight;
if (current_blockweight > tmpl->weightlimit) {
return false;
}
const size_t availsz2 = (tmpl->weightlimit - current_blockweight) / 4;
if (availsz2 < availsz) {
availsz = availsz2;
}
}
if (appendsz > availsz)
return availsz;
@ -165,13 +581,18 @@ ssize_t blkmk_append_coinbase_safe(blktemplate_t *tmpl, const void *append, size
return -2;
tmpl->cbtxn->data = newp;
if (!_blkmk_append_cb(tmpl, newp, append, appendsz))
if (!_blkmk_append_cb(tmpl, newp, append, appendsz, NULL, &tmpl->cbtxn->sigops_))
return -3;
tmpl->cbtxn->datasz += appendsz;
tmpl->cbtxn->weight += appendsz * 4;
return availsz;
}
ssize_t blkmk_append_coinbase_safe(blktemplate_t * const tmpl, const void * const append, const size_t appendsz) {
return blkmk_append_coinbase_safe2(tmpl, append, appendsz, 0, false);
}
bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, size_t *offs) {
unsigned char *in = tmpl->cbtxn->data;
size_t insz = tmpl->cbtxn->datasz;
@ -183,7 +604,7 @@ bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, siz
return true;
}
if (!_blkmk_append_cb(tmpl, vout, &workid, sizeof(workid)))
if (!_blkmk_append_cb(tmpl, vout, &workid, sizeof(workid), NULL, NULL))
return false;
*offs += insz + sizeof(workid);
@ -191,36 +612,197 @@ bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, siz
return true;
}
static const unsigned char witness_magic[] = { 0x6a /* OP_RETURN */, 0x24, 0xaa, 0x21, 0xa9, 0xed };
#define commitment_spk_size (sizeof(witness_magic) + sizeof(libblkmaker_hash_t) /* witness mrklroot */)
#define commitment_txout_size (8 /* value */ + 1 /* scriptPubKey length */ + commitment_spk_size)
static const size_t max_witness_commitment_insert = max_varint_size + commitment_txout_size - 1;
static const libblkmaker_hash_t witness_nonce = { 0 };
static
bool _blkmk_insert_witness_commitment(blktemplate_t * const tmpl, unsigned char * const gentxdata, size_t * const gentxsize) {
if (!_blkmk_witness_mrklroot(tmpl)) {
return false;
}
if (!tmpl->_witnessmrklroot) {
// No commitment needed
return true;
}
libblkmaker_hash_t merkle_with_nonce[2];
libblkmaker_hash_t commitment;
memcpy(&merkle_with_nonce[0], tmpl->_witnessmrklroot, sizeof(*tmpl->_witnessmrklroot));
memcpy(&merkle_with_nonce[1], &witness_nonce, sizeof(witness_nonce));
if(!dblsha256(&commitment, &merkle_with_nonce[0], sizeof(merkle_with_nonce)))
return false;
if (cbScriptSigLen >= *gentxsize) {
return false;
}
const uint8_t coinbasesz = gentxdata[cbScriptSigLen];
const size_t offset_of_txout_count = cbScriptSigLen + coinbasesz + sizeof(coinbasesz) + 4 /* nSequence */;
if (offset_of_txout_count >= *gentxsize) {
return false;
}
uint64_t txout_count;
const size_t in_txout_count_size = varintDecode(&gentxdata[offset_of_txout_count], *gentxsize - offset_of_txout_count, &txout_count);
if (!in_txout_count_size) {
return false;
}
++txout_count;
unsigned char insertbuf[max_varint_size + commitment_txout_size];
const size_t out_txout_count_size = varintEncode(insertbuf, txout_count);
unsigned char * const commitment_txout = &insertbuf[out_txout_count_size];
memset(commitment_txout, 0, 8); // value
commitment_txout[8] = commitment_spk_size;
memcpy(&commitment_txout[9], witness_magic, sizeof(witness_magic));
memcpy(&commitment_txout[9 + sizeof(witness_magic)], &commitment, sizeof(commitment));
const size_t offset_of_txout_data = (offset_of_txout_count + in_txout_count_size);
const size_t new_offset_of_preexisting_txout_data = (offset_of_txout_count + out_txout_count_size);
const size_t length_of_txtail = 4;
const size_t length_of_preexisting_txout_data = (*gentxsize - length_of_txtail) - offset_of_txout_data;
const size_t offset_of_txtail_i = *gentxsize - length_of_txtail; // just the lock time
const size_t offset_of_txtail_o = offset_of_txtail_i + (out_txout_count_size - in_txout_count_size) + commitment_txout_size;
memmove(&gentxdata[offset_of_txtail_o], &gentxdata[offset_of_txtail_i], length_of_txtail);
if (offset_of_txout_data != new_offset_of_preexisting_txout_data) {
memmove(&gentxdata[new_offset_of_preexisting_txout_data], &gentxdata[offset_of_txout_data], length_of_preexisting_txout_data);
}
memcpy(&gentxdata[offset_of_txout_count], insertbuf, out_txout_count_size);
const size_t offset_of_commitment_txout_o = new_offset_of_preexisting_txout_data + length_of_preexisting_txout_data;
memcpy(&gentxdata[offset_of_commitment_txout_o], commitment_txout, commitment_txout_size);
*gentxsize = offset_of_txtail_o + length_of_txtail;
return true;
}
static
void blkmk_set_times(blktemplate_t *tmpl, void * const out_hdrbuf, const time_t usetime, int16_t * const out_expire, const bool can_roll_ntime)
{
double time_passed = difftime(usetime, tmpl->_time_rcvd);
blktime_t timehdr = tmpl->curtime + time_passed;
if (timehdr > tmpl->maxtime)
timehdr = tmpl->maxtime;
my_htole32(out_hdrbuf, timehdr);
if (out_expire)
{
*out_expire = tmpl->expires - time_passed - 1;
if (can_roll_ntime)
{
// If the caller can roll the time header, we need to expire before reaching the maxtime
int16_t maxtime_expire_limit = (tmpl->maxtime - timehdr) + 1;
if (*out_expire > maxtime_expire_limit)
*out_expire = maxtime_expire_limit;
}
}
}
bool blkmk_sample_data_(blktemplate_t * const tmpl, uint8_t * const cbuf, const unsigned int dataid) {
my_htole32(&cbuf[0], tmpl->version);
memcpy(&cbuf[4], &tmpl->prevblk, 32);
unsigned char cbtxndata[tmpl->cbtxn->datasz + sizeof(dataid) + max_witness_commitment_insert];
size_t cbtxndatasz = 0;
if (!_blkmk_extranonce(tmpl, cbtxndata, dataid, &cbtxndatasz))
return false;
if (!_blkmk_insert_witness_commitment(tmpl, cbtxndata, &cbtxndatasz)) {
return false;
}
if (!build_merkle_root(&cbuf[36], tmpl, cbtxndata, cbtxndatasz))
return false;
my_htole32(&cbuf[0x44], tmpl->curtime);
memcpy(&cbuf[72], &tmpl->diffbits, 4);
return true;
}
size_t blkmk_get_data(blktemplate_t *tmpl, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire, unsigned int *out_dataid) {
if (!(blkmk_time_left(tmpl, usetime) && blkmk_work_left(tmpl) && tmpl->cbtxn))
return 0;
if (bufsz < 76)
return 76;
if (tmpl->cbtxn->datasz > cbScriptSigLen && tmpl->cbtxn->data[cbScriptSigLen] + sizeof(*out_dataid) < libblkmaker_coinbase_size_minimum) {
// Add some padding
const size_t padding_required = libblkmaker_coinbase_size_minimum - (tmpl->cbtxn->data[cbScriptSigLen] + sizeof(*out_dataid));
uint8_t padding[padding_required];
static const uint8_t opcode_nop = '\x61';
memset(padding, opcode_nop, padding_required);
if (padding_required != blkmk_append_coinbase_safe2(tmpl, padding, padding_required, 0, false)) {
return 0;
}
}
unsigned char *cbuf = buf;
*out_dataid = tmpl->next_dataid++;
if (!blkmk_sample_data_(tmpl, cbuf, *out_dataid))
return 0;
blkmk_set_times(tmpl, &cbuf[68], usetime, out_expire, false);
return 76;
}
bool blkmk_get_mdata(blktemplate_t * const tmpl, void * const buf, const size_t bufsz, const time_t usetime, int16_t * const out_expire, void * const _out_cbtxn, size_t * const out_cbtxnsz, size_t * const cbextranonceoffset, int * const out_branchcount, void * const _out_branches, size_t extranoncesz, const bool can_roll_ntime)
{
if (!(true
&& blkmk_time_left(tmpl, usetime)
&& tmpl->cbtxn
&& blkmk_build_merkle_branches(tmpl)
&& bufsz >= 76
&& (tmpl->mutations & (BMM_CBAPPEND | BMM_CBSET))
))
return false;
if (extranoncesz == sizeof(unsigned int))
// Avoid overlapping with blkmk_get_data use
++extranoncesz;
if (tmpl->cbtxn->datasz > cbScriptSigLen && tmpl->cbtxn->data[cbScriptSigLen] + extranoncesz < libblkmaker_coinbase_size_minimum) {
extranoncesz = libblkmaker_coinbase_size_minimum - tmpl->cbtxn->data[cbScriptSigLen];
}
void ** const out_branches = _out_branches;
void ** const out_cbtxn = _out_cbtxn;
unsigned char *cbuf = buf;
my_htole32(&cbuf[0], tmpl->version);
memcpy(&cbuf[4], &tmpl->prevblk, 32);
unsigned char cbtxndata[tmpl->cbtxn->datasz + sizeof(*out_dataid)];
size_t cbtxndatasz = 0;
*out_dataid = tmpl->next_dataid++;
if (!_blkmk_extranonce(tmpl, cbtxndata, *out_dataid, &cbtxndatasz))
return 0;
if (!build_merkle_root(&cbuf[36], tmpl, cbtxndata, cbtxndatasz))
return 0;
*out_cbtxnsz = tmpl->cbtxn->datasz + extranoncesz;
*out_cbtxn = malloc(*out_cbtxnsz + max_witness_commitment_insert);
if (!*out_cbtxn)
return false;
unsigned char dummy[extranoncesz];
memset(dummy, 0, extranoncesz);
if (!_blkmk_append_cb(tmpl, *out_cbtxn, dummy, extranoncesz, cbextranonceoffset, NULL))
{
free(*out_cbtxn);
return false;
}
if (!_blkmk_insert_witness_commitment(tmpl, *out_cbtxn, out_cbtxnsz)) {
free(*out_cbtxn);
return false;
}
blktime_t timehdr = tmpl->curtime + difftime(usetime, tmpl->_time_rcvd);
if (timehdr > tmpl->maxtime)
timehdr = tmpl->maxtime;
my_htole32(&cbuf[68], timehdr);
blkmk_set_times(tmpl, &cbuf[68], usetime, out_expire, can_roll_ntime);
memcpy(&cbuf[72], &tmpl->diffbits, 4);
// TODO: set *out_expire if provided
// TEMPORARY HACK:
memcpy(tmpl->_mrklroot, &cbuf[36], 32);
*out_branchcount = tmpl->_mrklbranchcount;
const size_t branches_bytesz = (sizeof(libblkmaker_hash_t) * tmpl->_mrklbranchcount);
*out_branches = malloc(branches_bytesz);
if (!*out_branches)
{
free(*out_cbtxn);
return false;
}
if (branches_bytesz) {
memcpy(*out_branches, tmpl->_mrklbranch, branches_bytesz);
}
return 76;
return true;
}
blktime_diff_t blkmk_time_left(const blktemplate_t *tmpl, time_t nowtime) {
@ -234,7 +816,87 @@ unsigned long blkmk_work_left(const blktemplate_t *tmpl) {
if (!tmpl->version)
return 0;
if (!(tmpl->mutations & (BMM_CBAPPEND | BMM_CBSET)))
return 1;
return (tmpl->next_dataid) ? 0 : 1;
return UINT_MAX - tmpl->next_dataid;
return BLKMK_UNLIMITED_WORK_COUNT;
}
static char *blkmk_assemble_submission2_internal(blktemplate_t * const tmpl, const unsigned char * const data, const void * const extranonce, const size_t extranoncesz, blknonce_t nonce, const bool foreign)
{
const bool incl_gentxn = (foreign || (!(tmpl->mutations & BMAb_TRUNCATE && !extranoncesz)));
const bool incl_alltxn = (foreign || !(tmpl->mutations & BMAb_COINBASE));
size_t blkbuf_sz = libblkmaker_blkheader_size;
if (incl_gentxn) {
blkbuf_sz += max_varint_size /* tx count */;
blkbuf_sz += tmpl->cbtxn->datasz + extranoncesz + (max_varint_size - 1) /* possible enlargement to txout count when adding commitment output */ + commitment_txout_size;
if (incl_alltxn) {
blkbuf_sz += tmpl->txns_datasz;
}
}
unsigned char * const blk = malloc(blkbuf_sz);
if (!blk) {
return NULL;
}
const size_t header_before_nonce_sz = libblkmaker_blkheader_size - sizeof(nonce);
memcpy(blk, data, header_before_nonce_sz);
nonce = htonl(nonce);
memcpy(&blk[header_before_nonce_sz], &nonce, sizeof(nonce));
size_t offs = libblkmaker_blkheader_size;
if (incl_gentxn) {
offs += varintEncode(&blk[offs], 1 + tmpl->txncount);
size_t cbtxnlen = 0;
// Essentially _blkmk_extranonce
if (extranoncesz) {
if (!_blkmk_append_cb(tmpl, &blk[offs], extranonce, extranoncesz, NULL, NULL)) {
free(blk);
return NULL;
}
cbtxnlen += tmpl->cbtxn->datasz + extranoncesz;
} else {
memcpy(&blk[offs], tmpl->cbtxn->data, tmpl->cbtxn->datasz);
cbtxnlen += tmpl->cbtxn->datasz;
}
if (!_blkmk_insert_witness_commitment(tmpl, &blk[offs], &cbtxnlen)) {
return NULL;
}
offs += cbtxnlen;
if (incl_alltxn) {
for (unsigned long i = 0; i < tmpl->txncount; ++i)
{
memcpy(&blk[offs], tmpl->txns[i].data, tmpl->txns[i].datasz);
offs += tmpl->txns[i].datasz;
}
}
}
char *blkhex = malloc((offs * 2) + 1);
_blkmk_bin2hex(blkhex, blk, offs);
free(blk);
return blkhex;
}
char *blkmk_assemble_submission2_(blktemplate_t * const tmpl, const unsigned char * const data, const void *extranonce, size_t extranoncesz, const unsigned int dataid, const blknonce_t nonce, const bool foreign)
{
if (dataid) {
if (extranoncesz) {
// Cannot specify both!
return NULL;
}
extranonce = &dataid;
extranoncesz = sizeof(dataid);
} else if (extranoncesz == sizeof(unsigned int)) {
// Avoid overlapping with blkmk_get_data use
unsigned char extended_extranonce[extranoncesz + 1];
memcpy(extended_extranonce, extranonce, extranoncesz);
extended_extranonce[extranoncesz] = 0;
return blkmk_assemble_submission2_internal(tmpl, data, extended_extranonce, extranoncesz + 1, nonce, foreign);
}
return blkmk_assemble_submission2_internal(tmpl, data, extranonce, extranoncesz, nonce, foreign);
}

View File

@ -7,19 +7,35 @@
#include <blktemplate.h>
#define BLKMAKER_VERSION (2L)
#define BLKMAKER_MAX_BLOCK_VERSION (2)
#ifdef __cplusplus
extern "C" {
#endif
#define BLKMAKER_VERSION (8L)
#define BLKMAKER_MAX_BLOCK_VERSION (0x3fffffff)
#define BLKMAKER_MAX_PRERULES_BLOCK_VERSION (4)
extern const char *blkmk_supported_rules[];
extern bool blkmk_supports_rule(const char *rulename);
extern bool (*blkmk_sha256_impl)(void *hash_out, const void *data, size_t datasz);
extern uint64_t blkmk_init_generation(blktemplate_t *, void *script, size_t scriptsz);
extern uint64_t blkmk_init_generation2(blktemplate_t *, void *script, size_t scriptsz, bool *out_newcb);
extern uint64_t blkmk_init_generation3(blktemplate_t *, const void *script, size_t scriptsz, bool *inout_newcb);
extern ssize_t blkmk_append_coinbase_safe(blktemplate_t *, const void *append, size_t appendsz);
extern ssize_t blkmk_append_coinbase_safe2(blktemplate_t *, const void *append, size_t appendsz, int extranoncesz, bool merkle_only);
extern bool _blkmk_extranonce(blktemplate_t *tmpl, void *vout, unsigned int workid, size_t *offs);
extern size_t blkmk_get_data(blktemplate_t *, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire, unsigned int *out_dataid);
extern bool blkmk_get_mdata(blktemplate_t *, void *buf, size_t bufsz, time_t usetime, int16_t *out_expire, void *out_cbtxn, size_t *out_cbtxnsz, size_t *cbextranonceoffset, int *out_branchcount, void *out_branches, size_t extranoncesz, bool can_roll_ntime);
extern blktime_diff_t blkmk_time_left(const blktemplate_t *, time_t nowtime);
extern unsigned long blkmk_work_left(const blktemplate_t *);
#define BLKMK_UNLIMITED_WORK_COUNT ULONG_MAX
extern size_t blkmk_address_to_script(void *out, size_t outsz, const char *addr);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,14 +1,18 @@
#define _BSD_SOURCE
/*
* Copyright 2012-2016 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#define _BSD_SOURCE
#define _DEFAULT_SOURCE
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif
#include <jansson.h>
#include <blkmaker.h>
@ -20,7 +24,7 @@
# error "Jansson 2.0 with long long support required!"
#endif
json_t *blktmpl_request_jansson(gbt_capabilities_t caps, const char *lpid) {
json_t *blktmpl_request_jansson2(const uint32_t caps, const char * const lpid, const char * const * const rulelist) {
json_t *req, *jcaps, *jstr, *reqf, *reqa;
if (!(req = json_object()))
return NULL;
@ -59,6 +63,26 @@ json_t *blktmpl_request_jansson(gbt_capabilities_t caps, const char *lpid) {
if (json_object_set_new(req, "longpollid", jstr))
goto err;
}
jstr = NULL;
// Add rules list
if (!(jcaps = json_array())) {
goto err;
}
for (const char * const *currule = rulelist; *currule; ++currule) {
if (!(jstr = json_string(*currule))) {
goto err;
}
if (json_array_append_new(jcaps, jstr)) {
goto err;
}
}
jstr = NULL;
if (json_object_set_new(req, "rules", jcaps))
goto err;
jcaps = NULL;
// Put together main JSON-RPC request Object
if (!(jstr = json_string("getblocktemplate")))
goto err;
if (json_object_set_new(reqf, "method", jstr))
@ -81,6 +105,10 @@ err:
return NULL;
}
json_t *blktmpl_request_jansson(const uint32_t caps, const char * const lpid) {
return blktmpl_request_jansson2(caps, lpid, blkmk_supported_rules);
}
#define my_hex2bin _blkmk_hex2bin
@ -97,9 +125,48 @@ err:
return "Error decoding '" #key "'"; \
} while(0)
#define GETNUM(key) do { \
#define GETNUM(key, type) do { \
GET(key, number); \
tmpl->key = json_integer_value(v); \
const double tmpd = json_number_value(v); \
const type tmp = tmpd; \
if (tmpd != tmp) { \
return "Invalid number value for '" #key "'"; \
} \
tmpl->key = tmp; \
} while(0)
#define GETNUM_T(key, type) do { \
GET(key, number); \
const double tmpd = json_number_value(v); \
const type tmp = tmpd; \
/* This checks if it's merely being truncated, and tolerates it */ \
if (tmpd != tmp && !((tmpd < 0) ? (tmpd < tmp && tmpd + 1 > tmp) : (tmpd > tmp && tmpd - 1 < tmp))) { \
return "Invalid number value for '" #key "'"; \
} \
tmpl->key = tmp; \
} while(0)
#define GETNUM_O2(key, skey, type) do { \
if ((v = json_object_get(json, #skey)) && json_is_number(v)) { \
const double tmpd = json_number_value(v); \
const type tmp = tmpd; \
if (tmpd == tmp) { \
tmpl->key = tmp; \
} \
} \
} while(0)
#define GETNUM_O(key, type) GETNUM_O2(key, key, type)
#define GETNUM_OT(key, type) do { \
if ((v = json_object_get(json, #key)) && json_is_number(v)) { \
const double tmpd = json_number_value(v); \
const type tmp = tmpd; \
/* This checks if it's merely being truncated, and tolerates it */ \
if (tmpd == tmp || ((tmpd < 0) ? (tmpd < tmp && tmpd + 1 > tmp) : (tmpd > tmp && tmpd - 1 < tmp))) { \
tmpl->key = tmp; \
} \
} \
} while(0)
#define GETSTR(key, skey) do { \
@ -116,10 +183,14 @@ err:
tmpl->skey = true; \
} while(0)
static void my_flip(void *, size_t);
static
const char *parse_txn(struct blktxn_t *txn, json_t *txnj) {
const char *parse_txn(struct blktxn_t *txn, json_t *txnj, size_t my_tx_index) {
json_t *vv;
blktxn_init(txn);
if (!((vv = json_object_get(txnj, "data")) && json_is_string(vv)))
return "Missing or invalid type for transaction data";
const char *hexdata = json_string_value(vv);
@ -132,15 +203,90 @@ const char *parse_txn(struct blktxn_t *txn, json_t *txnj) {
if ((vv = json_object_get(txnj, "hash")) && json_is_string(vv))
{
hexdata = json_string_value(vv);
txn->hash = malloc(sizeof(*txn->hash));
if (!my_hex2bin(*txn->hash, hexdata, sizeof(*txn->hash)))
txn->hash_ = malloc(sizeof(*txn->hash_));
if (!my_hex2bin(*txn->hash_, hexdata, sizeof(*txn->hash_)))
{
free(txn->hash);
txn->hash = NULL;
free(txn->hash_);
txn->hash_ = NULL;
}
else
my_flip(*txn->hash_, sizeof(*txn->hash_));
}
if ((vv = json_object_get(txnj, "txid")) && json_is_string(vv)) {
hexdata = json_string_value(vv);
txn->txid = malloc(sizeof(*txn->txid));
if (!my_hex2bin(*txn->txid, hexdata, sizeof(*txn->txid))) {
return "Error decoding txid field";
} else {
my_flip(*txn->txid, sizeof(*txn->txid));
}
}
// TODO: dependcount/depends, fee, required, sigops
txn->weight = -1;
if ((vv = json_object_get(txnj, "weight")) && json_is_number(vv)) {
const double f = json_number_value(txnj);
const int32_t i32 = f;
if (f == i32) {
txn->weight = i32;
}
}
if ((vv = json_object_get(txnj, "depends")) && json_is_array(vv)) {
size_t depcount = json_array_size(vv);
if (depcount <= LONG_MAX) {
json_t *v;
long i;
double f;
unsigned long ul;
txn->depends = malloc(sizeof(*txn->depends) * depcount);
for (i = 0; i < depcount; ++i) {
v = json_array_get(vv, i);
if (!json_is_number(v)) {
break;
}
f = json_number_value(v);
ul = f;
if (f != ul || ul >= my_tx_index) {
// Out of range for storage type, fractional number, forward dependency, etc
break;
}
txn->depends[i] = ul;
}
if (i != depcount) {
// We failed somewhere
free(txn->depends);
txn->depends = NULL;
} else {
// Success, finish up with storing the count
txn->dependscount = depcount;
}
}
}
if ((vv = json_object_get(txnj, "fee")) && json_is_number(vv)) {
double f;
int64_t i64;
f = json_number_value(vv);
i64 = f;
if (i64 == f && i64 >= 0) {
txn->fee_ = i64;
}
}
if ((vv = json_object_get(txnj, "required")) && json_is_true(vv)) {
txn->required = true;
}
if ((vv = json_object_get(txnj, "sigops")) && json_is_number(vv)) {
const double f = json_number_value(vv);
int16_t i16 = f;
if (i16 == f && i16 >= 0) {
txn->sigops_ = i16;
}
}
return NULL;
}
@ -161,7 +307,7 @@ void my_flip(void *data, size_t datasz) {
const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t time_rcvd) {
if (tmpl->version)
return false;
return "Template already populated (combining not supported)";
json_t *v, *v2;
const char *s;
@ -176,41 +322,14 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t
GETHEX(bits, diffbits);
my_flip(tmpl->diffbits, 4);
GETNUM(curtime);
GETNUM(height);
GETNUM_T(curtime, blktime_t);
GETNUM(height, blkheight_t);
GETHEX(previousblockhash, prevblk);
my_flip(tmpl->prevblk, 32);
GETNUM(sigoplimit);
GETNUM(sizelimit);
GETNUM(version);
if ((v = json_object_get(json, "coinbasevalue")) && json_is_number(v))
tmpl->cbvalue = json_integer_value(v);
GETSTR(workid, workid);
if (json_object_get(json, "expires"))
GETNUM(expires);
GETSTR(longpollid, lp.id);
GETSTR(longpolluri, lp.uri);
GETBOOL(submitold, submitold, true);
v = json_object_get(json, "transactions");
size_t txns = tmpl->txncount = json_array_size(v);
tmpl->txns = calloc(txns, sizeof(*tmpl->txns));
for (size_t i = 0; i < txns; ++i)
if ((s = parse_txn(&tmpl->txns[i], json_array_get(v, i))))
return s;
if ((v = json_object_get(json, "coinbasetxn")) && json_is_object(v))
{
tmpl->cbtxn = calloc(1, sizeof(*tmpl->cbtxn));
if ((s = parse_txn(tmpl->cbtxn, v)))
return s;
}
// TODO: coinbaseaux
GETNUM_O(sigoplimit, unsigned short);
GETNUM_O(sizelimit, unsigned long);
GETNUM_O(weightlimit, int64_t);
GETNUM(version, uint32_t);
if ((v = json_object_get(json, "mutable")) && json_is_array(v))
{
@ -223,84 +342,236 @@ const char *blktmpl_add_jansson(blktemplate_t *tmpl, const json_t *json, time_t
}
}
if (tmpl->version > 2 || (tmpl->version == 2 && !tmpl->height))
if ((tmpl->version & 0xe0000000) == 0x20000000 && (v = json_object_get(json, "vbavailable")) && json_is_object(v) && (v = json_object_get(json, "rules")) && json_is_array(v)) {
// calloc so that a failure doesn't result in freeing a random pointer
size_t n = json_array_size(v);
tmpl->rules = calloc(n + 1, sizeof(*tmpl->rules));
for (size_t i = 0; i < n; ++i) {
v2 = json_array_get(v, i);
if (!json_is_string(v2)) {
return "Non-String data in template rules list";
}
s = json_string_value(v2);
if (s[0] == '!') {
++s;
if (!blkmk_supports_rule(s)) {
return "Unsupported rule strictly required by template";
}
} else {
if (!blkmk_supports_rule(s)) {
tmpl->unsupported_rule = true;
}
}
tmpl->rules[i] = strdup(s);
if (!tmpl->rules[i]) {
return "Memory allocation error parsing rules";
}
if (!strcmp(s, "segwit")) {
tmpl->_bip141_sigops = true;
}
}
v = json_object_get(json, "vbavailable");
n = json_object_size(v);
tmpl->vbavailable = calloc(n + 1, sizeof(*tmpl->vbavailable));
struct blktmpl_vbassoc **cur_vbassoc = tmpl->vbavailable;
for (void *iter = json_object_iter(v); iter; (iter = json_object_iter_next(v, iter)), ++cur_vbassoc) {
v2 = json_object_iter_value(iter);
if (!json_is_number(v2)) {
return "Invalid type for vbavailable bit";
}
double bitnum = json_number_value(v2);
if (bitnum < 0 || bitnum > 28 || (unsigned)bitnum != bitnum) {
return "Invalid bit number in vbavailable";
}
*cur_vbassoc = malloc(sizeof(**cur_vbassoc));
if (!*cur_vbassoc) {
return "Memory allocation error for struct blktmpl_vbassoc";
}
**cur_vbassoc = (struct blktmpl_vbassoc){
.name = strdup(json_object_iter_key(iter)),
.bitnum = bitnum,
};
if (!(*cur_vbassoc)->name) {
return "Memory allocation error for vbavailable name";
}
}
v = json_object_get(json, "vbrequired");
if (v && json_is_number(v)) {
double tmpd = json_number_value(v);
tmpl->vbrequired = tmpd;
if (tmpl->vbrequired != tmpd) {
return "Unparsable vbrequired";
}
}
}
else
if (tmpl->version > BLKMAKER_MAX_PRERULES_BLOCK_VERSION || (tmpl->version >= 2 && !tmpl->height))
{
if (tmpl->mutations & BMM_VERDROP)
tmpl->version = tmpl->height ? 2 : 1;
tmpl->version = tmpl->height ? BLKMAKER_MAX_PRERULES_BLOCK_VERSION : 1;
else
if (!(tmpl->mutations & BMM_VERFORCE))
return "Unrecognized block version, and not allowed to reduce or force it";
}
if ((v = json_object_get(json, "coinbasevalue")) && json_is_number(v)) {
const double tmpd = json_number_value(v);
const uint64_t tmp = tmpd;
if (tmpd == tmp) {
tmpl->has_cbvalue = true;
tmpl->cbvalue = tmp;
}
}
GETSTR(workid, workid);
GETNUM_OT(expires, int16_t);
GETNUM_OT(maxtime, blktime_t);
GETNUM_OT(maxtimeoff, blktime_diff_t);
GETNUM_OT(mintime, blktime_t);
GETNUM_OT(mintimeoff, blktime_diff_t);
GETSTR(longpollid, lp.id);
GETSTR(longpolluri, lp.uri);
GETBOOL(submitold, submitold, true);
v = json_object_get(json, "transactions");
size_t txns = tmpl->txncount = json_array_size(v);
tmpl->txns = calloc(txns, sizeof(*tmpl->txns));
tmpl->txns_datasz = 0;
tmpl->txns_sigops = 0;
tmpl->txns_weight = 0;
for (size_t i = 0; i < txns; ++i)
{
struct blktxn_t * const txn = &tmpl->txns[i];
if ((s = parse_txn(txn, json_array_get(v, i), i + 1))) {
return s;
}
tmpl->txns_datasz += txn->datasz;
if (tmpl->txns_sigops == -1) {
; // Impossible to tally the unknown
} else if (txn->sigops_ == -1) {
tmpl->txns_sigops = -1;
} else {
tmpl->txns_sigops += txn->sigops_;
}
if (tmpl->txns_weight == -1) {
; // Impossible to tally the unknown
} else if (txn->weight == -1) {
tmpl->txns_weight = -1;
} else {
tmpl->txns_weight += txn->weight;
}
}
if ((v = json_object_get(json, "coinbasetxn")) && json_is_object(v))
{
tmpl->cbtxn = calloc(1, sizeof(*tmpl->cbtxn));
if ((s = parse_txn(tmpl->cbtxn, v, 0)))
return s;
} else if (!tmpl->has_cbvalue) {
return "Missing either coinbasetxn or coinbasevalue";
}
if ((v = json_object_get(json, "coinbaseaux")) && json_is_object(v))
{
tmpl->aux_count = json_object_size(v);
tmpl->auxs = calloc(tmpl->aux_count, sizeof(*tmpl->auxs));
unsigned i = 0;
for (void *iter = json_object_iter(v); iter; (iter = json_object_iter_next(v, iter)), ++i)
{
v2 = json_object_iter_value(iter);
s = json_string_value(v2);
if (!s)
continue;
size_t sz = strlen(s) / 2;
tmpl->auxs[i] = (struct blkaux_t){
.auxname = strdup(json_object_iter_key(iter)),
.data = malloc(sz),
.datasz = sz,
};
if (!my_hex2bin(tmpl->auxs[i].data, s, sz)) {
return "Error decoding 'coinbaseaux' data";
}
}
}
if ((v = json_object_get(json, "target")) && json_is_string(v))
{
tmpl->target = malloc(sizeof(*tmpl->target));
if (!my_hex2bin(tmpl->target, json_string_value(v), sizeof(*tmpl->target)))
return "Error decoding 'target'";
}
tmpl->_time_rcvd = time_rcvd;
return NULL;
}
static
char varintEncode(unsigned char *out, uint64_t n) {
if (n < 0xfd)
json_t *blktmpl_propose_jansson(blktemplate_t * const tmpl, const uint32_t caps, const bool foreign) {
json_t *jreq = blktmpl_request_jansson(caps, NULL), *ja = NULL, *jparams;
if (!(jreq && json_is_object(jreq)))
goto err;
jparams = json_array_get(json_object_get(jreq, "params"), 0);
if (!(jparams && json_is_object(jparams)))
goto err;
if (!(ja = json_string("proposal")))
goto err;
if (json_object_set_new(jparams, "mode", ja))
goto err;
if (tmpl->workid && !foreign)
{
out[0] = n;
return 1;
if (!(ja = json_string(tmpl->workid)))
goto err;
if (json_object_set_new(jparams, "workid", ja))
goto err;
}
char L;
if (n <= 0xffff)
{
out[0] = '\xfd';
L = 3;
}
else
if (n <= 0xffffffff)
{
out[0] = '\xfe';
L = 5;
}
else
{
out[0] = '\xff';
L = 9;
}
for (unsigned char i = 1; i < L; ++i)
out[i] = (n >> ((i - 1) * 8)) % 256;
return L;
ja = NULL;
unsigned int dataid = (tmpl->mutations & (BMM_CBAPPEND | BMM_CBSET) ? 1 : 0);
uint8_t sdata[0x4c];
if (!blkmk_sample_data_(tmpl, sdata, dataid))
goto err;
char *blkhex = blkmk_assemble_submission2_(tmpl, sdata, NULL, 0, dataid, 0, foreign);
if (!blkhex)
goto err;
if (!(ja = json_string(blkhex)))
goto err;
free(blkhex);
if (json_object_set_new(jparams, "data", ja))
goto err;
return jreq;
err:
if (jreq) json_decref(jreq);
if (ja) json_decref(ja);
return NULL;
}
#define my_bin2hex _blkmk_bin2hex
json_t *blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce) {
unsigned char blk[80 + 8 + 1000000];
memcpy(blk, data, 76);
*(uint32_t*)(&blk[76]) = htonl(nonce);
size_t offs = 80;
if (!(tmpl->mutations & BMAb_TRUNCATE && !dataid))
{
offs += varintEncode(&blk[offs], 1 + tmpl->txncount);
if (!_blkmk_extranonce(tmpl, &blk[offs], dataid, &offs))
return NULL;
if (!(tmpl->mutations & BMAb_COINBASE))
for (unsigned long i = 0; i < tmpl->txncount; ++i)
{
memcpy(&blk[offs], tmpl->txns[i].data, tmpl->txns[i].datasz);
offs += tmpl->txns[i].datasz;
}
}
char blkhex[(offs * 2) + 1];
my_bin2hex(blkhex, blk, offs);
static
json_t *_blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, const void * const extranonce, const size_t extranoncesz, unsigned int dataid, blknonce_t nonce, bool foreign) {
char *blkhex = blkmk_assemble_submission2_(tmpl, data, extranonce, extranoncesz, dataid, nonce, foreign);
if (!blkhex)
return NULL;
json_t *rv = json_array(), *ja, *jb;
jb = NULL;
if (!(ja = json_string(blkhex)))
ja = json_string(blkhex);
free(blkhex);
if (!ja)
goto err;
if (json_array_append_new(rv, ja))
goto err;
if (!(ja = json_object()))
goto err;
if (tmpl->workid)
if (tmpl->workid && !foreign)
{
if (!(jb = json_string(tmpl->workid)))
goto err;
@ -333,3 +604,15 @@ err:
if (jb) json_decref(jb);
return NULL;
}
json_t *blkmk_submit_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce) {
return _blkmk_submit_jansson(tmpl, data, NULL, 0, dataid, nonce, false);
}
json_t *blkmk_submit_foreign_jansson(blktemplate_t *tmpl, const unsigned char *data, unsigned int dataid, blknonce_t nonce) {
return _blkmk_submit_jansson(tmpl, data, NULL, 0, dataid, nonce, true);
}
json_t *blkmk_submitm_jansson(blktemplate_t * const tmpl, const unsigned char *data, const void * const extranonce, const size_t extranoncesz, const blknonce_t nonce, const bool foreign) {
return _blkmk_submit_jansson(tmpl, data, extranonce, extranoncesz, 0, nonce, foreign);
}

View File

@ -5,8 +5,20 @@
#include <blktemplate.h>
extern json_t *blktmpl_request_jansson(gbt_capabilities_t extracaps, const char *lpid);
#ifdef __cplusplus
extern "C" {
#endif
extern json_t *blktmpl_request_jansson(uint32_t extracaps, const char *lpid);
extern json_t *blktmpl_request_jansson2(uint32_t extracaps, const char *lpid, const char * const *rulelist);
extern const char *blktmpl_add_jansson(blktemplate_t *, const json_t *, time_t time_rcvd);
extern json_t *blktmpl_propose_jansson(blktemplate_t *, uint32_t caps, bool foreign);
extern json_t *blkmk_submit_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t);
extern json_t *blkmk_submit_foreign_jansson(blktemplate_t *, const unsigned char *data, unsigned int dataid, blknonce_t);
extern json_t *blkmk_submitm_jansson(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, blknonce_t, bool foreign);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,8 +1,16 @@
#define _BSD_SOURCE
/*
* Copyright 2012-2016 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <blktemplate.h>
@ -19,7 +27,7 @@ static const char *capnames[] = {
"coinbase/append",
"coinbase",
"generate",
"generation",
"time/increment",
"time/decrement",
"transactions/add",
@ -42,34 +50,59 @@ const char *blktmpl_capabilityname(gbt_capabilities_t caps) {
return NULL;
}
gbt_capabilities_t blktmpl_getcapability(const char *n) {
uint32_t blktmpl_getcapability(const char *n) {
for (unsigned int i = 0; i < GBT_CAPABILITY_COUNT; ++i)
if (capnames[i] && !strcasecmp(n, capnames[i]))
return 1 << i;
return ((uint32_t)1) << i;
if (!strcasecmp(n, "time")) {
// multi-capability
return BMM_TIMEINC | BMM_TIMEDEC;
}
if (!strcasecmp(n, "transactions"))
return BMM_TXNADD; // Odd one as it's overloaded w/"transactions/add" per spec
return 0;
}
void blktxn_init(struct blktxn_t * const txn) {
txn->data = NULL;
txn->datasz = 0;
txn->hash = NULL;
txn->hash_ = NULL;
txn->txid = NULL;
txn->dependscount = -1;
txn->depends = NULL;
txn->fee_ = -1;
txn->required = false;
txn->sigops_ = -1;
txn->weight = -1;
}
blktemplate_t *blktmpl_create() {
blktemplate_t *tmpl;
tmpl = calloc(1, sizeof(*tmpl));
if (!tmpl)
return NULL;
tmpl->sigoplimit = USHRT_MAX;
tmpl->sizelimit = ULONG_MAX;
tmpl->weightlimit = INT64_MAX;
tmpl->maxtime = 0xffffffff;
tmpl->maxtimeoff = 0x7fff;
tmpl->mintimeoff = -0x7fff;
tmpl->maxnonce = 0xffffffff;
tmpl->expires = 0x7fff;
return tmpl;
}
gbt_capabilities_t blktmpl_addcaps(const blktemplate_t *tmpl) {
uint32_t blktmpl_addcaps(const blktemplate_t *tmpl) {
// TODO: make this a lot more flexible for merging
// For now, it's a simple "filled" vs "not filled"
if (tmpl->version)
return 0;
return GBT_CBTXN | GBT_WORKID | BMM_TIMEINC | BMM_CBAPPEND;
return GBT_CBTXN | GBT_WORKID | BMM_TIMEINC | BMM_CBAPPEND | BMM_VERFORCE | BMM_VERDROP | BMAb_COINBASE | BMAb_TRUNCATE;
}
const struct blktmpl_longpoll_req *blktmpl_get_longpoll(blktemplate_t *tmpl) {
@ -82,27 +115,52 @@ bool blktmpl_get_submitold(blktemplate_t *tmpl) {
return tmpl->submitold;
}
static
void blktxn_free(struct blktxn_t *bt) {
void blktxn_clean(struct blktxn_t * const bt) {
free(bt->data);
free(bt->hash);
free(bt->hash_);
free(bt->depends);
free(bt->txid);
}
static
void blkaux_clean(struct blkaux_t * const aux) {
free(aux->auxname);
free(aux->data);
}
void blktmpl_free(blktemplate_t *tmpl) {
for (unsigned long i = 0; i < tmpl->txncount; ++i)
blktxn_free(&tmpl->txns[i]);
blktxn_clean(&tmpl->txns[i]);
free(tmpl->txns);
if (tmpl->cbtxn)
{
blktxn_free(tmpl->cbtxn);
blktxn_clean(tmpl->cbtxn);
free(tmpl->cbtxn);
}
// TODO: maybe free auxnames[0..n]? auxdata too
free(tmpl->auxnames);
free(tmpl->auxdata);
free(tmpl->_mrklbranch);
free(tmpl->_witnessmrklroot);
for (unsigned i = 0; i < tmpl->aux_count; ++i)
blkaux_clean(&tmpl->auxs[i]);
free(tmpl->auxs);
free(tmpl->workid);
free(tmpl->target);
free(tmpl->lp.id);
free(tmpl->lp.uri);
if (tmpl->rules) {
for (char **currule = tmpl->rules; *currule; ++currule) {
free(*currule);
}
free(tmpl->rules);
}
if (tmpl->vbavailable) {
for (struct blktmpl_vbassoc **curvb = tmpl->vbavailable; *curvb; ++curvb) {
free((*curvb)->name);
free(*curvb);
}
free(tmpl->vbavailable);
}
free(tmpl);
}

View File

@ -1,3 +1,10 @@
/*
* Copyright 2012-2016 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#ifndef BLKTEMPLATE_H
#define BLKTEMPLATE_H
@ -5,6 +12,10 @@
#include <stdint.h>
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint32_t blkheight_t;
typedef uint32_t libblkmaker_hash_t[8];
typedef libblkmaker_hash_t blkhash_t;
@ -13,17 +24,32 @@ typedef uint32_t blktime_t;
typedef int16_t blktime_diff_t;
typedef uint32_t blknonce_t;
#define libblkmaker_blkheader_size (80)
#define libblkmaker_coinbase_size_minimum (4)
#define libblkmaker_coinbase_size_limit (100)
struct blktxn_t {
unsigned char *data;
size_t datasz;
// NOTE: The byte order of hash is backward; use hash_ instead
txnhash_t *hash;
signed long dependcount;
signed long dependscount;
unsigned long *depends;
uint64_t fee;
int64_t fee_;
bool required;
int16_t sigops;
int16_t sigops_;
int32_t weight;
txnhash_t *hash_;
txnhash_t *txid;
};
struct blkaux_t {
char *auxname;
unsigned char *data;
uint8_t datasz;
};
// BIP 23: Long Polling
@ -65,11 +91,18 @@ typedef enum {
extern const char *blktmpl_capabilityname(gbt_capabilities_t);
#define BLKTMPL_LONGEST_CAPABILITY_NAME (16)
extern gbt_capabilities_t blktmpl_getcapability(const char *);
// NOTE: blktmpl_getcapability("time") yields a combination of gbt_capabilities_t
extern uint32_t blktmpl_getcapability(const char *);
typedef gbt_capabilities_t blkmutations_t;
struct blktmpl_vbassoc {
char *name;
uint8_t bitnum;
};
// WARNING: Do not allocate this (ABI is not guaranteed to remain fixed-size)
typedef struct {
uint32_t version;
unsigned char diffbits[4];
@ -86,9 +119,6 @@ typedef struct {
time_t _time_rcvd;
blktime_t curtime;
char auxcount;
char **auxnames;
unsigned char **auxdata;
char *workid;
@ -98,26 +128,51 @@ typedef struct {
// BIP 23: Basic Pool Extensions
int16_t expires;
blkhash_t target;
blkhash_t *target;
// BIP 23: Mutations
blkmutations_t mutations;
uint32_t mutations;
blktime_t maxtime;
blktime_diff_t maxtimeoff;
blktime_t mintime;
blktime_diff_t mintimeoff;
blknonce_t minnonce;
blknonce_t maxnonce;
// TEMPORARY HACK
libblkmaker_hash_t _mrklroot;
libblkmaker_hash_t *_mrklbranch;
int _mrklbranchcount;
unsigned int next_dataid;
unsigned aux_count;
struct blkaux_t *auxs;
unsigned long txns_datasz;
signed long txns_sigops;
char **rules;
bool unsupported_rule;
struct blktmpl_vbassoc **vbavailable;
uint32_t vbrequired;
bool _bip141_sigops;
bool _calculated_witness;
libblkmaker_hash_t *_witnessmrklroot;
int64_t weightlimit;
int64_t txns_weight;
bool has_cbvalue;
} blktemplate_t;
extern void blktxn_init(struct blktxn_t *);
extern void blktxn_clean(struct blktxn_t *);
extern blktemplate_t *blktmpl_create();
extern gbt_capabilities_t blktmpl_addcaps(const blktemplate_t *);
extern uint32_t blktmpl_addcaps(const blktemplate_t *);
extern const struct blktmpl_longpoll_req *blktmpl_get_longpoll(blktemplate_t *);
extern bool blktmpl_get_submitold(blktemplate_t *tmpl);
extern void blktmpl_free(blktemplate_t *);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,25 +1,68 @@
dnl * Copyright 2012-2014 Luke Dashjr
dnl *
dnl * This program is free software; you can redistribute it and/or modify it
dnl * under the terms of the standard MIT license. See COPYING for more details.
AC_INIT(
[libblkmaker],
[0.1],
[0.6.0],
[luke_libblkmaker@dashjr.org],
[libblkmaker],
[http://gitorious.org/bitcoin/libblkmaker])
AC_CONFIG_AUX_DIR([.])
AC_PREREQ([2.59])
AM_INIT_AUTOMAKE([1.10 -Wall dist-bzip2])
AM_INIT_AUTOMAKE([1.11 -Wall dist-xz foreign])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_PROG_CC_C99
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
LT_INIT([disable-static])
# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html
AC_SUBST([LIBBLKMAKER_SO_VERSION], [2:0:2])
AC_SUBST([LIBBLKMAKER_SO_VERSION], [8:0:0])
AC_SUBST([LIBBLKMAKER_API_VERSION], [0.1])
AC_CONFIG_FILES([Makefile
libblkmaker_jansson-${LIBBLKMAKER_API_VERSION}.pc:libblkmaker_jansson.pc.in
])
PKG_CHECK_MODULES([JANSSON],[jansson],[
true
],[
AC_MSG_CHECKING([for jansson in system-default locations])
LIBS="$LIBS -ljansson"
AC_TRY_LINK([
#include <jansson.h>
],[
json_object();
],[
AC_MSG_RESULT([found])
JANSSON_LIBS=-ljansson
],[
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Could not find jansson library])
])
LIBS="${save_LIBS}"
])
AC_SUBST(JANSSON_CFLAGS)
AC_SUBST(JANSSON_LIBS)
PKG_CHECK_MODULES([libbase58],[libbase58])
AC_CHECK_LIB([ws2_32], [strchr])
dnl libgcrypt necessary to build tests and example
dnl check for libgcrypt:
m4_ifdef([AM_PATH_LIBGCRYPT], [
AM_PATH_LIBGCRYPT([],
[
have_libgcrypt=yes
],[
have_libgcrypt=no
])
],[
m4_warn([syntax], [AM_PATH_LIBGCRYPT missing; example and tests will not be available])
])
AM_CONDITIONAL([HAVE_LIBGCRYPT], [test x$have_libgcrypt = xyes])
AC_OUTPUT

View File

@ -1,10 +1,22 @@
/*
* Copyright 2012 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#ifndef WIN32
#include <arpa/inet.h>
#else
#include <winsock2.h>
#endif
#include <gcrypt.h>
#include <libbase58.h>
#include <blkmaker.h>
#include <blkmaker_jansson.h>
@ -13,16 +25,27 @@
#include "testinput.c"
void testb58() {
int rv;
const char *iaddr = "11Baf75Ferj6A7AoN565gCQj9kGWbDMHfN9";
const char *addr = &iaddr[1];
const size_t addrlen = strlen(addr);
size_t actuallen;
char bufx[26] = {'\xff'};
char *buf = &bufx[1];
if (!_blkmk_b58tobin(buf, 25, "1Baf75Ferj6A7AoN565gCQj9kGWbDMHfN9", 0))
actuallen = 25;
if (!b58tobin(buf, &actuallen, addr, addrlen))
exit(1);
if (bufx[0] != '\xff')
exit(2);
char cbuf[51];
_blkmk_bin2hex(cbuf, buf, 25);
printf("Base58 raw data: %s\n", cbuf);
printf("Base58 check: %d\n", _blkmk_b58check(buf, 25));
assert((rv = b58check(buf, 25, addr, addrlen)) == 0);
printf("Base58 check: %d\n", rv);
assert((rv = b58check(buf, 25, &addr[1], addrlen)) < 0);
printf("Base58 check (invalid/ unpadded): %d\n", rv);
assert((rv = b58check(buf, 25, iaddr, addrlen + 1)) < 0);
printf("Base58 check (invalid/extra padded): %d\n", rv);
}
static
@ -44,6 +67,7 @@ int main(int argc, char**argv) {
json_error_t jsone;
const char *err;
b58_sha256_impl = my_sha256;
blkmk_sha256_impl = my_sha256;
testb58();
@ -107,4 +131,5 @@ int main(int argc, char**argv) {
send_json(req);
}
blktmpl_free(tmpl);
return 0;
}

7
hex.c
View File

@ -1,3 +1,10 @@
/*
* Copyright 2012 Luke Dashjr
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the standard MIT license. See COPYING for more details.
*/
#include <string.h>
#include <stdbool.h>

View File

@ -7,5 +7,7 @@ Name: @PACKAGE_NAME@_jansson
Description: Bitcoin block maker library.
Version: @PACKAGE_VERSION@
URL: @PACKAGE_URL@
Libs: -L${libdir} -lblkmaker-@LIBBLKMAKER_API_VERSION@ -lblkmaker_jansson-@LIBBLKMAKER_API_VERSION@
Libs: -L${libdir} -lblkmaker_jansson-@LIBBLKMAKER_API_VERSION@ -lblkmaker-@LIBBLKMAKER_API_VERSION@
Cflags: -I${includedir}/libblkmaker-@LIBBLKMAKER_API_VERSION@
Requires: jansson
Requires.private: libbase58

View File

@ -4,15 +4,59 @@
#include <stdbool.h>
#include <string.h>
#include <blktemplate.h>
// blkmaker.c
extern bool _blkmk_dblsha256(void *hash, const void *data, size_t datasz);
extern bool blkmk_sample_data_(blktemplate_t *, uint8_t *, unsigned int dataid);
extern char *blkmk_assemble_submission2_(blktemplate_t *, const unsigned char *data, const void *extranonce, size_t extranoncesz, unsigned int dataid, blknonce_t nonce, bool foreign);
// hex.c
extern void _blkmk_bin2hex(char *out, const void *data, size_t datasz);
extern bool _blkmk_hex2bin(void *o, const char *x, size_t len);
// base58.c
extern bool _blkmk_b58tobin(void *bin, size_t binsz, const char *b58, size_t b58sz);
extern int _blkmk_b58check(void *bin, size_t binsz);
// inline
// NOTE: This must return 0 for 0
static inline
int blkmk_flsl(unsigned long n)
{
int i;
for (i = 0; n; ++i)
n >>= 1;
return i;
}
static inline
uint16_t upk_u16le(const void * const bufp, const int offset)
{
const uint8_t * const buf = bufp;
return (((uint16_t)buf[offset+0]) << 0)
| (((uint16_t)buf[offset+1]) << 8);
}
static inline
uint32_t upk_u32le(const void * const bufp, const int offset)
{
const uint8_t * const buf = bufp;
return (((uint32_t)buf[offset+0]) << 0)
| (((uint32_t)buf[offset+1]) << 8)
| (((uint32_t)buf[offset+2]) << 0x10)
| (((uint32_t)buf[offset+3]) << 0x18);
}
static inline
uint64_t upk_u64le(const void * const bufp, const int offset)
{
const uint8_t * const buf = bufp;
return (((uint64_t)buf[offset+0]) << 0)
| (((uint64_t)buf[offset+1]) << 8)
| (((uint64_t)buf[offset+2]) << 0x10)
| (((uint64_t)buf[offset+3]) << 0x18)
| (((uint64_t)buf[offset+4]) << 0x20)
| (((uint64_t)buf[offset+5]) << 0x28)
| (((uint64_t)buf[offset+6]) << 0x30)
| (((uint64_t)buf[offset+7]) << 0x38);
}
#endif

1343
test.c Normal file

File diff suppressed because it is too large Load Diff

3
test.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
# To avoid exit codes other than 0 or 1
./test || exit 1

View File

@ -1,3 +1,9 @@
/*
* Written by Luke Dashjr in 2012
*
* This data is released under the terms of the Creative Commons "CC0 1.0 Universal" license and/or copyright waiver.
*/
const char *blkmaker_test_input =
"{"
"\"result\": {"