@ -15,25 +15,31 @@
@@ -15,25 +15,31 @@
# include "tinyformat.h"
# include "util.h"
namespace {
CBanDB : : CBanDB ( )
template < typename Stream , typename Data >
bool SerializeDB ( Stream & stream , const Data & data )
{
pathBanlist = GetDataDir ( ) / " banlist.dat " ;
// Write and commit header, data
try {
CHashWriter hasher ( SER_DISK , CLIENT_VERSION ) ;
stream < < FLATDATA ( Params ( ) . MessageStart ( ) ) < < data ;
hasher < < FLATDATA ( Params ( ) . MessageStart ( ) ) < < data ;
stream < < hasher . GetHash ( ) ;
} catch ( const std : : exception & e ) {
return error ( " %s: Serialize or I/O error - %s " , __func__ , e . what ( ) ) ;
}
return true ;
}
bool CBanDB : : Write ( const banmap_t & banSet )
template < typename Data >
bool SerializeFileDB ( const std : : string & prefix , const fs : : path & path , const Data & data )
{
// Generate random temporary filename
unsigned short randv = 0 ;
GetRandBytes ( ( unsigned char * ) & randv , sizeof ( randv ) ) ;
std : : string tmpfn = strprintf ( " banlist.dat.%04x " , randv ) ;
// serialize banlist, checksum data up to that point, then append csum
CDataStream ssBanlist ( SER_DISK , CLIENT_VERSION ) ;
ssBanlist < < FLATDATA ( Params ( ) . MessageStart ( ) ) ;
ssBanlist < < banSet ;
uint256 hash = Hash ( ssBanlist . begin ( ) , ssBanlist . end ( ) ) ;
ssBanlist < < hash ;
std : : string tmpfn = strprintf ( " %s.%04x " , prefix , randv ) ;
// open temp output file, and associate with CAutoFile
fs : : path pathTmp = GetDataDir ( ) / tmpfn ;
@ -42,69 +48,41 @@ bool CBanDB::Write(const banmap_t& banSet)
@@ -42,69 +48,41 @@ bool CBanDB::Write(const banmap_t& banSet)
if ( fileout . IsNull ( ) )
return error ( " %s: Failed to open file %s " , __func__ , pathTmp . string ( ) ) ;
// Write and commit header, data
try {
fileout < < ssBanlist ;
}
catch ( const std : : exception & e ) {
return error ( " %s: Serialize or I/O error - %s " , __func__ , e . what ( ) ) ;
}
// Serialize
if ( ! SerializeDB ( fileout , data ) ) return false ;
FileCommit ( fileout . Get ( ) ) ;
fileout . fclose ( ) ;
// replace existing banlist.dat, if any, with new banlist.dat.XXXX
if ( ! RenameOver ( pathTmp , pathBanlist ) )
// replace existing file, if any, with new file
if ( ! RenameOver ( pathTmp , path ) )
return error ( " %s: Rename-into-place failed " , __func__ ) ;
return true ;
}
bool CBanDB : : Read ( banmap_t & banSet )
template < typename Stream , typename Data >
bool DeserializeDB ( Stream & stream , Data & data , bool fCheckSum = true )
{
// open input file, and associate with CAutoFile
FILE * file = fsbridge : : fopen ( pathBanlist , " rb " ) ;
CAutoFile filein ( file , SER_DISK , CLIENT_VERSION ) ;
if ( filein . IsNull ( ) )
return error ( " %s: Failed to open file %s " , __func__ , pathBanlist . string ( ) ) ;
// use file size to size memory buffer
uint64_t fileSize = fs : : file_size ( pathBanlist ) ;
uint64_t dataSize = 0 ;
// Don't try to resize to a negative number if file is small
if ( fileSize > = sizeof ( uint256 ) )
dataSize = fileSize - sizeof ( uint256 ) ;
std : : vector < unsigned char > vchData ;
vchData . resize ( dataSize ) ;
uint256 hashIn ;
// read data and checksum from file
try {
filein . read ( ( char * ) & vchData [ 0 ] , dataSize ) ;
filein > > hashIn ;
}
catch ( const std : : exception & e ) {
return error ( " %s: Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
}
filein . fclose ( ) ;
CDataStream ssBanlist ( vchData , SER_DISK , CLIENT_VERSION ) ;
// verify stored checksum matches input data
uint256 hashTmp = Hash ( ssBanlist . begin ( ) , ssBanlist . end ( ) ) ;
if ( hashIn ! = hashTmp )
return error ( " %s: Checksum mismatch, data corrupted " , __func__ ) ;
unsigned char pchMsgTmp [ 4 ] ;
try {
CHashVerifier < Stream > verifier ( & stream ) ;
// de-serialize file header (network specific magic number) and ..
ssBanlist > > FLATDATA ( pchMsgTmp ) ;
unsigned char pchMsgTmp [ 4 ] ;
verifier > > FLATDATA ( pchMsgTmp ) ;
// ... verify the network matches ours
if ( memcmp ( pchMsgTmp , Params ( ) . MessageStart ( ) , sizeof ( pchMsgTmp ) ) )
return error ( " %s: Invalid network magic number " , __func__ ) ;
// de-serialize ban data
ssBanlist > > banSet ;
// de-serialize data
verifier > > data ;
// verify checksum
if ( fCheckSum ) {
uint256 hashTmp ;
stream > > hashTmp ;
if ( hashTmp ! = verifier . GetHash ( ) ) {
return error ( " %s: Checksum mismatch, data corrupted " , __func__ ) ;
}
}
}
catch ( const std : : exception & e ) {
return error ( " %s: Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
@ -113,106 +91,56 @@ bool CBanDB::Read(banmap_t& banSet)
@@ -113,106 +91,56 @@ bool CBanDB::Read(banmap_t& banSet)
return true ;
}
CAddrDB : : CAddrDB ( )
template < typename Data >
bool DeserializeFileDB ( const fs : : path & path , Data & data )
{
pathAddr = GetDataDir ( ) / " peers.dat " ;
// open input file, and associate with CAutoFile
FILE * file = fsbridge : : fopen ( path , " rb " ) ;
CAutoFile filein ( file , SER_DISK , CLIENT_VERSION ) ;
if ( filein . IsNull ( ) )
return error ( " %s: Failed to open file %s " , __func__ , path . string ( ) ) ;
return DeserializeDB ( filein , data ) ;
}
bool CAddrDB : : Write ( const CAddrMan & addr )
{
// Generate random temporary filename
unsigned short randv = 0 ;
GetRandBytes ( ( unsigned char * ) & randv , sizeof ( randv ) ) ;
std : : string tmpfn = strprintf ( " peers.dat.%04x " , randv ) ;
}
// serialize addresses, checksum data up to that point, then append csum
CDataStream ssPeers ( SER_DISK , CLIENT_VERSION ) ;
ssPeers < < FLATDATA ( Params ( ) . MessageStart ( ) ) ;
ssPeers < < addr ;
uint256 hash = Hash ( ssPeers . begin ( ) , ssPeers . end ( ) ) ;
ssPeers < < hash ;
CBanDB : : CBanDB ( )
{
pathBanlist = GetDataDir ( ) / " banlist.dat " ;
}
// open temp output file, and associate with CAutoFile
fs : : path pathTmp = GetDataDir ( ) / tmpfn ;
FILE * file = fsbridge : : fopen ( pathTmp , " wb " ) ;
CAutoFile fileout ( file , SER_DISK , CLIENT_VERSION ) ;
if ( fileout . IsNull ( ) )
return error ( " %s: Failed to open file %s " , __func__ , pathTmp . string ( ) ) ;
bool CBanDB : : Write ( const banmap_t & banSet )
{
return SerializeFileDB ( " banlist " , pathBanlist , banSet ) ;
}
// Write and commit header, data
try {
fileout < < ssPeers ;
}
catch ( const std : : exception & e ) {
return error ( " %s: Serialize or I/O error - %s " , __func__ , e . what ( ) ) ;
}
FileCommit ( fileout . Get ( ) ) ;
fileout . fclose ( ) ;
bool CBanDB : : Read ( banmap_t & banSet )
{
return DeserializeFileDB ( pathBanlist , banSet ) ;
}
// replace existing peers.dat, if any, with new peers.dat.XXXX
if ( ! RenameOver ( pathTmp , pathAddr ) )
return error ( " %s: Rename-into-place failed " , __func__ ) ;
CAddrDB : : CAddrDB ( )
{
pathAddr = GetDataDir ( ) / " peers.dat " ;
}
return true ;
bool CAddrDB : : Write ( const CAddrMan & addr )
{
return SerializeFileDB ( " peers " , pathAddr , addr ) ;
}
bool CAddrDB : : Read ( CAddrMan & addr )
{
// open input file, and associate with CAutoFile
FILE * file = fsbridge : : fopen ( pathAddr , " rb " ) ;
CAutoFile filein ( file , SER_DISK , CLIENT_VERSION ) ;
if ( filein . IsNull ( ) )
return error ( " %s: Failed to open file %s " , __func__ , pathAddr . string ( ) ) ;
// use file size to size memory buffer
uint64_t fileSize = fs : : file_size ( pathAddr ) ;
uint64_t dataSize = 0 ;
// Don't try to resize to a negative number if file is small
if ( fileSize > = sizeof ( uint256 ) )
dataSize = fileSize - sizeof ( uint256 ) ;
std : : vector < unsigned char > vchData ;
vchData . resize ( dataSize ) ;
uint256 hashIn ;
// read data and checksum from file
try {
filein . read ( ( char * ) & vchData [ 0 ] , dataSize ) ;
filein > > hashIn ;
}
catch ( const std : : exception & e ) {
return error ( " %s: Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
}
filein . fclose ( ) ;
CDataStream ssPeers ( vchData , SER_DISK , CLIENT_VERSION ) ;
// verify stored checksum matches input data
uint256 hashTmp = Hash ( ssPeers . begin ( ) , ssPeers . end ( ) ) ;
if ( hashIn ! = hashTmp )
return error ( " %s: Checksum mismatch, data corrupted " , __func__ ) ;
return Read ( addr , ssPeers ) ;
return DeserializeFileDB ( pathAddr , addr ) ;
}
bool CAddrDB : : Read ( CAddrMan & addr , CDataStream & ssPeers )
{
unsigned char pchMsgTmp [ 4 ] ;
try {
// de-serialize file header (network specific magic number) and ..
ssPeers > > FLATDATA ( pchMsgTmp ) ;
// ... verify the network matches ours
if ( memcmp ( pchMsgTmp , Params ( ) . MessageStart ( ) , sizeof ( pchMsgTmp ) ) )
return error ( " %s: Invalid network magic number " , __func__ ) ;
// de-serialize address data into one CAddrMan object
ssPeers > > addr ;
}
catch ( const std : : exception & e ) {
// de-serialization has failed, ensure addrman is left in a clean state
bool ret = DeserializeDB ( ssPeers , addr , false ) ;
if ( ! ret ) {
// Ensure addrman is left in a clean state
addr . Clear ( ) ;
return error ( " %s: Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
}
return true ;
return ret ;
}