Skip to content

Commit

Permalink
Initial representative weights for bootstrapping.
Browse files Browse the repository at this point in the history
  • Loading branch information
lukealonso committed Feb 4, 2018
1 parent fe6f27c commit 721a948
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 1 deletion.
10 changes: 10 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,18 @@ else ()
error ("Unknown platform: ${CMAKE_SYSTEM_NAME}")
endif ()

# Embed bootstrap representative weights in executable
file (READ rep_weights.bin filedata HEX)
string (REGEX REPLACE "(..)" "0x\\1," filedata ${filedata})
file (WRITE ${CMAKE_BINARY_DIR}/bootstrap_weights.cpp "#include <cstddef>\n\
namespace rai {\n\
unsigned char rai_bootstrap_weights[] = {${filedata} 0x00};\n\
size_t rai_bootstrap_weights_size = sizeof(rai_bootstrap_weights) - 1;\n\
}\n")

add_library (secure
${PLATFORM_SECURE_SOURCE}
${CMAKE_BINARY_DIR}/bootstrap_weights.cpp
rai/config.hpp
rai/secure.cpp
rai/secure.hpp
Expand Down
63 changes: 63 additions & 0 deletions ci/record_rep_weights.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import requests
import argparse
import string
from binascii import unhexlify
from base64 import b32decode
from binascii import hexlify, unhexlify


parser = argparse.ArgumentParser(description='Generate bootstrap representative weight file.')
parser.add_argument("output", type=str, help="output weight file")
parser.add_argument("--rpc", help="node rpc host:port", default="http://[::1]:7076")
parser.add_argument("--limit", help="percentage of the active supply represented", default=0.99)
parser.add_argument("--cutoff", help="stop using bootstrap reps this many blocks before the current block height", default=250000)
args = parser.parse_args()

r = requests.post(args.rpc, data='{"action":"representatives"}')
p = r.json()

reps = [ ]
tbl = string.maketrans('13456789abcdefghijkmnopqrstuwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
for acc in p["representatives"]:
reps.append({
'account': acc,
'weight': long(p["representatives"][acc])
})

r = requests.post(args.rpc, data='{"action":"block_count"}')
p = r.json()
block_height = max(0, int(p["count"]) - args.cutoff)

print "cutoff block height is %d" % block_height

reps.sort(key=lambda x: x["weight"], reverse=True)

supplymax = long(0)
for rep in reps:
supplymax += rep["weight"]

supplymax /= long('1000000000000000000000000000000')
supplymax = long(supplymax * args.limit)
supplymax *= long('1000000000000000000000000000000')

with open(args.output, 'wb') as of:
of.write(unhexlify("%032X" % block_height))

total = long(0)
count = 0
for rep in reps:
if rep["weight"] == 0:
break
acc_val = long(hexlify(b32decode(rep["account"].encode("utf-8").replace("xrb_", "").translate(tbl) + "====")), 16)
acc_bytes = unhexlify("%064X" % (((acc_val >> 36) & ((1 << 256) - 1))))
weight_bytes = unhexlify("%032X" % rep["weight"])
of.write(acc_bytes)
of.write(weight_bytes)
total += rep["weight"]
count += 1
if total >= supplymax:
break

print "wrote %d rep weights" % count

of.close()
35 changes: 35 additions & 0 deletions rai/core_test/ledger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1420,3 +1420,38 @@ TEST (ledger, send_open_receive_rollback)
ASSERT_EQ (0, ledger.weight (transaction, key3.pub));
ASSERT_EQ (rai::genesis_amount - 0, ledger.weight (transaction, rai::test_genesis_key.pub));
}

TEST (ledger, bootstrap_rep_weight)
{
bool init (false);
rai::block_store store (init, rai::unique_path ());
ASSERT_TRUE (!init);
rai::ledger ledger (store, 40);
rai::account_info info1;
rai::keypair key2;
rai::genesis genesis;
{
rai::transaction transaction (store.environment, nullptr, true);
genesis.initialize (transaction, store);
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info1));
rai::send_block send (info1.head, key2.pub, std::numeric_limits<rai::uint128_t>::max () - 50, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
ledger.process (transaction, send);
}
{
rai::transaction transaction (store.environment, nullptr, false);
ledger.bootstrap_weight_max_blocks = 3;
ledger.bootstrap_weights[key2.pub] = 1000;
ASSERT_EQ (1000, ledger.weight (transaction, key2.pub));
}
{
rai::transaction transaction (store.environment, nullptr, true);
genesis.initialize (transaction, store);
ASSERT_FALSE (store.account_get (transaction, rai::test_genesis_key.pub, info1));
rai::send_block send (info1.head, key2.pub, std::numeric_limits<rai::uint128_t>::max () - 100, rai::test_genesis_key.prv, rai::test_genesis_key.pub, 0);
ledger.process (transaction, send);
}
{
rai::transaction transaction (store.environment, nullptr, false);
ASSERT_EQ (0, ledger.weight (transaction, key2.pub));
}
}
31 changes: 31 additions & 0 deletions rai/node/node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1505,6 +1505,37 @@ block_processor_thread ([this]() { this->block_processor.process_blocks (); })
genesis.initialize (transaction, store);
}
}
if (rai::rai_network == rai::rai_networks::rai_live_network)
{
extern const char rai_bootstrap_weights[];
extern const size_t rai_bootstrap_weights_size;
rai::bufferstream weight_stream ((const uint8_t *)rai_bootstrap_weights, rai_bootstrap_weights_size);
rai::uint128_union block_height;
if (!rai::read (weight_stream, block_height))
{
auto max_blocks = (uint64_t)block_height.number ();
rai::transaction transaction (store.environment, nullptr, false);
if (ledger.store.block_count (transaction).sum () < max_blocks)
{
ledger.bootstrap_weight_max_blocks = max_blocks;
while (true)
{
rai::account account;
if (rai::read (weight_stream, account.bytes))
{
break;
}
rai::amount weight;
if (rai::read (weight_stream, weight.bytes))
{
break;
}
BOOST_LOG (log) << "Using bootstrap rep weight: " << account.to_account () << " -> " << weight.format_balance (Mxrb_ratio, 0, true) << " XRB";
ledger.bootstrap_weights[account] = weight.number ();
}
}
}
}
}

rai::node::~node ()
Expand Down
19 changes: 18 additions & 1 deletion rai/secure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ rai::keypair::keypair (std::string const & prv_a)

rai::ledger::ledger (rai::block_store & store_a, rai::uint128_t const & inactive_supply_a) :
store (store_a),
inactive_supply (inactive_supply_a)
inactive_supply (inactive_supply_a),
check_bootstrap_weights (true)
{
}

Expand Down Expand Up @@ -2153,6 +2154,22 @@ std::string rai::ledger::block_text (rai::block_hash const & hash_a)
// Vote weight of an account
rai::uint128_t rai::ledger::weight (MDB_txn * transaction_a, rai::account const & account_a)
{
if (check_bootstrap_weights.load ())
{
auto blocks = store.block_count (transaction_a);
if (blocks.sum () < bootstrap_weight_max_blocks)
{
auto weight = bootstrap_weights.find (account_a);
if (weight != bootstrap_weights.end ())
{
return weight->second;
}
}
else
{
check_bootstrap_weights = false;
}
}
return store.representation_get (transaction_a, account_a);
}

Expand Down
3 changes: 3 additions & 0 deletions rai/secure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ class ledger
static rai::uint128_t const unit;
rai::block_store & store;
rai::uint128_t inactive_supply;
std::unordered_map<rai::account, rai::uint128_t> bootstrap_weights;
uint64_t bootstrap_weight_max_blocks;
std::atomic<bool> check_bootstrap_weights;
};
extern rai::keypair const & zero_key;
extern rai::keypair const & test_genesis_key;
Expand Down
Binary file added rep_weights.bin
Binary file not shown.

0 comments on commit 721a948

Please sign in to comment.