void ab() { /* * Test a `inclusive-or` b: * This should produce the following automaton: * * = (prefix*(a) || b) | (a || prefix*(b)) | (a || b) * = (ø || b | (a || ø | (a || b) * = b | a | ab | ba * * CHECK: digraph automaton_{{[0-9]+}} */ int x, y; TESLA_PERTHREAD(strict(call(ab)), strict(returnfrom(ab)), strict(a(x) == 0 || b(y) == 0)); /* * Transitions, grouped into equivalence classes: * * ab(): 0->1 * CHECKX: label = "ab(){{.*}}Entry{{.*}}init{{.*}} * CHECKX: 0 -> [[CALL:[0-9]+]] * * a(x): [ 2->4, 5->7 ] * CHECKX: label = "a(x) * CHECKX: [[INIT1:[0-9]+]] -> [[A1:[0-9]+]] * CHECKX: [[B1:[0-9]+]] -> [[A2:[0-9]+]] * * b(y): [ 3->5, 4->7 ] * CHECKX: label = "b(y) * CHECKX: [[INIT2:[0-9]+]] -> [[B1]] * CHECKX: [[A1]] -> [[A2]] * * ø: [ 5->6, 4->6, 7->6, 1->2, 1->3 ] * CHECKX: label = "[[EPSILON:&#[0-9a-f]+;]]" * CHECKX: [[B1]] -> [[FINAL:[0-9]+]] * CHECKX: [[A1]] -> [[FINAL]] * CHECKX: [[CALL]] -> [[INIT2]] * CHECKX: [[A2]] -> [[FINAL]] * CHECKX: [[CALL]] -> [[INIT1]] */ /* * Graph footer: * CHECKX: label = "{{.*inclusive-or.c:[0-9]+#[0-9]+}} */ }
std::error_code organizer_impl::verify(size_t fork_point, const block_detail_list& orphan_chain, size_t orphan_index) { BITCOIN_ASSERT(orphan_index < orphan_chain.size()); const auto& current_block = orphan_chain[orphan_index]->actual(); const size_t height = fork_point + orphan_index + 1; BITCOIN_ASSERT(height != 0); validate_block_impl validate(interface_, fork_point, orphan_chain, orphan_index, height, current_block, checkpoints_); // Checks that are independent of the chain. auto ec = validate.check_block(); if (ec) return ec; // Checks that are dependent on height and preceding blocks. ec = validate.accept_block(); if (ec) return ec; // Start strict validation if past last checkpoint. if (strict(fork_point)) { const auto total_inputs = count_inputs(current_block); const auto total_transactions = current_block.transactions.size(); log_info(LOG_BLOCKCHAIN) << "Block [" << height << "] verify (" << total_transactions << ") txs and (" << total_inputs << ") inputs"; // Time this for logging. const auto timed = [&ec, &validate]() { // Checks that include input->output traversal. ec = validate.connect_block(); }; // Execute the timed validation. const auto elapsed = timer<std::chrono::milliseconds>::duration(timed); const auto ms_per_block = static_cast<float>(elapsed.count()); const auto ms_per_input = ms_per_block / total_inputs; const auto secs_per_block = ms_per_block / 1000; const auto verified = ec ? "unverified" : "verified"; log_info(LOG_BLOCKCHAIN) << "Block [" << height << "] " << verified << " in (" << secs_per_block << ") secs or (" << ms_per_input << ") ms/input"; } return ec; }