Line data Source code
1 : /**
2 : * The MIT License (MIT)
3 : *
4 : * Copyright (c) 2021 RSK Labs Ltd
5 : *
6 : * Permission is hereby granted, free of charge, to any person obtaining a copy
7 : * of this software and associated documentation files (the "Software"), to
8 : * deal in the Software without restriction, including without limitation the
9 : * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 : * sell copies of the Software, and to permit persons to whom the Software is
11 : * furnished to do so, subject to the following conditions:
12 : *
13 : * The above copyright notice and this permission notice shall be included in
14 : * all copies or substantial portions of the Software.
15 : *
16 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 : * IN THE SOFTWARE.
23 : */
24 :
25 : #include <string.h>
26 :
27 : #include "bc.h"
28 : #include "hal/log.h"
29 : #include "defs.h"
30 : #include "ints.h"
31 : #include "mem.h"
32 : #include "srlp.h"
33 : #include "bigdigits.h"
34 : #include "memutil.h"
35 :
36 : #include "bc_block.h"
37 : #include "bc_blockutils.h"
38 : #include "bc_advance.h"
39 : #include "bc_diff.h"
40 : #include "bc_err.h"
41 : #include "bc_hash.h"
42 : #include "bc_mm.h"
43 : #include "bc_nu.h"
44 : #include "bc_state.h"
45 : #include "util.h"
46 :
47 : // We'll be asking for block header chunks of at most this size
48 : #define MAX_CHUNK_SIZE 80
49 :
50 : // Threshold difficulty to achieve when advancing the blockchain
51 : // NOTE: for example, to specify 0x 000001d5 bcab6123 1c92f6c6, use
52 : // const DIGIT_T MIN_REQUIRED_DIFFICULTY[BIGINT_LEN] = { 0x1c92f6c6, 0xbcab6123,
53 : // 0x000001d5, 0, 0, 0, 0, 0, 0 };
54 :
55 : // Here we take it from an external definition (see Makefile for details)
56 : #if (defined(HSM_PLATFORM_LEDGER) || defined(HSM_PLATFORM_SGX)) && \
57 : defined(PARAM_MIN_REQUIRED_DIFFICULTY)
58 : static const DIGIT_T MIN_REQUIRED_DIFFICULTY[BIGINT_LEN] =
59 : PARAM_MIN_REQUIRED_DIFFICULTY;
60 : #elif defined(HSM_PLATFORM_X86)
61 : DIGIT_T MIN_REQUIRED_DIFFICULTY[BIGINT_LEN];
62 : #else
63 : #error "Minimum required difficulty not defined!"
64 : #endif
65 :
66 : // -----------------------------------------------------------------------
67 : // Blockchain advance validation state
68 : // -----------------------------------------------------------------------
69 :
70 : // Number of blocks to validate
71 : static uint32_t expected_blocks;
72 :
73 : // Count of validated blocks
74 : static uint32_t curr_block;
75 :
76 : // Expected OP for next message
77 : static uint8_t expected_state;
78 :
79 : // -----------------------------------------------------------------------
80 : // Storage utilities
81 : // -----------------------------------------------------------------------
82 :
83 : /*
84 : * Process merkle proof chunk.
85 : *
86 : * @arg[in] chunk pointer to chunk to process
87 : * @arg[in] size chunk size in bytes
88 : */
89 315 : static void process_merkle_proof(const uint8_t* chunk, uint16_t size) {
90 : // Size limit established from Iris network upgrade onwards
91 315 : if (block.network_upgrade >= NU_IRIS &&
92 315 : block.merkle_off + size > MAX_MERKLE_PROOF_SIZE) {
93 0 : FAIL(MERKLE_PROOF_OVERFLOW);
94 : }
95 :
96 : // Record the additional bytes on the merkle proof (for size tracking)
97 315 : block.merkle_off += size;
98 :
99 : // Process as many hashes as possible
100 315 : uint8_t offset = 0;
101 394 : while (block.wa_off + size - offset >= HASH_SIZE) {
102 79 : if (block.wa_off < HASH_SIZE) {
103 79 : uint8_t old_offset = offset;
104 79 : offset += HASH_SIZE - block.wa_off;
105 158 : WA_STORE(chunk + old_offset, HASH_SIZE - block.wa_off);
106 : }
107 79 : fold_left(&block.ctx, block.merkle_proof_left, block.wa_buf);
108 79 : block.wa_off = 0;
109 : }
110 :
111 : // Copy any remaining bytes in the chunk to the work area
112 315 : if (offset < size) {
113 40 : WA_STORE(chunk + offset, size - offset);
114 : }
115 315 : }
116 :
117 : /*
118 : * Store coinbase transaction chunk in block.cb_txn.
119 : *
120 : * @arg[in] chunk pointer to chunk to store
121 : * @arg[in] size chunk size in bytes
122 : */
123 732 : static void store_cb_txn_bytes(const uint8_t* chunk, uint16_t size) {
124 1464 : SAFE_MEMMOVE(block.cb_txn,
125 : sizeof(block.cb_txn),
126 : block.cb_off,
127 : chunk,
128 : size,
129 : MEMMOVE_ZERO_OFFSET,
130 : size,
131 : FAIL(CB_TXN_OVERFLOW));
132 :
133 732 : block.cb_off += size;
134 732 : }
135 :
136 : // -----------------------------------------------------------------------
137 : // Blockchain advance actions and validations
138 : // -----------------------------------------------------------------------
139 :
140 : /*
141 : * Patch the current block's hash_for_mm.
142 : *
143 : * @arg[in] has_umm_root whether the current block has a umm root
144 : */
145 291 : static void patch_hash_for_mm(bool has_umm_root) {
146 291 : if (has_umm_root) {
147 0 : KECCAK_INIT(&block.mm_ctx);
148 0 : KECCAK_UPDATE(&block.mm_ctx, block.hash_for_mm, UMM_ROOT_SIZE);
149 0 : KECCAK_UPDATE(&block.mm_ctx, block.umm_root, UMM_ROOT_SIZE);
150 0 : KECCAK_FINAL(&block.mm_ctx, block.hash_for_mm);
151 : }
152 :
153 1455 : VAR_BIGENDIAN_TO(
154 : &block.hash_for_mm[KECCAK256_HASH_SIZE - sizeof(block.number)],
155 : block.number,
156 : sizeof(block.number));
157 :
158 291 : uint8_t size =
159 : KECCAK256_HASH_SIZE - MM_HASH_PREFIX_SIZE - MM_HASH_SUFFIX_SIZE;
160 291 : memset(&block.hash_for_mm[MM_HASH_PREFIX_SIZE], 0, size);
161 291 : }
162 :
163 : /*
164 : * Validate the current block's merkle proof. This function assumes
165 : * that the cb_txn_hash is stored in the block's work area.
166 : */
167 295 : static void validate_merkle_proof() {
168 5015 : REV_HASH(block.merkle_proof_left);
169 :
170 295 : if (HNEQ(block.merkle_root, block.merkle_proof_left)) {
171 1 : FAIL(MERKLE_PROOF_MISMATCH);
172 : }
173 294 : }
174 :
175 : /*
176 : * Compute the cb_txn_hash for the current block. It stores
177 : * the cb_txn_hash in the block's work area, so this method
178 : * MUST be called before validate_cb_txn_hash().
179 : */
180 291 : static void compute_cb_txn_hash() {
181 291 : memset(block.wa_buf, 0, CB_MIDSTATE_PREFIX);
182 291 : SAFE_MEMMOVE(block.wa_buf,
183 : sizeof(block.wa_buf),
184 : CB_MIDSTATE_PREFIX,
185 : block.cb_txn,
186 : sizeof(block.cb_txn),
187 : MEMMOVE_ZERO_OFFSET,
188 : CB_MIDSTATE_DATA,
189 : FAIL(BUFFER_OVERFLOW));
190 291 : memset(block.wa_buf + CB_MIDSTATE_PREFIX + CB_MIDSTATE_DATA,
191 : 0,
192 : CB_MIDSTATE_SUFFIX);
193 291 : hash_sha256_ms_init(&block.mid_ctx);
194 291 : hash_sha256_ms_midstate(&block.mid_ctx, block.wa_buf);
195 291 : hash_sha256_ms_update(&block.mid_ctx,
196 : block.cb_txn + CB_MIDSTATE_DATA,
197 291 : block.cb_off - CB_MIDSTATE_DATA);
198 291 : hash_sha256_ms_final(&block.mid_ctx, block.wa_buf);
199 291 : hash_sha256_ms_init(&block.mid_ctx);
200 291 : hash_sha256_ms_update(&block.mid_ctx, block.wa_buf, HASH_SIZE);
201 291 : hash_sha256_ms_final(&block.mid_ctx, block.wa_buf);
202 4947 : REV_HASH(block.wa_buf);
203 291 : }
204 :
205 : /*
206 : * Validate the computed coinbase transaction hash
207 : * against the metadata coinbase transaction hash
208 : */
209 291 : static void validate_cb_txn_hash() {
210 291 : if (HNEQ(block.wa_buf, block.cb_txn_hash)) {
211 0 : FAIL(CB_TXN_HASH_MISMATCH);
212 : }
213 291 : }
214 :
215 : const char rsk_tag[] = "RSKBLOCK:";
216 : #define RSK_TAG_LEN 9 // Length of "RSKBLOCK:"
217 :
218 : /*
219 : * Extract mm_hash from the coinbase transaction, and compare
220 : * it with the current block's hash_for_mm.
221 : */
222 291 : static void validate_mm_hash() {
223 291 : uint8_t* tail = block.cb_txn + CB_MIDSTATE_DATA;
224 291 : uint8_t* last = block.cb_txn + block.cb_off - 1;
225 :
226 : // If present, ptr will point to the rightmost rsk_tag occurrence.
227 : // Otherwise, ptr will be 1 less than tail.
228 291 : uint8_t* ptr = last;
229 27354 : for (; ptr >= tail; ptr--) {
230 27354 : if (last - ptr + 1U >= RSK_TAG_LEN &&
231 25026 : memcmp(ptr, rsk_tag, RSK_TAG_LEN) == 0) {
232 291 : break;
233 : }
234 : }
235 :
236 291 : if (ptr < tail) {
237 0 : FAIL(BTC_CB_TXN_INVALID);
238 : }
239 :
240 291 : if (ptr - tail > CB_MAX_RSK_TAG_POSITION) {
241 0 : FAIL(BTC_CB_TXN_INVALID);
242 : }
243 :
244 291 : if (ptr + RSK_TAG_LEN + HASH_SIZE > last) {
245 0 : FAIL(BTC_CB_TXN_INVALID);
246 : }
247 :
248 291 : if (last - (ptr + RSK_TAG_LEN + HASH_SIZE) + 1 > CB_MAX_AFTER_MM_HASH) {
249 0 : FAIL(BTC_CB_TXN_INVALID);
250 : }
251 :
252 : uint64_t n;
253 2619 : BIGENDIAN_FROM(block.cb_txn, n);
254 291 : if (n + (last - tail) + 1 <= CB_MIN_TX_SIZE) {
255 0 : FAIL(BTC_CB_TXN_INVALID);
256 : }
257 :
258 291 : uint8_t size =
259 : KECCAK256_HASH_SIZE - MM_HASH_PREFIX_SIZE - MM_HASH_SUFFIX_SIZE;
260 291 : if (block.network_upgrade >= NU_WASABI) {
261 291 : memset(&(ptr + RSK_TAG_LEN)[MM_HASH_PREFIX_SIZE], 0, size);
262 : }
263 :
264 291 : if (HNEQ(ptr + RSK_TAG_LEN, block.hash_for_mm)) {
265 1 : FAIL(MM_HASH_MISMATCH);
266 : }
267 290 : }
268 :
269 : /*
270 : * Blockchain advance prologue: call once we have the first block's hash.
271 : */
272 34 : static void bc_adv_prologue() {
273 34 : if (bc_st_updating.in_progress &&
274 14 : HNEQ(block.block_hash, bc_st_updating.next_expected_block)) {
275 0 : FAIL(CHAIN_MISMATCH);
276 : }
277 :
278 34 : if (!bc_st_updating.in_progress) {
279 20 : bc_st_updating.in_progress = true;
280 20 : HSTORE(bc_st_updating.newest_valid_block, block.block_hash);
281 : }
282 34 : }
283 :
284 : /*
285 : * Accumulate total blockchain difficulty. Only call this once you
286 : * know that the current block is valid. If there is enough difficulty
287 : * accumulated, record in the state that we found our new best block.
288 : * Also used to accumulate each brother's difficulty once its parsed.
289 : */
290 292 : static void bc_adv_accum_diff() {
291 : // Nothing to do it we already have a best block
292 292 : if (bc_st_updating.found_best_block) {
293 124 : return;
294 : }
295 :
296 168 : LOG_BIGD_HEX("Total difficulty before = ",
297 : aux_bc_st.total_difficulty,
298 : BIGINT_LEN,
299 : "\n");
300 :
301 : // Cap the block difficulty
302 168 : int cap_error = cap_block_difficulty(block.difficulty);
303 168 : if (cap_error) {
304 0 : LOG("Error while capping block difficulty\n");
305 0 : FAIL(BUFFER_OVERFLOW);
306 : }
307 :
308 : // Otherwise accumulate total difficulty
309 : DIGIT_T carry =
310 168 : accum_difficulty(block.difficulty, aux_bc_st.total_difficulty);
311 168 : if (carry) {
312 0 : FAIL(TOTAL_DIFF_OVERFLOW);
313 : }
314 :
315 168 : LOG_BIGD_HEX("Min required difficulty = ",
316 : MIN_REQUIRED_DIFFICULTY,
317 : BIGINT_LEN,
318 : "\n");
319 168 : LOG_BIGD_HEX(
320 : "Total difficulty = ", aux_bc_st.total_difficulty, BIGINT_LEN, "\n");
321 168 : LOG("Comparison: %d\n",
322 : mpCompare_ct(
323 : aux_bc_st.total_difficulty, MIN_REQUIRED_DIFFICULTY, BIGINT_LEN));
324 :
325 : // Not enough difficulty yet: we are done
326 168 : if (mpCompare_ct(aux_bc_st.total_difficulty,
327 : MIN_REQUIRED_DIFFICULTY,
328 : BIGINT_LEN) < 0) {
329 164 : return;
330 : }
331 :
332 : // Enough difficulty accumulated? We found our best block!
333 4 : bc_st_updating.found_best_block = true;
334 4 : HSTORE(bc_st_updating.best_block, block.main_block_hash);
335 : }
336 :
337 : /*
338 : * State updates to perform when successfully advanced blockchain.
339 : */
340 3 : static void bc_adv_success() {
341 3 : NVM_WRITE(N_bc_state.best_block, bc_st_updating.best_block, HASH_SIZE);
342 3 : NVM_WRITE(N_bc_state.newest_valid_block,
343 : bc_st_updating.newest_valid_block,
344 : HASH_SIZE);
345 3 : RESET_BC_STATE();
346 3 : }
347 :
348 : /*
349 : * State updates to perform on partial sucess.
350 : */
351 24 : static void bc_adv_partial_success() {
352 24 : HSTORE(bc_st_updating.next_expected_block, aux_bc_st.prev_parent_hash);
353 24 : SAFE_MEMMOVE(bc_st_updating.total_difficulty,
354 : sizeof(bc_st_updating.total_difficulty),
355 : MEMMOVE_ZERO_OFFSET,
356 : aux_bc_st.total_difficulty,
357 : sizeof(aux_bc_st.total_difficulty),
358 : MEMMOVE_ZERO_OFFSET,
359 : sizeof(aux_bc_st.total_difficulty),
360 : FAIL(BUFFER_OVERFLOW));
361 24 : }
362 :
363 : /*
364 : * We have received the whole BTC merge mining header. We can:
365 : * - Perform advance blockchain validations
366 : * - Check that merge mining header matches block's difficulty
367 : * - Finish block.hash_for_mm computation
368 : */
369 294 : static void bc_mm_header_received() {
370 294 : if (PROCESSING_BLOCK()) {
371 : // First block: perform blockchain advance prologue
372 : // Otherwise: verify block chains to parent
373 275 : if (curr_block == 0) {
374 34 : bc_adv_prologue();
375 241 : } else if (HNEQ(aux_bc_st.prev_parent_hash, block.block_hash)) {
376 0 : LOG_HEX("PAR", aux_bc_st.prev_parent_hash, HASH_LENGTH);
377 0 : LOG_HEX("BLK", block.block_hash, HASH_LENGTH);
378 0 : FAIL(CHAIN_MISMATCH);
379 : }
380 : // Store parent hash to validate chaining for next block
381 : // (next block hash must match this block's parent hash)
382 275 : HSTORE(aux_bc_st.prev_parent_hash, block.parent_hash);
383 :
384 : // Store block hash to validate against brothers
385 : // and use after we finished processing this block
386 275 : HSTORE(block.main_block_hash, block.block_hash);
387 :
388 : // If we already validated the current block, signal that.
389 275 : if (HEQ(block.block_hash, N_bc_state.newest_valid_block)) {
390 1 : bc_st_updating.already_validated = true;
391 : }
392 : }
393 :
394 : // If block is known to be valid, set HEADER_VALID flag.
395 : // Otherwise perform validations enabled by having the mm header.
396 : // This optimization is not valid for brothers, only for blocks
397 : // on the chain given that it depends on chaining.
398 294 : if (PROCESSING_BLOCK() && bc_st_updating.already_validated) {
399 2 : SET_FLAG(block.flags, HEADER_VALID);
400 : } else {
401 : // Check difficulty
402 292 : diff_result r = check_difficulty(block.difficulty, block.mm_hdr_hash);
403 292 : if (r == DIFF_ZERO) {
404 0 : FAIL(BLOCK_DIFF_INVALID);
405 : }
406 292 : if (r == DIFF_MISMATCH) {
407 1 : FAIL(BTC_DIFF_MISMATCH);
408 : }
409 :
410 : // Finish hash for merge mining computation
411 291 : patch_hash_for_mm(HAS_FLAG(block.flags, HAS_UMM_ROOT));
412 : }
413 293 : }
414 :
415 : // -----------------------------------------------------------------------
416 : // RLP parser callbacks
417 : // -----------------------------------------------------------------------
418 :
419 : // Valid blocks have the form [field_1, ..., field_n]. That is, a single
420 : // top level list with bytearrays inside. Anything not having this shape
421 : // is an invalid block.
422 :
423 : /*
424 : * Block starts: nesting level must not exceed one.
425 : *
426 : * @arg[in] size: size of list payload in bytes
427 : */
428 299 : static void list_start(const uint16_t size) {
429 299 : ++block.depth;
430 299 : if (block.depth != 1) {
431 0 : FAIL(RLP_INVALID);
432 : }
433 :
434 299 : block.size = size;
435 299 : block.recv = 0;
436 299 : }
437 :
438 : /*
439 : * List finishes: we must be closing the top level list, and received
440 : * bytes must match block size. In addition, we must have seen the
441 : * expected number of fields.
442 : */
443 291 : static void list_end() {
444 291 : --block.depth;
445 291 : if (block.depth != 0 || block.size != block.recv) {
446 0 : FAIL(RLP_INVALID);
447 : }
448 :
449 291 : if (block.field != F_COINBASE_TXN) {
450 0 : FAIL(BLOCK_TOO_SHORT);
451 : }
452 291 : }
453 :
454 : /*
455 : * Block field starts: field must be inside top level list.
456 : *
457 : * @arg[in] field size in bytes
458 : */
459 5955 : static void str_start(const uint16_t size) {
460 5955 : if (block.depth != 1) {
461 0 : FAIL(RLP_INVALID);
462 : }
463 :
464 5955 : block.wa_off = 0;
465 :
466 : // NOTE: This will return 1 even for a single byte "bad" string
467 : // where str[0] <= 0x7f (it should return 0). That's ok because
468 : // in that case we actually received a single byte. But we must
469 : // not add 1 to block.recv in str_chunk.
470 5955 : block.recv += guess_rlp_str_prefix_size(size);
471 :
472 : // Signal bad string
473 5955 : if (size == 1) {
474 627 : SET_FLAG(block.flags, BAD_STR);
475 : }
476 :
477 5955 : ++block.field;
478 :
479 5955 : if (block.field == F_PARENT_HASH && size != HASH_SIZE) {
480 0 : FAIL(PARENT_HASH_INVALID);
481 : }
482 :
483 : // UMM root field and papyrus active?
484 : // Validate length of UMM root (either zero or expected length) and
485 : // mark whether it's present so that we save it when we get the data.
486 5955 : if (block.network_upgrade >= NU_PAPYRUS && block.field == F_UMM_ROOT) {
487 298 : if (size != 0 && size != UMM_ROOT_SIZE) {
488 0 : FAIL(UMM_ROOT_INVALID);
489 : }
490 298 : if (size != 0) {
491 0 : SET_FLAG(block.flags, HAS_UMM_ROOT);
492 : }
493 : }
494 :
495 5955 : if (SHOULD_COMPUTE_BLOCK_HASH) {
496 : // The starting str contributes to the block (and possibly mm) hash
497 : // - Good string: we can hash RLP prefix right now.
498 : // - Bad string: RLP prefix will depend on str contents.
499 5365 : if (!HAS_FLAG(block.flags, BAD_STR)) {
500 4738 : mm_hash_good_rlp_str_prefix(&block.block_ctx, size);
501 4738 : WHEN_MM(mm_hash_good_rlp_str_prefix(&block.mm_ctx, size));
502 : }
503 : }
504 :
505 5955 : if (block.field == F_MM_HEADER && size != BTC_HEADER_SIZE) {
506 0 : FAIL(BTC_HEADER_INVALID);
507 : }
508 :
509 : // Prepare for the processing of the merkle proof
510 : // if we don't already know this block is valid
511 : // or we are processing a brother
512 5955 : if (block.field == F_MERKLE_PROOF && !BLOCK_ALREADY_VALID()) {
513 296 : if (size % HASH_SIZE != 0) {
514 0 : FAIL(MERKLE_PROOF_INVALID);
515 : }
516 296 : block.merkle_off = 0;
517 :
518 : // In preparation for the reduction of the merkle proof to the
519 : // merkle root, copy the coinbase transaction hash to the
520 : // reduction area
521 296 : SAFE_MEMMOVE(block.merkle_proof_left,
522 : sizeof(block.merkle_proof_left),
523 : MEMMOVE_ZERO_OFFSET,
524 : block.cb_txn_hash,
525 : sizeof(block.cb_txn_hash),
526 : MEMMOVE_ZERO_OFFSET,
527 : sizeof(block.cb_txn_hash),
528 : FAIL(MERKLE_PROOF_INVALID));
529 : }
530 :
531 5955 : if (block.field == F_COINBASE_TXN) {
532 : // size <= CB_MIDSTATE_DATA: txn has no tail
533 294 : if (size <= CB_MIDSTATE_DATA || size > MAX_CB_TXN_SIZE) {
534 0 : FAIL(BTC_CB_TXN_INVALID);
535 : }
536 294 : block.cb_off = 0;
537 : }
538 5955 : }
539 :
540 : /*
541 : * Block chunk arrived.
542 : *
543 : * @arg[in] chunk pointer to arrived chunk
544 : * @arg[in] size size in bytes of arrived chunk
545 : */
546 8497 : static void str_chunk(const uint8_t* chunk, const size_t size) {
547 : // Count chunk length as received bytes only if:
548 : // - Chunk doesn't belong to a bad string, or
549 : // - Bad string actually has RLP prefix
550 8497 : if (!HAS_FLAG(block.flags, BAD_STR) || HAS_RLP_PREFIX(chunk[0])) {
551 7870 : block.recv += size;
552 : }
553 :
554 8497 : if (block.field == F_PARENT_HASH) {
555 598 : WA_STORE(chunk, size);
556 : }
557 :
558 8497 : if (block.field == F_BLOCK_DIFF) {
559 596 : WA_STORE(chunk, size);
560 : }
561 :
562 8497 : if (block.field == F_BLOCK_NUM) {
563 596 : WA_STORE(chunk, size);
564 : }
565 :
566 8497 : if (block.field == F_MM_HEADER) {
567 1192 : WA_STORE(chunk, size);
568 : }
569 :
570 8497 : if (block.field == F_UMM_ROOT && HAS_FLAG(block.flags, HAS_UMM_ROOT)) {
571 0 : WA_STORE(chunk, size);
572 : }
573 :
574 8497 : if (block.field == F_MERKLE_PROOF && !BLOCK_ALREADY_VALID()) {
575 315 : process_merkle_proof(chunk, size);
576 : }
577 :
578 8497 : if (block.field == F_COINBASE_TXN) {
579 732 : store_cb_txn_bytes(chunk, size);
580 : }
581 :
582 8497 : if (SHOULD_COMPUTE_BLOCK_HASH) {
583 : // Chunk corresponds to a bad str, so we couldn't hash its RLP prefix
584 : // until now, when str contents are available. Hash prefix now.
585 7450 : if (HAS_FLAG(block.flags, BAD_STR)) {
586 627 : mm_hash_bad_rlp_str_prefix(&block.block_ctx, chunk);
587 627 : WHEN_MM(mm_hash_bad_rlp_str_prefix(&block.mm_ctx, chunk));
588 : }
589 :
590 : // And then hash the str chunk itself
591 7450 : KECCAK_UPDATE(&block.block_ctx, chunk, size);
592 7450 : WHEN_MM(KECCAK_UPDATE(&block.mm_ctx, chunk, size));
593 : }
594 8497 : }
595 :
596 : /* Current block chunk finished */
597 5951 : static void str_end() {
598 5951 : if (block.field == F_PARENT_HASH) {
599 299 : HSTORE(block.parent_hash, block.wa_buf);
600 :
601 : // If we're processing a brother, then its parent hash
602 : // must match the main block's parent hash
603 : // (i.e., validate they are actually brothers)
604 299 : if (!PROCESSING_BLOCK() &&
605 23 : HNEQ(aux_bc_st.prev_parent_hash, block.parent_hash)) {
606 1 : FAIL(BROTHER_PARENT_MISMATCH);
607 : }
608 : }
609 :
610 5950 : if (block.field == F_BLOCK_DIFF) {
611 298 : if (block.wa_off > MAX_DIFFICULTY_SIZE) {
612 0 : FAIL(BLOCK_DIFF_INVALID);
613 : }
614 298 : store_difficulty(block.wa_buf, block.wa_off, block.difficulty);
615 : }
616 :
617 : // Block number in wa_buf:
618 : // Store for computing mm_hash and determine network upgrade
619 5950 : if (block.field == F_BLOCK_NUM) {
620 298 : if (block.wa_off > sizeof(block.number)) {
621 0 : FAIL(BLOCK_NUM_INVALID);
622 : }
623 895 : VAR_BIGENDIAN_FROM(block.wa_buf, block.number, block.wa_off);
624 298 : SET_NETWORK_UPGRADE(block.number, &block.network_upgrade);
625 298 : if (block.network_upgrade == NU_ANCIENT) {
626 0 : FAIL(BLOCK_TOO_OLD);
627 : }
628 : }
629 :
630 5950 : if (block.field == MM_HASH_LAST_FIELD) {
631 298 : if (block.recv != block.mm_rlp_len) {
632 0 : FAIL(MM_RLP_LEN_MISMATCH);
633 : }
634 :
635 : // If there's a umm_root, we now have it in block.wa_buf. Store it.
636 298 : if (HAS_FLAG(block.flags, HAS_UMM_ROOT)) {
637 0 : if (block.wa_off != UMM_ROOT_SIZE) {
638 0 : FAIL(UMM_ROOT_INVALID);
639 : }
640 :
641 0 : SAFE_MEMMOVE(block.umm_root,
642 : sizeof(block.umm_root),
643 : MEMMOVE_ZERO_OFFSET,
644 : block.wa_buf,
645 : sizeof(block.wa_buf),
646 : MEMMOVE_ZERO_OFFSET,
647 : block.wa_off,
648 : FAIL(UMM_ROOT_INVALID));
649 : }
650 : }
651 :
652 : // We have the complete merge mining header in wa_buf. We must:
653 : // - Finalize block and hash_for_mm computation
654 : // - Store the Merkle root in block.merkle_root
655 : // - Compute btc mm hdr hash
656 : // - Signal the merge mining header was received
657 5950 : if (block.field == F_MM_HEADER) {
658 298 : KECCAK_FINAL(&block.block_ctx, block.block_hash);
659 :
660 : // Check that the brother is not the same as the main block
661 298 : if (!PROCESSING_BLOCK() &&
662 22 : HEQ(block.main_block_hash, block.block_hash)) {
663 1 : FAIL(BROTHER_SAME_AS_BLOCK);
664 : }
665 :
666 : // Check that the brothers are sent in ascending order
667 : // wrt their block hash
668 297 : if (!PROCESSING_BLOCK() &&
669 21 : !HLT(block.prev_brother_hash, block.block_hash)) {
670 1 : FAIL(BROTHER_ORDER_INVALID);
671 : }
672 :
673 296 : KECCAK_FINAL(&block.mm_ctx, block.hash_for_mm);
674 296 : HSTORE(block.merkle_root, block.wa_buf + MERKLE_ROOT_OFFSET);
675 :
676 : // If we haven't reached a valid block while descending the chain,
677 : // we need to compute the btc mm header hash to then do the difficulty
678 : // validation. We do this here because if within this part of the RLP
679 : // processing there's also a portion of the mm merkle proof, then the
680 : // wa_buf will be overwritten.
681 : // We also always do this in case we are processing a brother
682 296 : if (!PROCESSING_BLOCK() || !bc_st_updating.already_validated) {
683 : // Compute merge mining header hash
684 295 : double_sha256_rev(
685 : &block.ctx, block.wa_buf, BTC_HEADER_SIZE, block.mm_hdr_hash);
686 : }
687 :
688 296 : SET_FLAG(block.flags, MM_HEADER_RECV);
689 : }
690 :
691 : // We have finished processing the merkle proof.
692 : // Validate the reduction against the stored coinbase
693 : // transaction hash.
694 : // All this given that the block hasn't been marked as valid and is not a
695 : // brother.
696 5948 : if (block.field == F_MERKLE_PROOF && !BLOCK_ALREADY_VALID()) {
697 295 : validate_merkle_proof();
698 : }
699 :
700 5947 : if (block.field == F_COINBASE_TXN) {
701 291 : SET_FLAG(block.flags, CB_TXN_RECV);
702 : }
703 :
704 : // Done with this chunk, clear BAD_STR flag if set
705 5947 : if (HAS_FLAG(block.flags, BAD_STR)) {
706 627 : CLR_FLAG(block.flags, BAD_STR);
707 : }
708 5947 : }
709 :
710 : static const rlp_callbacks_t callbacks = {
711 : str_start,
712 : str_chunk,
713 : str_end,
714 : list_start,
715 : list_end,
716 : };
717 :
718 268 : static unsigned int handle_end_of_block() {
719 : // Successfully advanced the blockchain: leave with success
720 268 : if (bc_st_updating.found_best_block &&
721 128 : HEQ(N_bc_state.best_block, aux_bc_st.prev_parent_hash)) {
722 3 : bc_adv_success();
723 3 : expected_state = OP_ADVANCE_INIT;
724 3 : SET_APDU_OP(OP_ADVANCE_SUCCESS);
725 3 : return TX_NO_DATA();
726 : }
727 :
728 : // Current block valid, yet no success.
729 : // If no more blocks available, leave with partial success
730 265 : ++curr_block;
731 265 : if (curr_block == expected_blocks) {
732 24 : bc_adv_partial_success();
733 24 : expected_state = OP_ADVANCE_INIT;
734 24 : SET_APDU_OP(OP_ADVANCE_PARTIAL);
735 24 : return TX_NO_DATA();
736 : }
737 :
738 : // Current block valid, yet no success.
739 : // More blocks available, ask for them and continue.
740 241 : expected_state = OP_ADVANCE_HEADER_META;
741 241 : SET_APDU_OP(OP_ADVANCE_HEADER_META);
742 241 : return TX_NO_DATA();
743 : }
744 :
745 : // -----------------------------------------------------------------------
746 : // Blockchain advance protocol implementation
747 : // -----------------------------------------------------------------------
748 :
749 : /*
750 : * Initialize Blockchain advance protocol state.
751 : */
752 270 : void bc_init_advance() {
753 270 : expected_blocks = 0;
754 270 : curr_block = 0;
755 270 : expected_state = OP_ADVANCE_INIT;
756 270 : }
757 :
758 : /*
759 : * Advance blockchain state.
760 : *
761 : * @arg[in] rx number of received bytes from the Host
762 : * @ret number of transmited bytes to the host
763 : */
764 3324 : unsigned int bc_advance(volatile unsigned int rx) {
765 3324 : uint8_t op = APDU_OP();
766 :
767 : // Check we are getting expected OP
768 3324 : if (op != OP_ADVANCE_INIT && op != expected_state) {
769 0 : FAIL(PROT_INVALID);
770 : }
771 :
772 : // Check we are getting the expected amount of data
773 3324 : if (op == OP_ADVANCE_INIT && APDU_DATA_SIZE(rx) != sizeof(uint32_t)) {
774 0 : FAIL(PROT_INVALID);
775 : }
776 3324 : if ((op == OP_ADVANCE_HEADER_META || op == OP_ADVANCE_BROTHER_META) &&
777 299 : APDU_DATA_SIZE(rx) !=
778 : (sizeof(block.mm_rlp_len) + sizeof(block.cb_txn_hash))) {
779 0 : FAIL(PROT_INVALID);
780 : }
781 3324 : if (op == OP_ADVANCE_BROTHER_LIST_META &&
782 148 : APDU_DATA_SIZE(rx) != sizeof(block.brother_count)) {
783 0 : FAIL(PROT_INVALID);
784 : }
785 3324 : if (op == OP_ADVANCE_HEADER_CHUNK || op == OP_ADVANCE_BROTHER_CHUNK) {
786 299 : uint16_t expected_txlen =
787 2842 : block.size > 0 ? MIN(block.size - block.recv, MAX_CHUNK_SIZE)
788 : : MAX_CHUNK_SIZE;
789 2842 : if (APDU_DATA_SIZE(rx) != expected_txlen) {
790 0 : FAIL(PROT_INVALID);
791 : }
792 : }
793 :
794 : // -------------------------------------------------------------------
795 : // OP_INIT
796 : // -------------------------------------------------------------------
797 3324 : if (op == OP_ADVANCE_INIT) {
798 35 : expected_state = OP_ADVANCE_HEADER_META;
799 :
800 35 : memset(aux_bc_st.prev_parent_hash, 0, HASH_SIZE);
801 35 : SAFE_MEMMOVE(aux_bc_st.total_difficulty,
802 : sizeof(aux_bc_st.total_difficulty),
803 : MEMMOVE_ZERO_OFFSET,
804 : bc_st_updating.total_difficulty,
805 : sizeof(bc_st_updating.total_difficulty),
806 : MEMMOVE_ZERO_OFFSET,
807 : sizeof(aux_bc_st.total_difficulty),
808 : FAIL(PROT_INVALID));
809 :
810 35 : curr_block = 0;
811 175 : BIGENDIAN_FROM(APDU_DATA_PTR, expected_blocks);
812 35 : if (expected_blocks == 0) {
813 0 : FAIL(PROT_INVALID);
814 : }
815 :
816 35 : SET_APDU_OP(OP_ADVANCE_HEADER_META);
817 35 : return TX_NO_DATA();
818 : }
819 :
820 : // -------------------------------------------------------------------
821 : // OP_BROTHER_LIST_META
822 : // -------------------------------------------------------------------
823 3289 : if (op == OP_ADVANCE_BROTHER_LIST_META) {
824 : // Read the brother count
825 296 : BIGENDIAN_FROM(APDU_DATA_PTR, block.brother_count);
826 :
827 : // No brothers? => we've finished processing the current block
828 148 : if (!block.brother_count) {
829 137 : return handle_end_of_block();
830 : }
831 :
832 : // Validate brother count
833 11 : if (block.brother_count > MAX_BROTHERS) {
834 1 : LOG("Too many brothers");
835 1 : FAIL(BROTHERS_TOO_MANY);
836 : }
837 :
838 : // Set previous brother hash to initial value
839 10 : memset(block.prev_brother_hash, 0, sizeof(block.prev_brother_hash));
840 :
841 : // Now expecting the first brother's meta
842 10 : expected_state = OP_ADVANCE_BROTHER_META;
843 10 : SET_APDU_OP(OP_ADVANCE_BROTHER_META);
844 10 : return TX_NO_DATA();
845 : }
846 :
847 : // -------------------------------------------------------------------
848 : // OP_HEADER_META or OP_BROTHER_META
849 : // -------------------------------------------------------------------
850 3141 : if (op == OP_ADVANCE_HEADER_META || op == OP_ADVANCE_BROTHER_META) {
851 299 : if (PROCESSING_BLOCK()) {
852 276 : LOG("---- Block %u of %u\n", curr_block + 1, expected_blocks);
853 :
854 : // Clear block data
855 276 : memset(&block, 0, sizeof(block));
856 : } else { // Processing brother
857 23 : LOG("---- Brother (%u remaining)\n", block.brother_count);
858 :
859 : // Init brother header data
860 : // (keep some of the current block data)
861 23 : block.size = 0;
862 23 : block.recv = 0;
863 23 : block.field = 0;
864 23 : block.depth = 0;
865 23 : block.flags = 0;
866 : }
867 : // Init RLP parser
868 299 : rlp_start(&callbacks);
869 :
870 : // Network upgrade unknown until we get to the block number
871 299 : block.network_upgrade = NU_UNKNOWN;
872 :
873 : // Read the RLP payload length
874 897 : BIGENDIAN_FROM(APDU_DATA_PTR, block.mm_rlp_len);
875 :
876 : // Read the coinbase transaction hash
877 598 : SAFE_MEMMOVE(block.cb_txn_hash,
878 : sizeof(block.cb_txn_hash),
879 : MEMMOVE_ZERO_OFFSET,
880 : APDU_DATA_PTR,
881 : APDU_TOTAL_DATA_SIZE,
882 : sizeof(block.mm_rlp_len),
883 : sizeof(block.cb_txn_hash),
884 : FAIL(PROT_INVALID));
885 :
886 : // Block hash computation: encode and hash payload len
887 : // (mm payload len + BTC header len)
888 : // Sanity check: make sure given mm_rlp_len plus BTC_HEADER_RLP_LEN does
889 : // not overflow
890 299 : if ((uint16_t)(block.mm_rlp_len + BTC_HEADER_RLP_LEN) <
891 : block.mm_rlp_len) {
892 0 : LOG("Given MM RLP list length too large, would overflow: %u\n",
893 0 : block.mm_rlp_len);
894 0 : FAIL(PROT_INVALID);
895 : }
896 :
897 299 : KECCAK_INIT(&block.block_ctx);
898 299 : mm_hash_rlp_list_prefix(&block.block_ctx,
899 299 : block.mm_rlp_len + BTC_HEADER_RLP_LEN);
900 :
901 : // Merge mining hash computation: encode and hash mm_rlp_payload_len
902 299 : KECCAK_INIT(&block.mm_ctx);
903 299 : mm_hash_rlp_list_prefix(&block.mm_ctx, block.mm_rlp_len);
904 :
905 : // Now waiting for either block or brother data
906 299 : expected_state = PROCESSING_BLOCK() ? OP_ADVANCE_HEADER_CHUNK
907 : : OP_ADVANCE_BROTHER_CHUNK;
908 299 : SET_APDU_OP(expected_state);
909 299 : SET_APDU_TXLEN(MAX_CHUNK_SIZE);
910 :
911 299 : return TX_FOR_DATA_SIZE(1);
912 : }
913 :
914 : // -------------------------------------------------------------------
915 : // OP_HEADER_CHUNK || OP_BROTHER_CHUNK
916 : // -------------------------------------------------------------------
917 2842 : if (op == OP_ADVANCE_HEADER_CHUNK || op == OP_ADVANCE_BROTHER_CHUNK) {
918 2842 : if (rlp_consume(APDU_DATA_PTR, APDU_DATA_SIZE(rx)) < 0) {
919 1 : FAIL(RLP_INVALID);
920 : }
921 :
922 : // Check flags. Don't forget to reset them, or they
923 : // will activated on successive chunks!
924 :
925 : // Do validations after full BTC MM header is received
926 2837 : if (HAS_FLAG(block.flags, MM_HEADER_RECV)) {
927 294 : CLR_FLAG(block.flags, MM_HEADER_RECV);
928 294 : bc_mm_header_received();
929 : }
930 :
931 : // We have received the whole coinbase transaction.
932 : // Provided the block is not valid, we can:
933 : // - Extract the cb_txn_hash
934 : // - Validate it against the metadata given cb txn hash
935 : // - Extract mm_hash and compare it with hash_for_mm
936 : //
937 : // This completes the current block's validation
938 2836 : if (HAS_FLAG(block.flags, CB_TXN_RECV) &&
939 291 : !HAS_FLAG(block.flags, HEADER_VALID)) {
940 291 : CLR_FLAG(block.flags, CB_TXN_RECV);
941 291 : compute_cb_txn_hash();
942 291 : validate_cb_txn_hash();
943 291 : validate_mm_hash();
944 290 : SET_FLAG(block.flags, HEADER_VALID);
945 : }
946 :
947 : // We know this block is valid
948 2835 : if (HAS_FLAG(block.flags, HEADER_VALID)) {
949 : // Since we have a valid block, we can accumulate difficulty.
950 : // This will set updating.found_best_block if we accumulated
951 : // enough difficulty.
952 292 : bc_adv_accum_diff();
953 :
954 292 : if (PROCESSING_BLOCK()) {
955 : // If we haven't yet found our new best block,
956 : // then request any brothers of this block
957 : // in order to accumulate their difficulty too
958 275 : if (!bc_st_updating.found_best_block) {
959 : // Request brother list meta information
960 148 : expected_state = OP_ADVANCE_BROTHER_LIST_META;
961 148 : SET_APDU_OP(OP_ADVANCE_BROTHER_LIST_META);
962 148 : SET_APDU_TXLEN(0);
963 :
964 148 : return TX_NO_DATA();
965 : }
966 :
967 127 : return handle_end_of_block();
968 : } else { // Processing brother
969 : // Have we finished parsing this brother?
970 17 : if (block.size == block.recv) {
971 17 : --block.brother_count;
972 :
973 : // Have we finished parsing all the brothers?
974 17 : if (!block.brother_count) {
975 4 : return handle_end_of_block();
976 : }
977 :
978 : // Remember this brother's hash to
979 : // compare against the next one
980 13 : HSTORE(block.prev_brother_hash, block.block_hash);
981 :
982 : // Request next brother meta
983 13 : expected_state = OP_ADVANCE_BROTHER_META;
984 13 : SET_APDU_OP(OP_ADVANCE_BROTHER_META);
985 13 : SET_APDU_TXLEN(0);
986 13 : return TX_NO_DATA();
987 : }
988 : }
989 : }
990 :
991 : // Current block header not exhausted, ask for next chunk
992 2543 : expected_state = (op == OP_ADVANCE_HEADER_CHUNK)
993 : ? OP_ADVANCE_HEADER_CHUNK
994 : : OP_ADVANCE_BROTHER_CHUNK;
995 2543 : SET_APDU_OP(expected_state);
996 2543 : SET_APDU_TXLEN(MIN(block.size - block.recv, MAX_CHUNK_SIZE));
997 2543 : return TX_FOR_DATA_SIZE(1);
998 : }
999 :
1000 : // You shouldn't be here
1001 0 : FAIL(PROT_INVALID);
1002 : return 0;
1003 : }
1004 :
1005 : // -----------------------------------------------------------------------
1006 : // Blockchain advance protocol precompiled parameters dumping
1007 : // -----------------------------------------------------------------------
1008 :
1009 : /*
1010 : * Dump minimum required difficulty to the specified APDU buffer data offset.
1011 : * This function will copy to the the buffer the bytes comprising the
1012 : * precompiled minimum cumulative difficulty in big endian order,
1013 : * including leading zeroes.
1014 : *
1015 : * @arg[in] offset APDU buffer data dump offset
1016 : * @ret number of bytes dumped to APDU buffer
1017 : */
1018 1 : static uint8_t dump_min_req_difficulty(int offset) {
1019 : // Make sure the minimum required difficulty fits into the output buffer
1020 1 : if (APDU_TOTAL_DATA_SIZE_OUT < sizeof(MIN_REQUIRED_DIFFICULTY) + offset)
1021 0 : FAIL(BUFFER_OVERFLOW);
1022 1 : dump_bigint_be(APDU_DATA_PTR + offset, MIN_REQUIRED_DIFFICULTY, BIGINT_LEN);
1023 1 : return sizeof(MIN_REQUIRED_DIFFICULTY);
1024 : }
1025 :
1026 : /*
1027 : * Get advance blockchain protocol precompiled parameters.
1028 : * Dump format:
1029 : * Bytes 0-31: initial block hash
1030 : * Bytes 32-67: minimum required difficulty (big endian)
1031 : * Byte 68: network identifier (see bc_nu.h for the definition)
1032 : *
1033 : * @ret number of transmited bytes to the host
1034 : */
1035 1 : unsigned int bc_advance_get_params() {
1036 1 : int dump_size = 0;
1037 1 : dump_size += bc_dump_initial_block_hash(0);
1038 1 : dump_size += dump_min_req_difficulty(dump_size);
1039 1 : APDU_DATA_PTR[dump_size++] = GET_NETWORK_IDENTIFIER();
1040 :
1041 1 : return TX_FOR_DATA_SIZE(dump_size);
1042 : }
|