Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
Josh Wilcox
crown-core
Commits
62efb315
Commit
62efb315
authored
13 years ago
by
Gavin Andresen
Browse files
Options
Download
Email Patches
Plain Diff
DoS fix for mapOrphanTransactions
parent
55ba5ffe
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/main.cpp
+24
-1
src/main.cpp
src/main.h
+1
-0
src/main.h
src/test/DoS_tests.cpp
+79
-0
src/test/DoS_tests.cpp
with
104 additions
and
1 deletion
+104
-1
src/main.cpp
View file @
62efb315
...
...
@@ -167,13 +167,14 @@ void static ResendWalletTransactions()
// mapOrphanTransactions
//
void
static
AddOrphanTx(const CDataStream& vMsg)
void
AddOrphanTx
(
const
CDataStream
&
vMsg
)
{
CTransaction
tx
;
CDataStream
(
vMsg
)
>>
tx
;
uint256
hash
=
tx
.
GetHash
();
if
(
mapOrphanTransactions
.
count
(
hash
))
return
;
CDataStream
*
pvMsg
=
mapOrphanTransactions
[
hash
]
=
new
CDataStream
(
vMsg
);
BOOST_FOREACH
(
const
CTxIn
&
txin
,
tx
.
vin
)
mapOrphanTransactionsByPrev
.
insert
(
make_pair
(
txin
.
prevout
.
hash
,
pvMsg
));
...
...
@@ -201,6 +202,23 @@ void static EraseOrphanTx(uint256 hash)
mapOrphanTransactions
.
erase
(
hash
);
}
int
LimitOrphanTxSize
(
int
nMaxOrphans
)
{
int
nEvicted
=
0
;
while
(
mapOrphanTransactions
.
size
()
>
nMaxOrphans
)
{
// Evict a random orphan:
std
::
vector
<
unsigned
char
>
randbytes
(
32
);
RAND_bytes
(
&
randbytes
[
0
],
32
);
uint256
randomhash
(
randbytes
);
map
<
uint256
,
CDataStream
*>::
iterator
it
=
mapOrphanTransactions
.
lower_bound
(
randomhash
);
if
(
it
==
mapOrphanTransactions
.
end
())
it
=
mapOrphanTransactions
.
begin
();
EraseOrphanTx
(
it
->
first
);
++
nEvicted
;
}
return
nEvicted
;
}
...
...
@@ -2473,6 +2491,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
printf
(
"storing orphan tx %s
\n
"
,
inv
.
hash
.
ToString
().
substr
(
0
,
10
).
c_str
());
AddOrphanTx
(
vMsg
);
// DoS prevention: do not allow mapOrphanTransactions to grow unbounded
int
nEvicted
=
LimitOrphanTxSize
(
MAX_ORPHAN_TRANSACTIONS
);
if
(
nEvicted
>
0
)
printf
(
"mapOrphan overflow, removed %d tx
\n
"
,
nEvicted
);
}
if
(
tx
.
nDoS
)
pfrom
->
Misbehaving
(
tx
.
nDoS
);
}
...
...
This diff is collapsed.
Click to expand it.
src/main.h
View file @
62efb315
...
...
@@ -33,6 +33,7 @@ extern const std::string CLIENT_NAME;
static
const
unsigned
int
MAX_BLOCK_SIZE
=
1000000
;
static
const
unsigned
int
MAX_BLOCK_SIZE_GEN
=
MAX_BLOCK_SIZE
/
2
;
static
const
int
MAX_BLOCK_SIGOPS
=
MAX_BLOCK_SIZE
/
50
;
static
const
int
MAX_ORPHAN_TRANSACTIONS
=
MAX_BLOCK_SIZE
/
100
;
static
const
int64
COIN
=
100000000
;
static
const
int64
CENT
=
1000000
;
static
const
int64
MIN_TX_FEE
=
50000
;
...
...
This diff is collapsed.
Click to expand it.
src/test/DoS_tests.cpp
View file @
62efb315
...
...
@@ -12,6 +12,12 @@
#include <stdint.h>
// Tests this internal-to-main.cpp method:
extern
void
AddOrphanTx
(
const
CDataStream
&
vMsg
);
extern
int
LimitOrphanTxSize
(
int
nMaxOrphans
);
extern
std
::
map
<
uint256
,
CDataStream
*>
mapOrphanTransactions
;
extern
std
::
multimap
<
uint256
,
CDataStream
*>
mapOrphanTransactionsByPrev
;
CService
ip
(
uint32_t
i
)
{
struct
in_addr
s
;
...
...
@@ -123,4 +129,77 @@ BOOST_AUTO_TEST_CASE(DoS_checknbits)
}
static
uint256
RandomHash
()
{
std
::
vector
<
unsigned
char
>
randbytes
(
32
);
RAND_bytes
(
&
randbytes
[
0
],
32
);
uint256
randomhash
(
randbytes
);
return
randomhash
;
}
CTransaction
RandomOrphan
()
{
std
::
map
<
uint256
,
CDataStream
*>::
iterator
it
;
it
=
mapOrphanTransactions
.
lower_bound
(
RandomHash
());
if
(
it
==
mapOrphanTransactions
.
end
())
it
=
mapOrphanTransactions
.
begin
();
const
CDataStream
*
pvMsg
=
it
->
second
;
CTransaction
tx
;
CDataStream
(
*
pvMsg
)
>>
tx
;
return
tx
;
}
BOOST_AUTO_TEST_CASE
(
DoS_mapOrphans
)
{
CKey
key
;
key
.
MakeNewKey
(
true
);
CBasicKeyStore
keystore
;
keystore
.
AddKey
(
key
);
// 50 orphan transactions:
for
(
int
i
=
0
;
i
<
50
;
i
++
)
{
CTransaction
tx
;
tx
.
vin
.
resize
(
1
);
tx
.
vin
[
0
].
prevout
.
n
=
0
;
tx
.
vin
[
0
].
prevout
.
hash
=
RandomHash
();
tx
.
vin
[
0
].
scriptSig
<<
OP_1
;
tx
.
vout
.
resize
(
1
);
tx
.
vout
[
0
].
nValue
=
1
*
CENT
;
tx
.
vout
[
0
].
scriptPubKey
.
SetBitcoinAddress
(
key
.
GetPubKey
());
CDataStream
ds
;
ds
<<
tx
;
AddOrphanTx
(
ds
);
}
// ... and 50 that depend on other orphans:
for
(
int
i
=
0
;
i
<
50
;
i
++
)
{
CTransaction
txPrev
=
RandomOrphan
();
CTransaction
tx
;
tx
.
vin
.
resize
(
1
);
tx
.
vin
[
0
].
prevout
.
n
=
0
;
tx
.
vin
[
0
].
prevout
.
hash
=
txPrev
.
GetHash
();
tx
.
vout
.
resize
(
1
);
tx
.
vout
[
0
].
nValue
=
1
*
CENT
;
tx
.
vout
[
0
].
scriptPubKey
.
SetBitcoinAddress
(
key
.
GetPubKey
());
SignSignature
(
keystore
,
txPrev
,
tx
,
0
);
CDataStream
ds
;
ds
<<
tx
;
AddOrphanTx
(
ds
);
}
// Test LimitOrphanTxSize() function:
LimitOrphanTxSize
(
40
);
BOOST_CHECK
(
mapOrphanTransactions
.
size
()
<=
40
);
LimitOrphanTxSize
(
10
);
BOOST_CHECK
(
mapOrphanTransactions
.
size
()
<=
10
);
LimitOrphanTxSize
(
0
);
BOOST_CHECK
(
mapOrphanTransactions
.
empty
());
BOOST_CHECK
(
mapOrphanTransactionsByPrev
.
empty
());
}
BOOST_AUTO_TEST_SUITE_END
()
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help