Block builder (#1451)
This commit is contained in:
parent
49a339babb
commit
5fb4617b45
11 changed files with 1264 additions and 0 deletions
|
@ -3,6 +3,7 @@
|
|||
#include <fstream>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <rai/core_test/testutil.hpp>
|
||||
|
||||
#include <rai/lib/interface.h>
|
||||
#include <rai/node/common.hpp>
|
||||
|
@ -452,3 +453,239 @@ TEST (block_uniquer, cleanup)
|
|||
ASSERT_LT (iterations++, 200);
|
||||
}
|
||||
}
|
||||
|
||||
TEST (block_builder, zeroed_state_block)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
rai::keypair key;
|
||||
// Make sure manually- and builder constructed all-zero blocks have equal hashes, and check signature.
|
||||
auto zero_block_manual (std::make_shared<rai::state_block> (0, 0, 0, 0, 0, key.prv, key.pub, 0));
|
||||
auto zero_block_build = builder.state ().zero ().sign (key.prv, key.pub).build ();
|
||||
ASSERT_TRUE (zero_block_manual->hash () == zero_block_build->hash ());
|
||||
ASSERT_FALSE (rai::validate_message (key.pub, zero_block_build->hash (), zero_block_build->signature));
|
||||
}
|
||||
|
||||
TEST (block_builder, state)
|
||||
{
|
||||
// Test against a random hash from the live network
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
auto block = builder
|
||||
.state ()
|
||||
.account_address ("xrb_15nhh1kzw3x8ohez6s75wy3jr6dqgq65oaede1fzk5hqxk4j8ehz7iqtb3to")
|
||||
.previous_hex ("FEFBCE274E75148AB31FF63EFB3082EF1126BF72BF3FA9C76A97FD5A9F0EBEC5")
|
||||
.balance_dec ("2251569974100400000000000000000000")
|
||||
.representative_address ("xrb_1stofnrxuz3cai7ze75o174bpm7scwj9jn3nxsn8ntzg784jf1gzn1jjdkou")
|
||||
.link_hex ("E16DD58C1EFA8B521545B0A74375AA994D9FC43828A4266D75ECF57F07A7EE86")
|
||||
.build (ec);
|
||||
ASSERT_EQ (block->hash ().to_string (), "2D243F8F92CDD0AD94A1D456A6B15F3BE7A6FCBD98D4C5831D06D15C818CD81F");
|
||||
}
|
||||
|
||||
TEST (block_builder, state_missing_rep)
|
||||
{
|
||||
// Test against a random hash from the live network
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
auto block = builder
|
||||
.state ()
|
||||
.account_address ("xrb_15nhh1kzw3x8ohez6s75wy3jr6dqgq65oaede1fzk5hqxk4j8ehz7iqtb3to")
|
||||
.previous_hex ("FEFBCE274E75148AB31FF63EFB3082EF1126BF72BF3FA9C76A97FD5A9F0EBEC5")
|
||||
.balance_dec ("2251569974100400000000000000000000")
|
||||
.link_hex ("E16DD58C1EFA8B521545B0A74375AA994D9FC43828A4266D75ECF57F07A7EE86")
|
||||
.sign_zero ()
|
||||
.work (0)
|
||||
.build (ec);
|
||||
ASSERT_EQ (ec, nano::error_common::missing_representative);
|
||||
}
|
||||
|
||||
TEST (block_builder, state_equality)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
|
||||
// With constructor
|
||||
rai::keypair key1, key2;
|
||||
rai::state_block block1 (key1.pub, 1, key2.pub, 2, 4, key1.prv, key1.pub, 5);
|
||||
|
||||
// With builder
|
||||
auto block2 = builder
|
||||
.state ()
|
||||
.account (key1.pub)
|
||||
.previous (1)
|
||||
.representative (key2.pub)
|
||||
.balance (2)
|
||||
.link (4)
|
||||
.sign (key1.prv, key1.pub)
|
||||
.work (5)
|
||||
.build (ec);
|
||||
|
||||
ASSERT_NO_ERROR (ec);
|
||||
ASSERT_EQ (block1.hash (), block2->hash ());
|
||||
ASSERT_EQ (block1.work, block2->work);
|
||||
}
|
||||
|
||||
TEST (block_builder, state_errors)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
|
||||
// Make sure we assert when building a block without an std::error_code
|
||||
EXPECT_DEATH (builder
|
||||
.state ()
|
||||
.account_hex ("xyz")
|
||||
.build (),
|
||||
".*");
|
||||
|
||||
// Ensure the proper error is generated
|
||||
builder.state ().account_hex ("xrb_bad").build (ec);
|
||||
ASSERT_EQ (ec, nano::error_common::bad_account_number);
|
||||
|
||||
builder.state ().zero ().account_address ("xrb_1111111111111111111111111111111111111111111111111111hifc8npp").build (ec);
|
||||
ASSERT_NO_ERROR (ec);
|
||||
}
|
||||
|
||||
TEST (block_builder, open)
|
||||
{
|
||||
// Test built block's hash against the Genesis open block from the live network
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
auto block = builder
|
||||
.open ()
|
||||
.account_address ("xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3")
|
||||
.representative_address ("xrb_3t6k35gi95xu6tergt6p69ck76ogmitsa8mnijtpxm9fkcm736xtoncuohr3")
|
||||
.source_hex ("E89208DD038FBB269987689621D52292AE9C35941A7484756ECCED92A65093BA")
|
||||
.build (ec);
|
||||
ASSERT_EQ (block->hash ().to_string (), "991CF190094C00F0B68E2E5F75F6BEE95A2E0BD93CEAA4A6734DB9F19B728948");
|
||||
}
|
||||
|
||||
TEST (block_builder, open_equality)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
|
||||
// With constructor
|
||||
rai::keypair key1, key2;
|
||||
rai::open_block block1 (1, key1.pub, key2.pub, key1.prv, key1.pub, 5);
|
||||
|
||||
// With builder
|
||||
auto block2 = builder
|
||||
.open ()
|
||||
.source (1)
|
||||
.account (key2.pub)
|
||||
.representative (key1.pub)
|
||||
.sign (key1.prv, key1.pub)
|
||||
.work (5)
|
||||
.build (ec);
|
||||
|
||||
ASSERT_NO_ERROR (ec);
|
||||
ASSERT_EQ (block1.hash (), block2->hash ());
|
||||
ASSERT_EQ (block1.work, block2->work);
|
||||
}
|
||||
|
||||
TEST (block_builder, change)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
auto block = builder
|
||||
.change ()
|
||||
.representative_address ("xrb_3rropjiqfxpmrrkooej4qtmm1pueu36f9ghinpho4esfdor8785a455d16nf")
|
||||
.previous_hex ("088EE46429CA936F76C4EAA20B97F6D33E5D872971433EE0C1311BCB98764456")
|
||||
.build (ec);
|
||||
ASSERT_EQ (block->hash ().to_string (), "13552AC3928E93B5C6C215F61879358E248D4A5246B8B3D1EEC5A566EDCEE077");
|
||||
}
|
||||
|
||||
TEST (block_builder, change_equality)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
|
||||
// With constructor
|
||||
rai::keypair key1, key2;
|
||||
rai::change_block block1 (1, key1.pub, key1.prv, key1.pub, 5);
|
||||
|
||||
// With builder
|
||||
auto block2 = builder
|
||||
.change ()
|
||||
.previous (1)
|
||||
.representative (key1.pub)
|
||||
.sign (key1.prv, key1.pub)
|
||||
.work (5)
|
||||
.build (ec);
|
||||
|
||||
ASSERT_NO_ERROR (ec);
|
||||
ASSERT_EQ (block1.hash (), block2->hash ());
|
||||
ASSERT_EQ (block1.work, block2->work);
|
||||
}
|
||||
|
||||
TEST (block_builder, send)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
auto block = builder
|
||||
.send ()
|
||||
.destination_address ("xrb_1gys8r4crpxhp94n4uho5cshaho81na6454qni5gu9n53gksoyy1wcd4udyb")
|
||||
.previous_hex ("F685856D73A488894F7F3A62BC3A88E17E985F9969629FF3FDD4A0D4FD823F24")
|
||||
.balance_hex ("00F035A9C7D818E7C34148C524FFFFEE")
|
||||
.build (ec);
|
||||
ASSERT_EQ (block->hash ().to_string (), "4560E7B1F3735D082700CFC2852F5D1F378F7418FD24CEF1AD45AB69316F15CD");
|
||||
}
|
||||
|
||||
TEST (block_builder, send_equality)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
|
||||
// With constructor
|
||||
rai::keypair key1, key2;
|
||||
rai::send_block block1 (1, key1.pub, 2, key1.prv, key1.pub, 5);
|
||||
|
||||
// With builder
|
||||
auto block2 = builder
|
||||
.send ()
|
||||
.previous (1)
|
||||
.destination (key1.pub)
|
||||
.balance (2)
|
||||
.sign (key1.prv, key1.pub)
|
||||
.work (5)
|
||||
.build (ec);
|
||||
|
||||
ASSERT_NO_ERROR (ec);
|
||||
ASSERT_EQ (block1.hash (), block2->hash ());
|
||||
ASSERT_EQ (block1.work, block2->work);
|
||||
}
|
||||
|
||||
TEST (block_builder, receive_equality)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
|
||||
// With constructor
|
||||
rai::keypair key1;
|
||||
rai::receive_block block1 (1, 2, key1.prv, key1.pub, 5);
|
||||
|
||||
// With builder
|
||||
auto block2 = builder
|
||||
.receive ()
|
||||
.previous (1)
|
||||
.source (2)
|
||||
.sign (key1.prv, key1.pub)
|
||||
.work (5)
|
||||
.build (ec);
|
||||
|
||||
ASSERT_NO_ERROR (ec);
|
||||
ASSERT_EQ (block1.hash (), block2->hash ());
|
||||
ASSERT_EQ (block1.work, block2->work);
|
||||
}
|
||||
|
||||
TEST (block_builder, receive)
|
||||
{
|
||||
std::error_code ec;
|
||||
rai::block_builder builder;
|
||||
auto block = builder
|
||||
.receive ()
|
||||
.previous_hex ("59660153194CAC5DAC08509D87970BF86F6AEA943025E2A7ED7460930594950E")
|
||||
.source_hex ("7B2B0A29C1B235FDF9B4DEF2984BB3573BD1A52D28246396FBB3E4C5FE662135")
|
||||
.build (ec);
|
||||
ASSERT_EQ (block->hash ().to_string (), "6C004BF911D9CF2ED75CF6EC45E795122AD5D093FF5A83EDFBA43EC4A3EDC722");
|
||||
}
|
||||
|
|
|
@ -13,3 +13,8 @@
|
|||
#define ASSERT_NO_ERROR(condition) \
|
||||
GTEST_TEST_ERROR_CODE (!(condition), #condition, condition.message ().c_str (), "", \
|
||||
GTEST_FATAL_FAILURE_)
|
||||
|
||||
/** Extends gtest with a std::error_code assert that expects an error */
|
||||
#define ASSERT_IS_ERROR(condition) \
|
||||
GTEST_TEST_ERROR_CODE ((condition.value () > 0), #condition, "An error was expected", "", \
|
||||
GTEST_FATAL_FAILURE_)
|
||||
|
|
|
@ -15,6 +15,8 @@ add_library (rai_lib
|
|||
errors.hpp
|
||||
errors.cpp
|
||||
expected.hpp
|
||||
blockbuilders.cpp
|
||||
blockbuilders.hpp
|
||||
blocks.cpp
|
||||
blocks.hpp
|
||||
config.hpp
|
||||
|
|
632
rai/lib/blockbuilders.cpp
Normal file
632
rai/lib/blockbuilders.cpp
Normal file
|
@ -0,0 +1,632 @@
|
|||
#include <cryptopp/osrng.h>
|
||||
#include <rai/lib/blockbuilders.hpp>
|
||||
#include <rai/secure/common.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <typename BLOCKTYPE>
|
||||
void previous_hex_impl (std::string const & previous_hex, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::block_hash previous;
|
||||
if (!previous.decode_hex (previous_hex))
|
||||
{
|
||||
block->hashables.previous = previous;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_previous;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void account_hex_impl (std::string const & account_hex, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::account account;
|
||||
if (!account.decode_hex (account_hex))
|
||||
{
|
||||
block->hashables.account = account;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_account_number;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void account_address_impl (std::string const & address, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::account account;
|
||||
if (!account.decode_account (address))
|
||||
{
|
||||
block->hashables.account = account;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_account_number;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void representative_hex_impl (std::string const & account_hex, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::account account;
|
||||
if (!account.decode_hex (account_hex))
|
||||
{
|
||||
block->hashables.representative = account;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_representative_number;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void representative_address_impl (std::string const & address, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::account account;
|
||||
if (!account.decode_account (address))
|
||||
{
|
||||
block->hashables.representative = account;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_representative_number;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void destination_hex_impl (std::string const & account_hex, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::account account;
|
||||
if (!account.decode_hex (account_hex))
|
||||
{
|
||||
block->hashables.destination = account;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_account_number;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void destination_address_impl (std::string const & address, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::account account;
|
||||
if (!account.decode_account (address))
|
||||
{
|
||||
block->hashables.destination = account;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_account_number;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void source_hex_impl (std::string const & source_hex, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::block_hash source;
|
||||
if (!source.decode_hex (source_hex))
|
||||
{
|
||||
block->hashables.source = source;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_source;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void balance_dec_impl (std::string const & balance_decimal, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::amount balance;
|
||||
if (!balance.decode_dec (balance_decimal))
|
||||
{
|
||||
block->hashables.balance = balance;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_balance;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename BLOCKTYPE>
|
||||
void balance_hex_impl (std::string const & balance_hex, std::error_code & ec, BLOCKTYPE & block)
|
||||
{
|
||||
rai::amount balance;
|
||||
if (!balance.decode_hex (balance_hex))
|
||||
{
|
||||
block->hashables.balance = balance;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_balance;
|
||||
}
|
||||
}
|
||||
|
||||
/* The cost of looking up the error_code map is only taken if field-presence checks fail */
|
||||
std::unordered_map<uint8_t, std::error_code> ec_map = {
|
||||
{ static_cast<uint8_t> (rai::build_flags::account_present), nano::error_common::missing_account },
|
||||
{ static_cast<uint8_t> (rai::build_flags::balance_present), nano::error_common::missing_balance },
|
||||
{ static_cast<uint8_t> (rai::build_flags::link_present), nano::error_common::missing_link },
|
||||
{ static_cast<uint8_t> (rai::build_flags::previous_present), nano::error_common::missing_previous },
|
||||
{ static_cast<uint8_t> (rai::build_flags::representative_present), nano::error_common::missing_representative },
|
||||
{ static_cast<uint8_t> (rai::build_flags::signature_present), nano::error_common::missing_signature },
|
||||
{ static_cast<uint8_t> (rai::build_flags::work_present), nano::error_common::missing_work }
|
||||
};
|
||||
|
||||
/** Find first set bit as a mask, e.g. 10101000 => 0x08. Returns -1 if no bit is set. */
|
||||
inline signed ffs_mask (uint8_t num)
|
||||
{
|
||||
for (signed i = 0; i < 8; i++)
|
||||
{
|
||||
if ((num >> i) & 1)
|
||||
{
|
||||
return 1 << i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if \p build_state contains all the flags in \p block_all_flags.
|
||||
* If not, return the corresponding nano::error_common::missing_<...> value.
|
||||
*/
|
||||
std::error_code check_fields_set (uint8_t block_all_flags, uint8_t build_state)
|
||||
{
|
||||
std::error_code ec;
|
||||
|
||||
// Figure out which fields are not set. Note that static typing ensures we cannot set values
|
||||
// not applicable to a given block type, we can only forget to set fields. This will be zero
|
||||
// if all fields are set and thus succeed.
|
||||
uint8_t res = block_all_flags ^ build_state;
|
||||
if (res)
|
||||
{
|
||||
// Convert the first bit set to a field mask and look up the error code.
|
||||
auto build_flags_mask = ffs_mask (res);
|
||||
assert (ec_map.find (build_flags_mask) != ec_map.end ());
|
||||
ec = ec_map[build_flags_mask];
|
||||
}
|
||||
return ec;
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
rai::state_block_builder::state_block_builder ()
|
||||
{
|
||||
make_block ();
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::make_block ()
|
||||
{
|
||||
construct_block ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void rai::state_block_builder::validate ()
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ec = check_fields_set (required_fields, build_state);
|
||||
}
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::zero ()
|
||||
{
|
||||
block->work = uint64_t (0);
|
||||
block->signature.clear ();
|
||||
block->hashables.account.clear ();
|
||||
block->hashables.balance.clear ();
|
||||
block->hashables.link.clear ();
|
||||
block->hashables.previous.clear ();
|
||||
block->hashables.representative.clear ();
|
||||
build_state = required_fields;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::account (rai::account account)
|
||||
{
|
||||
block->hashables.account = account;
|
||||
build_state |= build_flags::account_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::account_hex (std::string account_hex)
|
||||
{
|
||||
account_hex_impl (account_hex, ec, block);
|
||||
build_state |= build_flags::account_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::account_address (std::string address)
|
||||
{
|
||||
account_address_impl (address, ec, block);
|
||||
build_state |= build_flags::account_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::representative (rai::account account)
|
||||
{
|
||||
block->hashables.representative = account;
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::representative_hex (std::string account_hex)
|
||||
{
|
||||
representative_hex_impl (account_hex, ec, block);
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::representative_address (std::string address)
|
||||
{
|
||||
representative_address_impl (address, ec, block);
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::previous (rai::block_hash previous)
|
||||
{
|
||||
block->hashables.previous = previous;
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::previous_hex (std::string previous_hex)
|
||||
{
|
||||
previous_hex_impl (previous_hex, ec, block);
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::balance (rai::amount balance)
|
||||
{
|
||||
block->hashables.balance = balance;
|
||||
build_state |= build_flags::balance_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::balance_dec (std::string balance_decimal)
|
||||
{
|
||||
balance_dec_impl (balance_decimal, ec, block);
|
||||
build_state |= build_flags::balance_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::balance_hex (std::string balance_hex)
|
||||
{
|
||||
balance_hex_impl (balance_hex, ec, block);
|
||||
build_state |= build_flags::balance_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::link (rai::uint256_union link)
|
||||
{
|
||||
block->hashables.link = link;
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::link_hex (std::string link_hex)
|
||||
{
|
||||
rai::uint256_union link;
|
||||
if (!link.decode_hex (link_hex))
|
||||
{
|
||||
block->hashables.link = link;
|
||||
build_state |= build_flags::link_present;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_link;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::state_block_builder & rai::state_block_builder::link_address (std::string link_address)
|
||||
{
|
||||
rai::account link;
|
||||
if (!link.decode_account (link_address))
|
||||
{
|
||||
block->hashables.link = link;
|
||||
build_state |= build_flags::link_present;
|
||||
}
|
||||
else
|
||||
{
|
||||
ec = nano::error_common::bad_link;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder::open_block_builder ()
|
||||
{
|
||||
make_block ();
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::make_block ()
|
||||
{
|
||||
construct_block ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void rai::open_block_builder::validate ()
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ec = check_fields_set (required_fields, build_state);
|
||||
}
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::zero ()
|
||||
{
|
||||
block->work = uint64_t (0);
|
||||
block->signature.clear ();
|
||||
block->hashables.account.clear ();
|
||||
block->hashables.representative.clear ();
|
||||
block->hashables.source.clear ();
|
||||
build_state = required_fields;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::account (rai::account account)
|
||||
{
|
||||
block->hashables.account = account;
|
||||
build_state |= build_flags::account_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::account_hex (std::string account_hex)
|
||||
{
|
||||
account_hex_impl (account_hex, ec, block);
|
||||
build_state |= build_flags::account_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::account_address (std::string address)
|
||||
{
|
||||
account_address_impl (address, ec, block);
|
||||
build_state |= build_flags::account_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::representative (rai::account account)
|
||||
{
|
||||
block->hashables.representative = account;
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::representative_hex (std::string account_hex)
|
||||
{
|
||||
representative_hex_impl (account_hex, ec, block);
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::representative_address (std::string address)
|
||||
{
|
||||
representative_address_impl (address, ec, block);
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::source (rai::block_hash source)
|
||||
{
|
||||
block->hashables.source = source;
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::open_block_builder & rai::open_block_builder::source_hex (std::string source_hex)
|
||||
{
|
||||
source_hex_impl (source_hex, ec, block);
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::change_block_builder::change_block_builder ()
|
||||
{
|
||||
make_block ();
|
||||
}
|
||||
|
||||
rai::change_block_builder & rai::change_block_builder::make_block ()
|
||||
{
|
||||
construct_block ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void rai::change_block_builder::validate ()
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ec = check_fields_set (required_fields, build_state);
|
||||
}
|
||||
}
|
||||
|
||||
rai::change_block_builder & rai::change_block_builder::zero ()
|
||||
{
|
||||
block->work = uint64_t (0);
|
||||
block->signature.clear ();
|
||||
block->hashables.previous.clear ();
|
||||
block->hashables.representative.clear ();
|
||||
build_state = required_fields;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::change_block_builder & rai::change_block_builder::representative (rai::account account)
|
||||
{
|
||||
block->hashables.representative = account;
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::change_block_builder & rai::change_block_builder::representative_hex (std::string account_hex)
|
||||
{
|
||||
representative_hex_impl (account_hex, ec, block);
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::change_block_builder & rai::change_block_builder::representative_address (std::string address)
|
||||
{
|
||||
representative_address_impl (address, ec, block);
|
||||
build_state |= build_flags::representative_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::change_block_builder & rai::change_block_builder::previous (rai::block_hash previous)
|
||||
{
|
||||
block->hashables.previous = previous;
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::change_block_builder & rai::change_block_builder::previous_hex (std::string previous_hex)
|
||||
{
|
||||
previous_hex_impl (previous_hex, ec, block);
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder::send_block_builder ()
|
||||
{
|
||||
make_block ();
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::make_block ()
|
||||
{
|
||||
construct_block ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void rai::send_block_builder::validate ()
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ec = check_fields_set (required_fields, build_state);
|
||||
}
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::zero ()
|
||||
{
|
||||
block->work = uint64_t (0);
|
||||
block->signature.clear ();
|
||||
block->hashables.previous.clear ();
|
||||
block->hashables.destination.clear ();
|
||||
block->hashables.balance.clear ();
|
||||
build_state = required_fields;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::destination (rai::account account)
|
||||
{
|
||||
block->hashables.destination = account;
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::destination_hex (std::string account_hex)
|
||||
{
|
||||
destination_hex_impl (account_hex, ec, block);
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::destination_address (std::string address)
|
||||
{
|
||||
destination_address_impl (address, ec, block);
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::previous (rai::block_hash previous)
|
||||
{
|
||||
block->hashables.previous = previous;
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::previous_hex (std::string previous_hex)
|
||||
{
|
||||
previous_hex_impl (previous_hex, ec, block);
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::balance (rai::amount balance)
|
||||
{
|
||||
block->hashables.balance = balance;
|
||||
build_state |= build_flags::balance_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::balance_dec (std::string balance_decimal)
|
||||
{
|
||||
balance_dec_impl (balance_decimal, ec, block);
|
||||
build_state |= build_flags::balance_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::send_block_builder & rai::send_block_builder::balance_hex (std::string balance_hex)
|
||||
{
|
||||
balance_hex_impl (balance_hex, ec, block);
|
||||
build_state |= build_flags::balance_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::receive_block_builder::receive_block_builder ()
|
||||
{
|
||||
make_block ();
|
||||
}
|
||||
|
||||
rai::receive_block_builder & rai::receive_block_builder::make_block ()
|
||||
{
|
||||
construct_block ();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void rai::receive_block_builder::validate ()
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
ec = check_fields_set (required_fields, build_state);
|
||||
}
|
||||
}
|
||||
|
||||
rai::receive_block_builder & rai::receive_block_builder::zero ()
|
||||
{
|
||||
block->work = uint64_t (0);
|
||||
block->signature.clear ();
|
||||
block->hashables.previous.clear ();
|
||||
block->hashables.source.clear ();
|
||||
build_state = required_fields;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::receive_block_builder & rai::receive_block_builder::previous (rai::block_hash previous)
|
||||
{
|
||||
block->hashables.previous = previous;
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::receive_block_builder & rai::receive_block_builder::previous_hex (std::string previous_hex)
|
||||
{
|
||||
previous_hex_impl (previous_hex, ec, block);
|
||||
build_state |= build_flags::previous_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::receive_block_builder & rai::receive_block_builder::source (rai::block_hash source)
|
||||
{
|
||||
block->hashables.source = source;
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
rai::receive_block_builder & rai::receive_block_builder::source_hex (std::string source_hex)
|
||||
{
|
||||
source_hex_impl (source_hex, ec, block);
|
||||
build_state |= build_flags::link_present;
|
||||
return *this;
|
||||
}
|
331
rai/lib/blockbuilders.hpp
Normal file
331
rai/lib/blockbuilders.hpp
Normal file
|
@ -0,0 +1,331 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <rai/lib/blocks.hpp>
|
||||
#include <rai/lib/errors.hpp>
|
||||
|
||||
namespace rai
|
||||
{
|
||||
/** Flags to track builder state */
|
||||
enum class build_flags : uint8_t
|
||||
{
|
||||
signature_present = 1,
|
||||
work_present = 2,
|
||||
account_present = 4,
|
||||
balance_present = 8,
|
||||
/* link also covers source and destination for legacy blocks */
|
||||
link_present = 16,
|
||||
previous_present = 32,
|
||||
representative_present = 64
|
||||
};
|
||||
|
||||
inline rai::build_flags operator| (rai::build_flags a, rai::build_flags b)
|
||||
{
|
||||
return static_cast<rai::build_flags> (static_cast<uint8_t> (a) | static_cast<uint8_t> (b));
|
||||
}
|
||||
inline uint8_t operator| (uint8_t a, rai::build_flags b)
|
||||
{
|
||||
return static_cast<uint8_t> (a | static_cast<uint8_t> (b));
|
||||
}
|
||||
inline uint8_t operator& (uint8_t a, rai::build_flags b)
|
||||
{
|
||||
return static_cast<uint8_t> (a & static_cast<uint8_t> (b));
|
||||
}
|
||||
inline uint8_t operator|= (uint8_t & a, rai::build_flags b)
|
||||
{
|
||||
return a = static_cast<uint8_t> (a | static_cast<uint8_t> (b));
|
||||
}
|
||||
|
||||
/**
|
||||
* Base type for block builder implementations. We employ static polymorphism
|
||||
* to pass validation through subtypes without incurring the vtable cost.
|
||||
*/
|
||||
template <typename BLOCKTYPE, typename BUILDER>
|
||||
class abstract_builder
|
||||
{
|
||||
public:
|
||||
/** Returns the built block as a unique_ptr */
|
||||
inline std::unique_ptr<BLOCKTYPE> build ()
|
||||
{
|
||||
if (!ec)
|
||||
{
|
||||
static_cast<BUILDER *> (this)->validate ();
|
||||
}
|
||||
assert (!ec);
|
||||
return std::move (block);
|
||||
}
|
||||
|
||||
/** Returns the built block as a unique_ptr. Any errors are placed in \p ec */
|
||||
inline std::unique_ptr<BLOCKTYPE> build (std::error_code & ec)
|
||||
{
|
||||
if (!this->ec)
|
||||
{
|
||||
static_cast<BUILDER *> (this)->validate ();
|
||||
}
|
||||
ec = this->ec;
|
||||
return std::move (block);
|
||||
}
|
||||
|
||||
/** Set work value */
|
||||
inline abstract_builder & work (uint64_t work)
|
||||
{
|
||||
block->work = work;
|
||||
build_state |= build_flags::work_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Sign the block using the \p private_key and \p public_key */
|
||||
inline abstract_builder & sign (rai::raw_key const & private_key, rai::public_key const & public_key)
|
||||
{
|
||||
block->signature = rai::sign_message (private_key, public_key, block->hash ());
|
||||
build_state |= build_flags::signature_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Set signature to zero to pass build() validation, allowing block to be signed at a later point. This is mostly useful for tests. */
|
||||
inline abstract_builder & sign_zero ()
|
||||
{
|
||||
block->signature.clear ();
|
||||
build_state |= build_flags::signature_present;
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
abstract_builder ()
|
||||
{
|
||||
}
|
||||
|
||||
/** Create a new block and resets the internal builder state */
|
||||
inline void construct_block ()
|
||||
{
|
||||
block = std::make_unique<BLOCKTYPE> ();
|
||||
ec.clear ();
|
||||
build_state = 0;
|
||||
}
|
||||
|
||||
/** The block we're building. Clients can convert this to shared_ptr as needed. */
|
||||
std::unique_ptr<BLOCKTYPE> block;
|
||||
|
||||
/**
|
||||
* Set if any builder functions fail. This will be output via the build(std::error_code) function,
|
||||
* or cause an assert for the parameter-less overload.
|
||||
*/
|
||||
std::error_code ec;
|
||||
|
||||
/** Bitset to track build state */
|
||||
uint8_t build_state{ 0 };
|
||||
|
||||
/** Required field shared by all block types*/
|
||||
uint8_t base_fields = static_cast<uint8_t> (rai::build_flags::work_present | rai::build_flags::signature_present);
|
||||
};
|
||||
|
||||
/** Builder for state blocks */
|
||||
class state_block_builder : public abstract_builder<rai::state_block, state_block_builder>
|
||||
{
|
||||
public:
|
||||
/** Creates a state block builder by calling make_block() */
|
||||
state_block_builder ();
|
||||
/** Creates a new block with fields, signature and work set to sentinel values. All fields must be set or zeroed for build() to succeed. */
|
||||
state_block_builder & make_block ();
|
||||
/** Sets all hashables, signature and work to zero. */
|
||||
state_block_builder & zero ();
|
||||
/** Set account */
|
||||
state_block_builder & account (rai::account account);
|
||||
/** Set account from hex representation of public key */
|
||||
state_block_builder & account_hex (std::string account_hex);
|
||||
/** Set account from an xrb_ or nano_ address */
|
||||
state_block_builder & account_address (std::string account_address);
|
||||
/** Set representative */
|
||||
state_block_builder & representative (rai::account account);
|
||||
/** Set representative from hex representation of public key */
|
||||
state_block_builder & representative_hex (std::string account_hex);
|
||||
/** Set representative from an xrb_ or nano_ address */
|
||||
state_block_builder & representative_address (std::string account_address);
|
||||
/** Set previous block hash */
|
||||
state_block_builder & previous (rai::block_hash previous);
|
||||
/** Set previous block hash from hex representation */
|
||||
state_block_builder & previous_hex (std::string previous_hex);
|
||||
/** Set balance */
|
||||
state_block_builder & balance (rai::amount balance);
|
||||
/** Set balance from decimal string */
|
||||
state_block_builder & balance_dec (std::string balance_decimal);
|
||||
/** Set balance from hex string */
|
||||
state_block_builder & balance_hex (std::string balance_hex);
|
||||
/** Set link */
|
||||
state_block_builder & link (rai::uint256_union link);
|
||||
/** Set link from hex representation */
|
||||
state_block_builder & link_hex (std::string link_hex);
|
||||
/** Set link from an xrb_ or nano_ address */
|
||||
state_block_builder & link_address (std::string link_address);
|
||||
/** Provides validation for build() */
|
||||
void validate ();
|
||||
|
||||
private:
|
||||
uint8_t required_fields = base_fields | static_cast<uint8_t> (rai::build_flags::account_present | rai::build_flags::balance_present | rai::build_flags::link_present | rai::build_flags::previous_present | rai::build_flags::representative_present);
|
||||
};
|
||||
|
||||
/** Builder for open blocks */
|
||||
class open_block_builder : public abstract_builder<rai::open_block, open_block_builder>
|
||||
{
|
||||
public:
|
||||
/** Creates an open block builder by calling make_block() */
|
||||
open_block_builder ();
|
||||
/** Creates a new block with fields, signature and work set to sentinel values. All fields must be set or zeroed for build() to succeed. */
|
||||
open_block_builder & make_block ();
|
||||
/** Sets all hashables, signature and work to zero. */
|
||||
open_block_builder & zero ();
|
||||
/** Set account */
|
||||
open_block_builder & account (rai::account account);
|
||||
/** Set account from hex representation of public key */
|
||||
open_block_builder & account_hex (std::string account_hex);
|
||||
/** Set account from an xrb_ or nano_ address */
|
||||
open_block_builder & account_address (std::string account_address);
|
||||
/** Set representative */
|
||||
open_block_builder & representative (rai::account account);
|
||||
/** Set representative from hex representation of public key */
|
||||
open_block_builder & representative_hex (std::string account_hex);
|
||||
/** Set representative from an xrb_ or nano_ address */
|
||||
open_block_builder & representative_address (std::string account_address);
|
||||
/** Set source block hash */
|
||||
open_block_builder & source (rai::block_hash source);
|
||||
/** Set source block hash from hex representation */
|
||||
open_block_builder & source_hex (std::string source_hex);
|
||||
/** Provides validation for build() */
|
||||
void validate ();
|
||||
|
||||
private:
|
||||
uint8_t required_fields = base_fields | static_cast<uint8_t> (rai::build_flags::account_present | rai::build_flags::representative_present | rai::build_flags::link_present);
|
||||
};
|
||||
|
||||
/** Builder for change blocks */
|
||||
class change_block_builder : public abstract_builder<rai::change_block, change_block_builder>
|
||||
{
|
||||
public:
|
||||
/** Create a change block builder by calling make_block() */
|
||||
change_block_builder ();
|
||||
/** Creates a new block with fields, signature and work set to sentinel values. All fields must be set or zeroed for build() to succeed. */
|
||||
change_block_builder & make_block ();
|
||||
/** Sets all hashables, signature and work to zero. */
|
||||
change_block_builder & zero ();
|
||||
/** Set representative */
|
||||
change_block_builder & representative (rai::account account);
|
||||
/** Set representative from hex representation of public key */
|
||||
change_block_builder & representative_hex (std::string account_hex);
|
||||
/** Set representative from an xrb_ or nano_ address */
|
||||
change_block_builder & representative_address (std::string account_address);
|
||||
/** Set previous block hash */
|
||||
change_block_builder & previous (rai::block_hash previous);
|
||||
/** Set previous block hash from hex representation */
|
||||
change_block_builder & previous_hex (std::string previous_hex);
|
||||
/** Provides validation for build() */
|
||||
void validate ();
|
||||
|
||||
private:
|
||||
uint8_t required_fields = base_fields | static_cast<uint8_t> (rai::build_flags::previous_present | rai::build_flags::representative_present);
|
||||
};
|
||||
|
||||
/** Builder for send blocks */
|
||||
class send_block_builder : public abstract_builder<rai::send_block, send_block_builder>
|
||||
{
|
||||
public:
|
||||
/** Creates a send block builder by calling make_block() */
|
||||
send_block_builder ();
|
||||
/** Creates a new block with fields, signature and work set to sentinel values. All fields must be set or zeroed for build() to succeed. */
|
||||
send_block_builder & make_block ();
|
||||
/** Sets all hashables, signature and work to zero. */
|
||||
send_block_builder & zero ();
|
||||
/** Set destination */
|
||||
send_block_builder & destination (rai::account account);
|
||||
/** Set destination from hex representation of public key */
|
||||
send_block_builder & destination_hex (std::string account_hex);
|
||||
/** Set destination from an xrb_ or nano_ address */
|
||||
send_block_builder & destination_address (std::string account_address);
|
||||
/** Set previous block hash */
|
||||
send_block_builder & previous (rai::block_hash previous);
|
||||
/** Set previous block hash from hex representation */
|
||||
send_block_builder & previous_hex (std::string previous_hex);
|
||||
/** Set balance */
|
||||
send_block_builder & balance (rai::amount balance);
|
||||
/** Set balance from decimal string */
|
||||
send_block_builder & balance_dec (std::string balance_decimal);
|
||||
/** Set balance from hex string */
|
||||
send_block_builder & balance_hex (std::string balance_hex);
|
||||
/** Provides validation for build() */
|
||||
void validate ();
|
||||
|
||||
private:
|
||||
uint8_t required_fields = base_fields | static_cast<uint8_t> (build_flags::previous_present | build_flags::link_present | build_flags::balance_present);
|
||||
};
|
||||
|
||||
/** Builder for receive blocks */
|
||||
class receive_block_builder : public abstract_builder<rai::receive_block, receive_block_builder>
|
||||
{
|
||||
public:
|
||||
/** Creates a receive block by calling make_block() */
|
||||
receive_block_builder ();
|
||||
/** Creates a new block with fields, signature and work set to sentinel values. All fields must be set or zeroed for build() to succeed. */
|
||||
receive_block_builder & make_block ();
|
||||
/** Sets all hashables, signature and work to zero. */
|
||||
receive_block_builder & zero ();
|
||||
/** Set previous block hash */
|
||||
receive_block_builder & previous (rai::block_hash previous);
|
||||
/** Set previous block hash from hex representation */
|
||||
receive_block_builder & previous_hex (std::string previous_hex);
|
||||
/** Set source block hash */
|
||||
receive_block_builder & source (rai::block_hash source);
|
||||
/** Set source block hash from hex representation */
|
||||
receive_block_builder & source_hex (std::string source_hex);
|
||||
/** Provides validation for build() */
|
||||
void validate ();
|
||||
|
||||
private:
|
||||
uint8_t required_fields = base_fields | static_cast<uint8_t> (build_flags::previous_present | build_flags::link_present);
|
||||
};
|
||||
|
||||
/** Block builder to simplify construction of the various block types */
|
||||
class block_builder
|
||||
{
|
||||
public:
|
||||
/** Prepares a new state block and returns a block builder */
|
||||
inline rai::state_block_builder & state ()
|
||||
{
|
||||
state_builder.make_block ();
|
||||
return state_builder;
|
||||
}
|
||||
|
||||
/** Prepares a new open block and returns a block builder */
|
||||
inline rai::open_block_builder & open ()
|
||||
{
|
||||
open_builder.make_block ();
|
||||
return open_builder;
|
||||
}
|
||||
|
||||
/** Prepares a new change block and returns a block builder */
|
||||
inline rai::change_block_builder & change ()
|
||||
{
|
||||
change_builder.make_block ();
|
||||
return change_builder;
|
||||
}
|
||||
|
||||
/** Prepares a new send block and returns a block builder */
|
||||
inline rai::send_block_builder & send ()
|
||||
{
|
||||
send_builder.make_block ();
|
||||
return send_builder;
|
||||
}
|
||||
|
||||
/** Prepares a new receive block and returns a block builder */
|
||||
inline rai::receive_block_builder & receive ()
|
||||
{
|
||||
receive_builder.make_block ();
|
||||
return receive_builder;
|
||||
}
|
||||
|
||||
private:
|
||||
rai::state_block_builder state_builder;
|
||||
rai::open_block_builder open_builder;
|
||||
rai::change_block_builder change_builder;
|
||||
rai::send_block_builder send_builder;
|
||||
rai::receive_block_builder receive_builder;
|
||||
};
|
||||
}
|
|
@ -73,6 +73,7 @@ public:
|
|||
class send_hashables
|
||||
{
|
||||
public:
|
||||
send_hashables () = default;
|
||||
send_hashables (rai::account const &, rai::block_hash const &, rai::amount const &);
|
||||
send_hashables (bool &, rai::stream &);
|
||||
send_hashables (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -84,6 +85,7 @@ public:
|
|||
class send_block : public rai::block
|
||||
{
|
||||
public:
|
||||
send_block () = default;
|
||||
send_block (rai::block_hash const &, rai::account const &, rai::amount const &, rai::raw_key const &, rai::public_key const &, uint64_t);
|
||||
send_block (bool &, rai::stream &);
|
||||
send_block (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -116,6 +118,7 @@ public:
|
|||
class receive_hashables
|
||||
{
|
||||
public:
|
||||
receive_hashables () = default;
|
||||
receive_hashables (rai::block_hash const &, rai::block_hash const &);
|
||||
receive_hashables (bool &, rai::stream &);
|
||||
receive_hashables (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -126,6 +129,7 @@ public:
|
|||
class receive_block : public rai::block
|
||||
{
|
||||
public:
|
||||
receive_block () = default;
|
||||
receive_block (rai::block_hash const &, rai::block_hash const &, rai::raw_key const &, rai::public_key const &, uint64_t);
|
||||
receive_block (bool &, rai::stream &);
|
||||
receive_block (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -158,6 +162,7 @@ public:
|
|||
class open_hashables
|
||||
{
|
||||
public:
|
||||
open_hashables () = default;
|
||||
open_hashables (rai::block_hash const &, rai::account const &, rai::account const &);
|
||||
open_hashables (bool &, rai::stream &);
|
||||
open_hashables (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -169,6 +174,7 @@ public:
|
|||
class open_block : public rai::block
|
||||
{
|
||||
public:
|
||||
open_block () = default;
|
||||
open_block (rai::block_hash const &, rai::account const &, rai::account const &, rai::raw_key const &, rai::public_key const &, uint64_t);
|
||||
open_block (rai::block_hash const &, rai::account const &, rai::account const &, std::nullptr_t);
|
||||
open_block (bool &, rai::stream &);
|
||||
|
@ -202,6 +208,7 @@ public:
|
|||
class change_hashables
|
||||
{
|
||||
public:
|
||||
change_hashables () = default;
|
||||
change_hashables (rai::block_hash const &, rai::account const &);
|
||||
change_hashables (bool &, rai::stream &);
|
||||
change_hashables (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -212,6 +219,7 @@ public:
|
|||
class change_block : public rai::block
|
||||
{
|
||||
public:
|
||||
change_block () = default;
|
||||
change_block (rai::block_hash const &, rai::account const &, rai::raw_key const &, rai::public_key const &, uint64_t);
|
||||
change_block (bool &, rai::stream &);
|
||||
change_block (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -244,6 +252,7 @@ public:
|
|||
class state_hashables
|
||||
{
|
||||
public:
|
||||
state_hashables () = default;
|
||||
state_hashables (rai::account const &, rai::block_hash const &, rai::account const &, rai::amount const &, rai::uint256_union const &);
|
||||
state_hashables (bool &, rai::stream &);
|
||||
state_hashables (bool &, boost::property_tree::ptree const &);
|
||||
|
@ -266,6 +275,7 @@ public:
|
|||
class state_block : public rai::block
|
||||
{
|
||||
public:
|
||||
state_block () = default;
|
||||
state_block (rai::account const &, rai::block_hash const &, rai::account const &, rai::amount const &, rai::uint256_union const &, rai::raw_key const &, rai::public_key const &, uint64_t);
|
||||
state_block (bool &, rai::stream &);
|
||||
state_block (bool &, boost::property_tree::ptree const &);
|
||||
|
|
|
@ -6,6 +6,20 @@ std::string nano::error_common_messages::message (int ev) const
|
|||
{
|
||||
case nano::error_common::generic:
|
||||
return "Unknown error";
|
||||
case nano::error_common::missing_account:
|
||||
return "Missing account";
|
||||
case nano::error_common::missing_balance:
|
||||
return "Missing balance";
|
||||
case nano::error_common::missing_link:
|
||||
return "Missing link, source or destination";
|
||||
case nano::error_common::missing_previous:
|
||||
return "Missing previous";
|
||||
case nano::error_common::missing_representative:
|
||||
return "Missing representative";
|
||||
case nano::error_common::missing_signature:
|
||||
return "Missing signature";
|
||||
case nano::error_common::missing_work:
|
||||
return "Missing work";
|
||||
case nano::error_common::account_exists:
|
||||
return "Account already exists";
|
||||
case nano::error_common::account_not_found:
|
||||
|
@ -14,6 +28,18 @@ std::string nano::error_common_messages::message (int ev) const
|
|||
return "Account not found in wallet";
|
||||
case nano::error_common::bad_account_number:
|
||||
return "Bad account number";
|
||||
case nano::error_common::bad_balance:
|
||||
return "Bad balance";
|
||||
case nano::error_common::bad_link:
|
||||
return "Bad link value";
|
||||
case nano::error_common::bad_previous:
|
||||
return "Bad previous hash";
|
||||
case nano::error_common::bad_representative_number:
|
||||
return "Bad representative";
|
||||
case nano::error_common::bad_source:
|
||||
return "Bad source";
|
||||
case nano::error_common::bad_signature:
|
||||
return "Bad signature";
|
||||
case nano::error_common::bad_private_key:
|
||||
return "Bad private key";
|
||||
case nano::error_common::bad_public_key:
|
||||
|
|
|
@ -32,12 +32,25 @@ enum class error_common
|
|||
account_not_found_wallet,
|
||||
account_exists,
|
||||
bad_account_number,
|
||||
bad_balance,
|
||||
bad_link,
|
||||
bad_previous,
|
||||
bad_representative_number,
|
||||
bad_source,
|
||||
bad_signature,
|
||||
bad_private_key,
|
||||
bad_public_key,
|
||||
bad_seed,
|
||||
bad_threshold,
|
||||
bad_wallet_number,
|
||||
bad_work_format,
|
||||
missing_account,
|
||||
missing_balance,
|
||||
missing_link,
|
||||
missing_previous,
|
||||
missing_representative,
|
||||
missing_signature,
|
||||
missing_work,
|
||||
invalid_amount,
|
||||
invalid_amount_big,
|
||||
invalid_count,
|
||||
|
|
|
@ -310,6 +310,12 @@ rai::uint512_union::uint512_union (rai::uint512_t const & number_a)
|
|||
}
|
||||
}
|
||||
|
||||
bool rai::uint512_union::is_zero () const
|
||||
{
|
||||
return qwords[0] == 0 && qwords[1] == 0 && qwords[2] == 0 && qwords[3] == 0
|
||||
&& qwords[4] == 0 && qwords[5] == 0 && qwords[6] == 0 && qwords[7] == 0;
|
||||
}
|
||||
|
||||
void rai::uint512_union::clear ()
|
||||
{
|
||||
bytes.fill (0);
|
||||
|
|
|
@ -119,6 +119,7 @@ union uint512_union
|
|||
std::array<uint64_t, 8> qwords;
|
||||
std::array<uint256_union, 2> uint256s;
|
||||
void clear ();
|
||||
bool is_zero () const;
|
||||
rai::uint512_t number () const;
|
||||
std::string to_string () const;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <rai/lib/blockbuilders.hpp>
|
||||
#include <rai/lib/blocks.hpp>
|
||||
#include <rai/secure/utility.hpp>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue