Initial representative weights for bootstrapping

This commit is contained in:
Luke Alonso 2018-02-07 18:50:12 -08:00 committed by androm3da
commit 89339ef08b
7 changed files with 160 additions and 1 deletions

View file

@ -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

63
ci/record_rep_weights.py Normal file
View file

@ -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()

View file

@ -1431,3 +1431,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));
}
}

View file

@ -1525,6 +1525,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 ()

View file

@ -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)
{
}
@ -2424,6 +2425,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);
}

View file

@ -390,6 +390,9 @@ public:
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;

BIN
rep_weights.bin Normal file

Binary file not shown.