Skip to content

Commit

Permalink
Merge pull request #306 from skalenetwork/bug/SKALE-2755-stateRoot
Browse files Browse the repository at this point in the history
Bug/skale 2755 state root
  • Loading branch information
dimalit authored Jul 10, 2020
2 parents 87fcdcf + 63bca4a commit 1564097
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 70 deletions.
27 changes: 21 additions & 6 deletions libethereum/ChainParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,12 @@ ChainParams ChainParams::loadConfig(
if ( cp.rotateAfterBlock_ < 0 )
cp.rotateAfterBlock_ = 0;

std::string ecdsaKeyName = infoObj.at( "ecdsaKeyName" ).get_str();
std::string ecdsaKeyName;
try {
ecdsaKeyName = infoObj.at( "ecdsaKeyName" ).get_str();
} catch ( ... ) {
}

std::array< std::string, 4 > insecureBLSPublicKeys;
std::array< std::string, 4 > insecureCommonBLSPublicKeys;

Expand Down Expand Up @@ -208,12 +213,22 @@ ChainParams ChainParams::loadConfig(
node.port6 = 0;
}
node.sChainIndex = nodeConfObj.at( "schainIndex" ).get_uint64();
node.publicKey = nodeConfObj.at( "publicKey" ).get_str();
try {
node.publicKey = nodeConfObj.at( "publicKey" ).get_str();
} catch ( ... ) {
}
if ( !keyShareName.empty() ) {
node.blsPublicKey[0] = nodeConfObj.at( "blsPublicKey0" ).get_str();
node.blsPublicKey[1] = nodeConfObj.at( "blsPublicKey1" ).get_str();
node.blsPublicKey[2] = nodeConfObj.at( "blsPublicKey2" ).get_str();
node.blsPublicKey[3] = nodeConfObj.at( "blsPublicKey3" ).get_str();
try {
node.blsPublicKey[0] = nodeConfObj.at( "blsPublicKey0" ).get_str();
node.blsPublicKey[1] = nodeConfObj.at( "blsPublicKey1" ).get_str();
node.blsPublicKey[2] = nodeConfObj.at( "blsPublicKey2" ).get_str();
node.blsPublicKey[3] = nodeConfObj.at( "blsPublicKey3" ).get_str();
} catch ( ... ) {
node.blsPublicKey[0] = "";
node.blsPublicKey[1] = "";
node.blsPublicKey[2] = "";
node.blsPublicKey[3] = "";
}
}
s.nodes.push_back( node );
}
Expand Down
92 changes: 55 additions & 37 deletions libethereum/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ void Client::injectSkaleHost( std::shared_ptr< SkaleHost > _skaleHost ) {

if ( !m_skaleHost )
m_skaleHost = make_shared< SkaleHost >( *this );

if ( Worker::isWorking() )
m_skaleHost->startWorking();
}
Expand Down Expand Up @@ -200,8 +199,14 @@ void Client::init( WithExisting _forceAction, u256 _networkId ) {

if ( chainParams().sChain.snapshotIntervalMs > 0 ) {
if ( this->number() == 0 ) {
m_snapshotManager->doSnapshot( 0 );
LOG( m_logger ) << "DOING SNAPSHOT: " << 0;
try {
m_snapshotManager->doSnapshot( 0 );
} catch ( SnapshotManager::SnapshotPresent& ex ) {
cerror << "WARNING " << dev::nested_exception_what( ex );
}
}
this->initHashes();
}

doWork( false );
Expand Down Expand Up @@ -397,6 +402,9 @@ size_t Client::importTransactionsAsBlock(
int64_t snapshotIntervalMs = chainParams().sChain.snapshotIntervalMs;
if ( snapshotIntervalMs > 0 && this->isTimeToDoSnapshot( _timestamp ) &&
block_number != 0 ) {
if ( this->last_snapshoted_block != -1 ) {
this->updateHashes();
}
try {
LOG( m_logger ) << "DOING SNAPSHOT: " << block_number;
m_snapshotManager->doSnapshot( block_number );
Expand All @@ -412,31 +420,23 @@ size_t Client::importTransactionsAsBlock(
this->last_snapshot_time += snapshotIntervalMs;
}

if ( this->m_snapshotManager->isSnapshotHashPresent( block_number ) ) {
this->updateHashes( block_number );
} else {
std::thread( [this, block_number]() {
try {
this->m_snapshotManager->computeSnapshotHash( block_number );
this->updateHashes( block_number );
} catch ( const std::exception& ex ) {
cerror << "CRITICAL " << dev::nested_exception_what( ex )
<< " in computeSnapshotHash() or updateHashes(). Exiting";
cerror << "\n"
<< skutils::signal::generate_stack_trace() << "\n"
<< std::endl;
ExitHandler::exitHandler( SIGABRT );
} catch ( ... ) {
cerror << "CRITICAL unknown exception in computeSnapshotHash() or "
"updateHashes(). Exiting";
cerror << "\n"
<< skutils::signal::generate_stack_trace() << "\n"
<< std::endl;
ExitHandler::exitHandler( SIGABRT );
}
} )
.detach();
}
std::thread( [this, block_number]() {
try {
this->m_snapshotManager->computeSnapshotHash( block_number );
this->last_snapshoted_block = block_number;
} catch ( const std::exception& ex ) {
cerror << "CRITICAL " << dev::nested_exception_what( ex )
<< " in computeSnapshotHash() or updateHashes(). Exiting";
cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl;
ExitHandler::exitHandler( SIGABRT );
} catch ( ... ) {
cerror << "CRITICAL unknown exception in computeSnapshotHash() or "
"updateHashes(). Exiting";
cerror << "\n" << skutils::signal::generate_stack_trace() << "\n" << std::endl;
ExitHandler::exitHandler( SIGABRT );
}
} )
.detach();
// TODO Make this number configurable
m_snapshotManager->leaveNLastSnapshots( 2 );
} // if snapshot
Expand Down Expand Up @@ -1008,17 +1008,35 @@ ExecutionResult Client::call( Address const& _from, u256 _value, Address _dest,
return ret;
}

void Client::updateHashes( unsigned block_number ) {
if ( this->last_snapshoted_block == -1 ) {
this->last_snapshot_hashes.first = this->m_snapshotManager->getSnapshotHash( block_number );
} else {
if ( this->last_snapshot_hashes.second != this->empty_str_hash ) {
std::swap( this->last_snapshot_hashes.first, this->last_snapshot_hashes.second );
}
this->last_snapshot_hashes.second =
this->m_snapshotManager->getSnapshotHash( block_number );
void Client::updateHashes() {
if ( this->last_snapshot_hashes.first == this->empty_str_hash ) {
this->last_snapshot_hashes.first =
this->m_snapshotManager->getSnapshotHash( this->last_snapshoted_block );
return;
}
this->last_snapshoted_block = block_number;
if ( this->last_snapshot_hashes.second != this->empty_str_hash ) {
std::swap( this->last_snapshot_hashes.first, this->last_snapshot_hashes.second );
}
this->last_snapshot_hashes.second =
this->m_snapshotManager->getSnapshotHash( this->last_snapshoted_block );
}

void Client::initHashes() {
auto latest_snapshots = this->m_snapshotManager->getLatestSnasphot();
this->last_snapshoted_block = ( latest_snapshots.first ? latest_snapshots.first : -1 );

this->last_snapshot_time =
( latest_snapshots.first ?
this->blockInfo( this->hashFromNumber( this->last_snapshoted_block ) ).timestamp() :
-1 );
this->last_snapshot_hashes.first =
( latest_snapshots.second ?
this->m_snapshotManager->getSnapshotHash( latest_snapshots.second ) :
this->empty_str_hash );
this->last_snapshot_hashes.second =
( latest_snapshots.first ?
this->m_snapshotManager->getSnapshotHash( latest_snapshots.first ) :
this->empty_str_hash );
}

// new block watch
Expand Down
4 changes: 2 additions & 2 deletions libethereum/Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,8 +468,8 @@ class Client : public ClientBase, protected Worker {

private:
inline bool isTimeToDoSnapshot( uint64_t _timestamp ) const;
void updateHashes( unsigned block_number );

void initHashes();
void updateHashes();

int64_t last_snapshot_time = -1;
int64_t last_snapshoted_block = -1;
Expand Down
56 changes: 36 additions & 20 deletions libethereum/SkaleHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,10 @@ std::unique_ptr< ConsensusInterface > DefaultConsensusFactory::create(
auto ts = nfo.timestamp();
auto consensus_engine_ptr = make_unique< ConsensusEngine >( _extFace, m_client.number(), ts );

if ( m_client.chainParams().nodeInfo.sgxServerUrl != "" ) {
this->fillSgxInfo( *consensus_engine_ptr );
}
// temproray hack, remove it in further versions
// if ( m_client.chainParams().nodeInfo.sgxServerUrl != "" ) {
// this->fillSgxInfo( *consensus_engine_ptr );
// }

return consensus_engine_ptr;
#else
Expand Down Expand Up @@ -103,7 +104,7 @@ void DefaultConsensusFactory::fillSgxInfo( ConsensusEngine& consensus ) const {
std::shared_ptr< std::vector< std::string > > ecdsaPublicKeys =
std::make_shared< std::vector< std::string > >();
for ( const auto& node : m_client.chainParams().sChain.nodes ) {
ecdsaPublicKeys->push_back( node.publicKey );
ecdsaPublicKeys->push_back( node.publicKey.substr( 2 ) );
}

std::vector< std::shared_ptr< std::vector< std::string > > > blsPublicKeys;
Expand All @@ -115,10 +116,10 @@ void DefaultConsensusFactory::fillSgxInfo( ConsensusEngine& consensus ) const {
public_key_share[2] = node.blsPublicKey[2];
public_key_share[3] = node.blsPublicKey[3];
} else {
public_key_share[0] = this->m_client.chainParams().nodeInfo.insecureBLSPublicKeys[0];
public_key_share[1] = this->m_client.chainParams().nodeInfo.insecureBLSPublicKeys[1];
public_key_share[2] = this->m_client.chainParams().nodeInfo.insecureBLSPublicKeys[2];
public_key_share[3] = this->m_client.chainParams().nodeInfo.insecureBLSPublicKeys[3];
public_key_share[0] = m_client.chainParams().nodeInfo.insecureBLSPublicKeys[0];
public_key_share[1] = m_client.chainParams().nodeInfo.insecureBLSPublicKeys[1];
public_key_share[2] = m_client.chainParams().nodeInfo.insecureBLSPublicKeys[2];
public_key_share[3] = m_client.chainParams().nodeInfo.insecureBLSPublicKeys[3];
}

blsPublicKeys.push_back(
Expand All @@ -130,10 +131,16 @@ void DefaultConsensusFactory::fillSgxInfo( ConsensusEngine& consensus ) const {
blsPublicKeys );

size_t n = m_client.chainParams().sChain.nodes.size();
size_t t = ( 2 * n + 2 ) / 3;
size_t t = ( 2 * n + 1 ) / 3;

consensus.setSGXKeyInfo( sgxServerUrl, sgxSSLKeyFilePath, sgxSSLCertFilePath, ecdsaKeyName,
ecdsaPublicKeys, blsKeyName, blsPublicKeysPtr, t, n );
try {
consensus.setSGXKeyInfo( sgxServerUrl, sgxSSLKeyFilePath, sgxSSLCertFilePath, ecdsaKeyName,
ecdsaPublicKeys, blsKeyName, blsPublicKeysPtr, t, n );
} catch ( const std::exception& ex ) {
std::throw_with_nested( ex.what() );
} catch ( const boost::exception& ex ) {
std::throw_with_nested( boost::diagnostic_information( ex ) );
}
}
#endif

Expand Down Expand Up @@ -206,7 +213,7 @@ SkaleHost::SkaleHost( dev::eth::Client& _client, const ConsensusFactory* _consFa
SkaleHost::~SkaleHost() {}

void SkaleHost::logState() {
LOG( m_debugLogger ) << cc::debug( "sent_to_consensus = " ) << total_sent
LOG( m_debugLogger ) << cc::debug( " sent_to_consensus = " ) << total_sent
<< cc::debug( " got_from_consensus = " ) << total_arrived
<< cc::debug( " m_transaction_cache = " ) << m_m_transaction_cache.size()
<< cc::debug( " m_tq = " ) << m_tq.status().current
Expand Down Expand Up @@ -457,15 +464,24 @@ void SkaleHost::createBlock( const ConsensusExtFace::transactions_vector& _appro
std::lock_guard< std::recursive_mutex > lock( m_pending_createMutex );

if ( this->m_client.chainParams().sChain.snapshotIntervalMs > 0 ) {
LOG( m_traceLogger ) << cc::debug( "STATE ROOT FOR BLOCK: " )
<< cc::debug( std::to_string( _blockID - 1 ) ) << ' '
<< cc::debug(
this->m_client
.blockInfo( this->m_client.hashFromNumber( _blockID - 1 ) )
.stateRoot()
.hex() )
<< std::endl;
// this is need for testing. should add better handling
LOG( m_traceLogger )
<< cc::debug( "STATE ROOT FOR BLOCK: " ) << cc::debug( std::to_string( _blockID ) )
<< cc::debug( this->m_client.blockInfo( this->m_client.hashFromNumber( _blockID ) )
.stateRoot()
.hex() );
assert(
dev::h256::Arith( this->m_client.blockInfo( this->m_client.hashFromNumber( _blockID ) )
.stateRoot() ) == _stateRoot );
// if ( dev::h256::Arith( this->m_client.blockInfo( this->m_client.hashFromNumber(
// _blockID ) )
// .stateRoot() ) != _stateRoot ) {
// cerror << "StateRoot assertion failed. Clean up /data_dir. Exiting";
// ExitHandler::exitHandler( SIGABRT );
// }
assert( dev::h256::Arith(
this->m_client.blockInfo( this->m_client.hashFromNumber( _blockID - 1 ) )
.stateRoot() ) == _stateRoot );
}

std::vector< Transaction > out_txns; // resultant Transaction vector
Expand Down
4 changes: 2 additions & 2 deletions libskale/SnapshotHashAgent.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class SnapshotHashAgentTest;
}
} // namespace dev

class SnapshotHashAgentException : std::exception {
class SnapshotHashAgentException : public std::exception {
protected:
std::string what_str;

Expand Down Expand Up @@ -68,7 +68,7 @@ class SnapshotHashAgent {
this->hashes_.resize( n_ );
this->signatures_.resize( n_ );
this->public_keys_.resize( n_ );
this->bls_.reset( new signatures::Bls( ( 2 * this->n_ + 2 ) / 3, this->n_ ) );
this->bls_.reset( new signatures::Bls( ( 2 * this->n_ + 1 ) / 3, this->n_ ) );
if ( common_public_key == "" ) {
this->common_public_key_.X.c0 = libff::alt_bn128_Fq(
chain_params_.nodeInfo.insecureCommonBLSPublicKeys[0].c_str() );
Expand Down
31 changes: 28 additions & 3 deletions libskale/SnapshotManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,14 +272,36 @@ void SnapshotManager::leaveNLastSnapshots( unsigned n ) {
} // for
}

std::pair< int, int > SnapshotManager::getLatestSnasphot() const {
multimap< time_t, fs::path, std::greater< time_t > > time_map;
for ( auto& f : fs::directory_iterator( snapshots_dir ) ) {
// HACK We exclude 0 snapshot forcefully
if ( fs::basename( f ) != "0" )
time_map.insert( make_pair( fs::last_write_time( f ), f ) );
}
if ( time_map.empty() ) {
return std::make_pair( 0, 0 );
}
auto it = time_map.rbegin();
int fst = std::stoi( fs::basename( ( *it++ ).second ) );

int snd;
if ( time_map.size() > 1 ) {
snd = 0;
} else {
snd = std::stoi( fs::basename( ( *it ).second ) );
}
return std::make_pair( fst, snd );
}

// exeptions: filesystem
void SnapshotManager::leaveNLastDiffs( unsigned n ) {
multimap< time_t, fs::path, std::greater< time_t > > time_map;
for ( auto& f : fs::directory_iterator( diffs_dir ) ) {
time_map.insert( make_pair( fs::last_write_time( f ), f ) );
} // for

// delete all efter n first
// delete all after n first
unsigned i = 1;
for ( const auto& p : time_map ) {
if ( i++ > n ) {
Expand Down Expand Up @@ -307,11 +329,10 @@ dev::h256 SnapshotManager::getSnapshotHash( unsigned block_number ) const {
BOOST_THROW_EXCEPTION( SnapshotManager::CannotRead( hash_file ) );
}

std::lock_guard< std::mutex > lock( hash_file_mutex );

dev::h256 hash;

try {
std::lock_guard< std::mutex > lock( hash_file_mutex );
std::ifstream in( hash_file );
in >> hash;
} catch ( const std::exception& ex ) {
Expand Down Expand Up @@ -476,6 +497,10 @@ void SnapshotManager::computeAllVolumesHash(
}

void SnapshotManager::computeSnapshotHash( unsigned _blockNumber, bool is_checking ) {
if ( this->isSnapshotHashPresent( _blockNumber ) ) {
return;
}

secp256k1_sha256_t ctx;
secp256k1_sha256_initialize( &ctx );

Expand Down
1 change: 1 addition & 0 deletions libskale/SnapshotManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class SnapshotManager {
void leaveNLastDiffs( unsigned n );

dev::h256 getSnapshotHash( unsigned _blockNumber ) const;
std::pair< int, int > getLatestSnasphot() const;
bool isSnapshotHashPresent( unsigned _blockNumber ) const;
void computeSnapshotHash( unsigned _blockNumber, bool is_checking = false );

Expand Down

0 comments on commit 1564097

Please sign in to comment.