Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615264
addrdb.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
8 KB
Subscribers
None
addrdb.cpp
View Options
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include
<addrdb.h>
#include
<addrman.h>
#include
<chainparams.h>
#include
<clientversion.h>
#include
<hash.h>
#include
<logging/timer.h>
#include
<random.h>
#include
<streams.h>
#include
<tinyformat.h>
#include
<util/system.h>
#include
<util/translation.h>
#include
<cstdint>
namespace
{
class
DbNotFoundError
:
public
std
::
exception
{
using
std
::
exception
::
exception
;
};
template
<
typename
Stream
,
typename
Data
>
bool
SerializeDB
(
const
CChainParams
&
chainParams
,
Stream
&
stream
,
const
Data
&
data
)
{
// Write and commit header, data
try
{
CHashWriter
hasher
(
SER_DISK
,
CLIENT_VERSION
);
stream
<<
chainParams
.
DiskMagic
()
<<
data
;
hasher
<<
chainParams
.
DiskMagic
()
<<
data
;
stream
<<
hasher
.
GetHash
();
}
catch
(
const
std
::
exception
&
e
)
{
return
error
(
"%s: Serialize or I/O error - %s"
,
__func__
,
e
.
what
());
}
return
true
;
}
template
<
typename
Data
>
bool
SerializeFileDB
(
const
CChainParams
&
chainParams
,
const
std
::
string
&
prefix
,
const
fs
::
path
&
path
,
const
Data
&
data
)
{
// Generate random temporary filename
uint16_t
randv
=
0
;
GetRandBytes
((
uint8_t
*
)
&
randv
,
sizeof
(
randv
));
std
::
string
tmpfn
=
strprintf
(
"%s.%04x"
,
prefix
,
randv
);
// open temp output file, and associate with CAutoFile
fs
::
path
pathTmp
=
gArgs
.
GetDataDirNet
()
/
tmpfn
;
FILE
*
file
=
fsbridge
::
fopen
(
pathTmp
,
"wb"
);
CAutoFile
fileout
(
file
,
SER_DISK
,
CLIENT_VERSION
);
if
(
fileout
.
IsNull
())
{
fileout
.
fclose
();
remove
(
pathTmp
);
return
error
(
"%s: Failed to open file %s"
,
__func__
,
fs
::
PathToString
(
pathTmp
));
}
// Serialize
if
(
!
SerializeDB
(
chainParams
,
fileout
,
data
))
{
fileout
.
fclose
();
remove
(
pathTmp
);
return
false
;
}
if
(
!
FileCommit
(
fileout
.
Get
()))
{
fileout
.
fclose
();
remove
(
pathTmp
);
return
error
(
"%s: Failed to flush file %s"
,
__func__
,
fs
::
PathToString
(
pathTmp
));
}
fileout
.
fclose
();
// replace existing file, if any, with new file
if
(
!
RenameOver
(
pathTmp
,
path
))
{
remove
(
pathTmp
);
return
error
(
"%s: Rename-into-place failed"
,
__func__
);
}
return
true
;
}
template
<
typename
Stream
,
typename
Data
>
void
DeserializeDB
(
const
CChainParams
&
chainParams
,
Stream
&
stream
,
Data
&
data
,
bool
fCheckSum
=
true
)
{
CHashVerifier
<
Stream
>
verifier
(
&
stream
);
// de-serialize file header (network specific magic number) and ..
uint8_t
pchMsgTmp
[
4
];
verifier
>>
pchMsgTmp
;
// ... verify the network matches ours
if
(
memcmp
(
pchMsgTmp
,
std
::
begin
(
chainParams
.
DiskMagic
()),
sizeof
(
pchMsgTmp
)))
{
throw
std
::
runtime_error
{
"Invalid network magic number"
};
}
// de-serialize data
verifier
>>
data
;
// verify checksum
if
(
fCheckSum
)
{
uint256
hashTmp
;
stream
>>
hashTmp
;
if
(
hashTmp
!=
verifier
.
GetHash
())
{
throw
std
::
runtime_error
{
"Checksum mismatch, data corrupted"
};
}
}
}
template
<
typename
Data
>
void
DeserializeFileDB
(
const
CChainParams
&
chainParams
,
const
fs
::
path
&
path
,
Data
&
data
)
{
// open input file, and associate with CAutoFile
FILE
*
file
=
fsbridge
::
fopen
(
path
,
"rb"
);
CAutoFile
filein
(
file
,
SER_DISK
,
CLIENT_VERSION
);
if
(
filein
.
IsNull
())
{
throw
DbNotFoundError
{};
}
DeserializeDB
(
chainParams
,
filein
,
data
);
}
}
// namespace
CBanDB
::
CBanDB
(
fs
::
path
ban_list_path
,
const
CChainParams
&
_chainParams
)
:
m_ban_list_path
(
std
::
move
(
ban_list_path
)),
chainParams
(
_chainParams
)
{}
bool
CBanDB
::
Write
(
const
banmap_t
&
banSet
)
{
return
SerializeFileDB
(
chainParams
,
"banlist"
,
m_ban_list_path
,
banSet
);
}
bool
CBanDB
::
Read
(
banmap_t
&
banSet
)
{
// TODO: this needs to be reworked after banlist.dat is deprecated (in
// favor of banlist.json). See:
// - https://github.com/bitcoin/bitcoin/pull/20966
// - https://github.com/bitcoin/bitcoin/pull/22570
try
{
DeserializeFileDB
(
chainParams
,
m_ban_list_path
,
banSet
);
}
catch
(
const
std
::
exception
&
)
{
LogPrintf
(
"Missing or invalid file %s
\n
"
,
fs
::
quoted
(
fs
::
PathToString
(
m_ban_list_path
)));
return
false
;
}
return
true
;
}
bool
DumpPeerAddresses
(
const
CChainParams
&
chainParams
,
const
ArgsManager
&
args
,
const
AddrMan
&
addr
)
{
const
auto
pathAddr
=
args
.
GetDataDirNet
()
/
"peers.dat"
;
return
SerializeFileDB
(
chainParams
,
"peers"
,
pathAddr
,
addr
);
}
void
ReadFromStream
(
const
CChainParams
&
chainParams
,
AddrMan
&
addr
,
CDataStream
&
ssPeers
)
{
DeserializeDB
(
chainParams
,
ssPeers
,
addr
,
false
);
}
std
::
optional
<
bilingual_str
>
LoadAddrman
(
const
CChainParams
&
chainparams
,
const
std
::
vector
<
bool
>
&
asmap
,
const
ArgsManager
&
args
,
std
::
unique_ptr
<
AddrMan
>
&
addrman
)
{
auto
check_addrman
=
std
::
clamp
<
int32_t
>
(
args
.
GetIntArg
(
"-checkaddrman"
,
DEFAULT_ADDRMAN_CONSISTENCY_CHECKS
),
0
,
1000000
);
addrman
=
std
::
make_unique
<
AddrMan
>
(
asmap
,
/* consistency_check_ratio= */
check_addrman
);
int64_t
nStart
=
GetTimeMillis
();
const
auto
path_addr
{
args
.
GetDataDirNet
()
/
"peers.dat"
};
try
{
DeserializeFileDB
(
chainparams
,
path_addr
,
*
addrman
);
LogPrintf
(
"Loaded %i addresses from peers.dat %dms
\n
"
,
addrman
->
size
(),
GetTimeMillis
()
-
nStart
);
}
catch
(
const
DbNotFoundError
&
)
{
// Addrman can be in an inconsistent state after failure, reset it
addrman
=
std
::
make_unique
<
AddrMan
>
(
asmap
,
/* consistency_check_ratio= */
check_addrman
);
LogPrintf
(
"Creating peers.dat because the file was not found (%s)
\n
"
,
fs
::
quoted
(
fs
::
PathToString
(
path_addr
)));
DumpPeerAddresses
(
chainparams
,
args
,
*
addrman
);
}
catch
(
const
InvalidAddrManVersionError
&
)
{
if
(
!
RenameOver
(
path_addr
,
fs
::
path
(
path_addr
)
+
".bak"
))
{
addrman
=
nullptr
;
return
strprintf
(
_
(
"Failed to rename invalid peers.dat file. "
"Please move or delete it and try again."
));
}
// Addrman can be in an inconsistent state after failure, reset it
addrman
=
std
::
make_unique
<
AddrMan
>
(
asmap
,
/* consistency_check_ratio= */
check_addrman
);
LogPrintf
(
"Creating new peers.dat because the file version was not "
"compatible (%s). Original backed up to peers.dat.bak
\n
"
,
fs
::
quoted
(
fs
::
PathToString
(
path_addr
)));
DumpPeerAddresses
(
chainparams
,
args
,
*
addrman
);
}
catch
(
const
std
::
exception
&
e
)
{
addrman
=
nullptr
;
return
strprintf
(
_
(
"Invalid or corrupt peers.dat (%s)
.
If
you
believe
this
is
a
"
"bug, please report it to %s. As a workaround, you can move the "
"file (%s) out of the way (rename, move, or delete) to have a "
"new one created on the next start."
),
e
.
what
(),
PACKAGE_BUGREPORT
,
fs
::
quoted
(
fs
::
PathToString
(
path_addr
)));
}
return
std
::
nullopt
;
}
void
DumpAnchors
(
const
CChainParams
&
chainParams
,
const
fs
::
path
&
anchors_db_path
,
const
std
::
vector
<
CAddress
>
&
anchors
)
{
LOG_TIME_SECONDS
(
strprintf
(
"Flush %d outbound block-relay-only peer addresses to anchors.dat"
,
anchors
.
size
()));
SerializeFileDB
(
chainParams
,
"anchors"
,
anchors_db_path
,
anchors
);
}
std
::
vector
<
CAddress
>
ReadAnchors
(
const
CChainParams
&
chainParams
,
const
fs
::
path
&
anchors_db_path
)
{
std
::
vector
<
CAddress
>
anchors
;
try
{
DeserializeFileDB
(
chainParams
,
anchors_db_path
,
anchors
);
LogPrintf
(
"Loaded %i addresses from %s
\n
"
,
anchors
.
size
(),
fs
::
quoted
(
fs
::
PathToString
(
anchors_db_path
.
filename
())));
}
catch
(
const
std
::
exception
&
)
{
anchors
.
clear
();
}
fs
::
remove
(
anchors_db_path
);
return
anchors
;
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 23, 10:03 (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4511874
Default Alt Text
addrdb.cpp (8 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment