Skip to content
This repository has been archived by the owner on Feb 21, 2019. It is now read-only.

Commit

Permalink
Merge pull request #86 from vikramrajkumar/btsx
Browse files Browse the repository at this point in the history
Merge upstream
  • Loading branch information
bitsha256 committed Oct 28, 2014
2 parents 61a32bf + 40f55d2 commit c440710
Show file tree
Hide file tree
Showing 14 changed files with 256 additions and 55 deletions.
37 changes: 19 additions & 18 deletions libraries/blockchain/address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,41 @@ namespace bts {
address::address( const std::string& base58str )
{
FC_ASSERT( is_valid( base58str ) );
std::vector<char> v = fc::from_base58( base58str.substr( strlen(BTS_ADDRESS_PREFIX) ) );
memcpy( (char*)addr._hash, v.data(), std::min<size_t>( v.size()-4, sizeof(addr) ) );
std::string prefix( BTS_ADDRESS_PREFIX );
std::vector<char> v = fc::from_base58( base58str.substr( prefix.size() ) );
memcpy( (char*)addr._hash, v.data(), std::min<size_t>( v.size()-4, sizeof( addr ) ) );
}
address::address( const withdraw_condition& condition )
{
// uint32_t address_type = 1;
fc::sha512::encoder enc;
fc::raw::pack( enc, condition );
// enc.write( (char*)&address_type, sizeof(address_type) );
addr = fc::ripemd160::hash( enc.result() );
}

/**
* Validates checksum and length of base58 address
*
// TODO is_valid should not throw, should return false...
* @return true if successful, throws an exception with reason if invalid.
*/
// TODO: This should return false rather than throwing
bool address::is_valid( const std::string& base58str )
{ try {
FC_ASSERT( base58str.size() > strlen(BTS_ADDRESS_PREFIX) ); // could probably increase from 10 to some min length
FC_ASSERT( base58str.substr( 0, strlen(BTS_ADDRESS_PREFIX) ) == BTS_ADDRESS_PREFIX );
std::vector<char> v = fc::from_base58( base58str.substr( strlen(BTS_ADDRESS_PREFIX) ) );
std::string prefix( BTS_ADDRESS_PREFIX );
const size_t prefix_len = prefix.size();
FC_ASSERT( base58str.size() > prefix_len );
FC_ASSERT( base58str.substr( 0, prefix_len ) == prefix );
std::vector<char> v = fc::from_base58( base58str.substr( prefix_len ) );
FC_ASSERT( v.size() > 4, "all addresses must have a 4 byte checksum" );
FC_ASSERT(v.size() <= sizeof(fc::ripemd160) + 4, "all addresses are less than 24 bytes");
auto checksum = fc::ripemd160::hash( v.data(), v.size() - 4 );
FC_ASSERT( memcmp( v.data()+20, (char*)checksum._hash, 4 ) == 0, "address checksum mismatch" );
FC_ASSERT(v.size() <= sizeof( fc::ripemd160 ) + 4, "all addresses are less than 24 bytes");
const fc::ripemd160 checksum = fc::ripemd160::hash( v.data(), v.size() - 4 );
FC_ASSERT( memcmp( v.data() + 20, (char*)checksum._hash, 4 ) == 0, "address checksum mismatch" );
return true;
} FC_RETHROW_EXCEPTIONS( warn, "invalid address '${a}'", ("a", base58str) ) }

address::address( const fc::ecc::public_key& pub )
{
auto dat = pub.serialize();
addr = fc::ripemd160::hash( fc::sha512::hash( dat.data, sizeof(dat) ) );
auto dat = pub.serialize();
addr = fc::ripemd160::hash( fc::sha512::hash( dat.data, sizeof( dat ) ) );
}

address::address( const pts_address& ptsaddr )
Expand All @@ -54,21 +55,21 @@ namespace bts {

address::address( const fc::ecc::public_key_data& pub )
{
addr = fc::ripemd160::hash( fc::sha512::hash( pub.data, sizeof(pub) ) );
addr = fc::ripemd160::hash( fc::sha512::hash( pub.data, sizeof( pub ) ) );
}

address::address( const bts::blockchain::public_key_type& pub )
{
addr = fc::ripemd160::hash( fc::sha512::hash( pub.key_data.data, sizeof(pub.key_data) ) );
addr = fc::ripemd160::hash( fc::sha512::hash( pub.key_data.data, sizeof( pub.key_data ) ) );
}

address::operator std::string()const
{
fc::array<char,24> bin_addr;
memcpy( (char*)&bin_addr, (char*)&addr, sizeof(addr) );
auto checksum = fc::ripemd160::hash( (char*)&addr, sizeof(addr) );
memcpy( (char*)&bin_addr, (char*)&addr, sizeof( addr ) );
auto checksum = fc::ripemd160::hash( (char*)&addr, sizeof( addr ) );
memcpy( ((char*)&bin_addr)+20, (char*)&checksum._hash[0], 4 );
return BTS_ADDRESS_PREFIX + fc::to_base58( bin_addr.data, sizeof(bin_addr) );
return BTS_ADDRESS_PREFIX + fc::to_base58( bin_addr.data, sizeof( bin_addr ) );
}

} } // namespace bts::blockchain
Expand Down
35 changes: 23 additions & 12 deletions libraries/blockchain/chain_database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,19 @@ namespace bts { namespace blockchain {
vector<transaction_id_type> trx_to_discard;

_pending_trx_state = std::make_shared<pending_chain_state>( self->shared_from_this() );
unsigned num_pending_transaction_considered = 0;
auto itr = _pending_transaction_db.begin();
while( itr.valid() )
{
auto trx = itr.value();
auto trx_id = trx.id();
try {
auto eval_state = self->evaluate_transaction( trx, _relay_fee );
signed_transaction trx = itr.value();
transaction_id_type trx_id = itr.key();
assert(trx_id == trx.id());
try
{
transaction_evaluation_state_ptr eval_state = self->evaluate_transaction( trx, _relay_fee );
share_type fees = eval_state->get_fees();
_pending_fee_index[ fee_index( fees, trx_id ) ] = eval_state;
_pending_transaction_db.store( trx_id, trx );
wlog("revalidated pending transaction id ${id}", ("id", trx_id));
}
catch ( const fc::canceled_exception& )
{
Expand All @@ -69,11 +72,15 @@ namespace bts { namespace blockchain {
wlog( "discarding invalid transaction: ${id} ${e}",
("id",trx_id)("e",e.to_detail_string()) );
}
++num_pending_transaction_considered;
++itr;
}

for( const auto& item : trx_to_discard )
_pending_transaction_db.remove( item );
wlog("revalidate_pending complete, there are now ${pending_count} evaluated transactions, ${num_pending_transaction_considered} raw transactions",
("pending_count", _pending_fee_index.size())
("num_pending_transaction_considered", num_pending_transaction_considered));
}

void chain_database_impl::open_database( const fc::path& data_dir )
Expand Down Expand Up @@ -347,7 +354,7 @@ namespace bts { namespace blockchain {
{
std::unordered_set<transaction_id_type> confirmed_trx_ids;

for( const auto& trx : blk.user_transactions )
for( const signed_transaction& trx : blk.user_transactions )
{
auto id = trx.id();
confirmed_trx_ids.insert( id );
Expand All @@ -365,7 +372,8 @@ namespace bts { namespace blockchain {
uint32_t last_checkpoint_block_num = 0;
if( !CHECKPOINT_BLOCKS.empty() )
last_checkpoint_block_num = (--(CHECKPOINT_BLOCKS.end()))->first;
if( (!_revalidate_pending.valid() || _revalidate_pending.ready()) && _head_block_header.block_num >= last_checkpoint_block_num )
if( (!_revalidate_pending.valid() || _revalidate_pending.ready()) &&
_head_block_header.block_num >= last_checkpoint_block_num )
_revalidate_pending = fc::async( [=](){ revalidate_pending(); }, "revalidate_pending" );

_pending_trx_state = std::make_shared<pending_chain_state>( self->shared_from_this() );
Expand Down Expand Up @@ -1870,10 +1878,13 @@ namespace bts { namespace blockchain {
/** this should throw if the trx is invalid */
transaction_evaluation_state_ptr chain_database::store_pending_transaction( const signed_transaction& trx, bool override_limits )
{ try {

auto trx_id = trx.id();
auto current_itr = my->_pending_transaction_db.find( trx_id );
if( current_itr.valid() ) return nullptr;
if (override_limits)
wlog("storing new local transaction with id ${id}", ("id", trx_id));

auto current_itr = my->_pending_transaction_db.find(trx_id);
if( current_itr.valid() )
return nullptr;

share_type relay_fee = my->_relay_fee;
if( !override_limits )
Expand All @@ -1885,7 +1896,7 @@ namespace bts { namespace blockchain {
}
}

auto eval_state = evaluate_transaction( trx, relay_fee );
transaction_evaluation_state_ptr eval_state = evaluate_transaction( trx, relay_fee );
share_type fees = eval_state->get_fees();

//if( fees < my->_relay_fee )
Expand Down Expand Up @@ -3152,7 +3163,7 @@ namespace bts { namespace blockchain {
return prices[prices.size()/2];
}
return oprice();
} FC_CAPTURE_AND_RETHROW( (asset_id) ) }
} FC_CAPTURE_AND_RETHROW( (asset_id)(base_id) ) }

vector<feed_record> chain_database::get_feeds_for_asset( const asset_id_type& asset_id, const asset_id_type& base_id )const
{ try {
Expand Down
18 changes: 10 additions & 8 deletions libraries/blockchain/extended_address.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace bts { namespace blockchain {
{
}

extended_public_key::~extended_public_key(){}
extended_public_key::~extended_public_key(){}

extended_public_key::extended_public_key( const fc::ecc::public_key& key, const fc::sha256& code )
:pub_key(key),chain_code(code)
Expand Down Expand Up @@ -101,7 +101,7 @@ namespace bts { namespace blockchain {
memcpy( (char*)&ikey_right, ((char*)&ikey) + sizeof(ikey_left), sizeof(ikey_right) );

child_key.priv_key = fc::ecc::private_key::generate_from_seed( priv_key, ikey_left ).get_secret();
child_key.chain_code = ikey_right;
child_key.chain_code = ikey_right;

return child_key;
} FC_RETHROW_EXCEPTIONS( warn, "child index ${child_idx}", ("child_idx", child_idx ) ) }
Expand Down Expand Up @@ -132,7 +132,7 @@ namespace bts { namespace blockchain {
memcpy( (char*)&ikey_right, ((char*)&ikey) + sizeof(ikey_left), sizeof(ikey_right) );

child_key.priv_key = fc::ecc::private_key::generate_from_seed( priv_key, ikey_left ).get_secret();
child_key.chain_code = ikey_right;
child_key.chain_code = ikey_right;

return child_key;
} FC_RETHROW_EXCEPTIONS( warn, "child index ${child_idx}", ("child_idx", child_idx ) ) }
Expand All @@ -154,10 +154,12 @@ namespace bts { namespace blockchain {
{ try {

uint32_t checksum = 0;
FC_ASSERT( base58str.size() > strlen( BTS_ADDRESS_PREFIX ) );
FC_ASSERT( base58str.substr( 0, strlen( BTS_ADDRESS_PREFIX ) ) == BTS_ADDRESS_PREFIX );
std::string prefix( BTS_ADDRESS_PREFIX );
const size_t prefix_len = prefix.size();
FC_ASSERT( base58str.size() > prefix_len );
FC_ASSERT( base58str.substr( 0, prefix_len ) == prefix );

std::vector<char> data = fc::from_base58( base58str.substr( strlen( BTS_ADDRESS_PREFIX ) ) );
std::vector<char> data = fc::from_base58( base58str.substr( prefix_len ) );
FC_ASSERT( data.size() == (33+32+4) );

fc::datastream<const char*> ds(data.data(),data.size());
Expand Down Expand Up @@ -196,8 +198,8 @@ namespace bts { namespace blockchain {

} } // namespace bts::blockchain

namespace fc
{
namespace fc
{
void to_variant( const bts::blockchain::extended_address& ext_addr, fc::variant& vo )
{
vo = std::string(ext_addr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ const static std::map<uint32_t, bts::blockchain::block_id_type> CHECKPOINT_BLOCK
{ 600000, bts::blockchain::block_id_type( "f278db8722235343c9db9f077fe67c54a5f25f3b" ) },
{ 700000, bts::blockchain::block_id_type( "f120ff9b159661b9ac084a0a69c58dcbd79cbb49" ) },
{ 800000, bts::blockchain::block_id_type( "0e94ad17c598e42e5ec2f522a05bf4df6a1778da" ) },
{ 855200, bts::blockchain::block_id_type( "d0dabe7b2a5c09a10f7b980dee02d8b48568adc8" ) }
{ 863300, bts::blockchain::block_id_type( "9ad71eb07c202fdc81661d246c3d26ac2a4ba98f" ) }
};
5 changes: 3 additions & 2 deletions libraries/blockchain/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ namespace bts { namespace blockchain {

public_key_type::public_key_type( const std::string& base58str )
{
static const size_t prefix_len = strlen(BTS_ADDRESS_PREFIX);
std::string prefix( BTS_ADDRESS_PREFIX );
const size_t prefix_len = prefix.size();
FC_ASSERT( base58str.size() > prefix_len );
FC_ASSERT( base58str.substr( 0, prefix_len ) == BTS_ADDRESS_PREFIX, "", ("base58str", base58str) );
FC_ASSERT( base58str.substr( 0, prefix_len ) == prefix , "", ("base58str", base58str) );
auto bin = fc::from_base58( base58str.substr( prefix_len ) );
auto bin_key = fc::raw::unpack<binary_key>(bin);
key_data = bin_key.data;
Expand Down
4 changes: 2 additions & 2 deletions libraries/client/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ void print_banner()
{
std::cout<<"================================================================\n";
std::cout<<"= =\n";
std::cout<<"= Welcome to BitShares "<< std::setw(5) << std::left << BTS_ADDRESS_PREFIX<<" =\n";
std::cout<<"= Welcome to BitShares "<< std::setw(5) << std::left << BTS_ADDRESS_PREFIX << " =\n";
std::cout<<"= =\n";
std::cout<<"= This software is in alpha testing and is not suitable for =\n";
std::cout<<"= real monetary transactions or trading. Use at your own =\n";
Expand Down Expand Up @@ -3302,7 +3302,7 @@ config load_config( const fc::path& datadir, bool enable_ulog )
info["blockchain_delegate_pay_rate"] = _chain_db->get_delegate_pay_rate();

info["blockchain_share_supply"] = variant();
const auto share_record = _chain_db->get_asset_record( BTS_ADDRESS_PREFIX );
const auto share_record = _chain_db->get_asset_record( BTS_BLOCKCHAIN_SYMBOL );
if( share_record.valid() )
info["blockchain_share_supply"] = share_record->current_share_supply;

Expand Down
14 changes: 7 additions & 7 deletions libraries/db/include/bts/db/cached_level_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@ namespace bts { namespace db {

void flush()
{
// TODO...
// start batch
for( auto item : _dirty )
_db.store( item, _cache[item] );
for( auto item : _dirty_remove )
_db.remove( item );
// end batch
typename level_map<Key, Value>::write_batch batch = _db.create_batch();
for( const auto& item : _dirty )
batch.store(item, _cache[item]);
for( const auto& item : _dirty_remove )
batch.remove(item);
batch.commit();

_dirty.clear();
_dirty_remove.clear();
}
Expand Down
85 changes: 84 additions & 1 deletion libraries/db/include/bts/db/level_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <leveldb/db.h>
#include <leveldb/comparator.h>
#include <leveldb/cache.h>
#include <leveldb/write_batch.h>

#include <fc/filesystem.hpp>

Expand Down Expand Up @@ -263,7 +264,89 @@ namespace bts { namespace db {
return true;
} FC_RETHROW_EXCEPTIONS( warn, "error reading last item from database" ); }

void store( const Key& k, const Value& v, bool sync = false )
/** this class allows batched, atomic database writes.
* usage:
* {
* write_batch batch = _db.create_batch();
* batch.store(key1, value1);
* batch.store(key2, value2);
* }
* when the batch goes out of scope, the operations are commited to the database
*/
class write_batch
{
private:
leveldb::WriteBatch _batch;
level_map* _map;

friend class level_map;
write_batch(level_map* map) :
_map(map)
{
}
public:
~write_batch()
{
try
{
commit();
}
catch (const fc::canceled_exception&)
{
throw;
}
catch (const fc::exception&)
{
// we're in a destructor, nothing we can do...
}
}

void commit()
{
try
{
FC_ASSERT(_map->is_open(), "Database is not open!");

ldb::Status status = _map->_db->Write(ldb::WriteOptions(), &_batch);
if (status.IsNotFound())
FC_THROW_EXCEPTION(fc::key_not_found_exception, "unable to find key while applying batch");
if (!status.ok())
FC_THROW_EXCEPTION(db_exception, "database error while applying batch: ${msg}", ("msg", status.ToString()));
_batch.Clear();
}
FC_RETHROW_EXCEPTIONS(warn, "error applying batch");
}

void abort()
{
_batch.Clear();
}

void store(const Key& k, const Value& v)
{
std::vector<char> kslice = fc::raw::pack(k);
ldb::Slice ks(kslice.data(), kslice.size());

auto vec = fc::raw::pack(v);
ldb::Slice vs(vec.data(), vec.size());

_batch.Put(ks, vs);
}

void remove(const Key& k, bool sync = false)
{
std::vector<char> kslice = fc::raw::pack(k);
ldb::Slice ks(kslice.data(), kslice.size());
_batch.Delete(ks);
}
};

write_batch create_batch()
{
return write_batch(this);
}

void store(const Key& k, const Value& v, bool sync = false)
{ try {
FC_ASSERT( is_open(), "Database is not open!" );

Expand Down
2 changes: 1 addition & 1 deletion libraries/fc
Submodule fc updated from 307252 to d1f51d
2 changes: 1 addition & 1 deletion libraries/leveldb
Loading

0 comments on commit c440710

Please sign in to comment.