Skip to content

Commit c8beb7f

Browse files
Merge dashpay#6688: backport: Merge bitcoin#27480, 27664, 27334, 27930, 27831
c781f1a (Partial) Merge bitcoin#27831: test: handle failed `assert_equal()` assertions in bcc callback functions (fanquake) 3b3fdaa Merge bitcoin#27930: util: Don't derive secure_allocator from std::allocator (Andrew Chow) 0ad41d1 Merge bitcoin#27334: util: implement `noexcept` move assignment & move ctor for `prevector` (Andrew Chow) 9a390dd Merge bitcoin#27664: docs: fix spelling errors (fanquake) 2a5616e Merge bitcoin#27480: doc: Improve documentation of rpcallowip (Andrew Chow) Pull request description: backport ACKs for top commit: UdjinM6: utACK c781f1a UdjinM6: re-utACK c781f1a Tree-SHA512: 939486f8f5d0280bec16e0d5772281ba0927c7f136cddb06fb41a022f931bfcfb6620484cec61fa675cbb8b7ca558d52639113400ea76cf77cd4a1c0933a0f33
2 parents ae771ac + c781f1a commit c8beb7f

File tree

10 files changed

+139
-75
lines changed

10 files changed

+139
-75
lines changed

src/bench/prevector.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,30 @@ static void PrevectorAssignTo(benchmark::Bench& bench)
107107
});
108108
}
109109

110+
template <typename T>
111+
static void PrevectorFillVectorDirect(benchmark::Bench& bench)
112+
{
113+
bench.run([&] {
114+
std::vector<prevector<28, T>> vec;
115+
for (size_t i = 0; i < 260; ++i) {
116+
vec.emplace_back();
117+
}
118+
});
119+
}
120+
121+
122+
template <typename T>
123+
static void PrevectorFillVectorIndirect(benchmark::Bench& bench)
124+
{
125+
bench.run([&] {
126+
std::vector<prevector<28, T>> vec;
127+
for (size_t i = 0; i < 260; ++i) {
128+
// force allocation
129+
vec.emplace_back(29, T{});
130+
}
131+
});
132+
}
133+
110134
#define PREVECTOR_TEST(name) \
111135
static void Prevector##name##Nontrivial(benchmark::Bench& bench) \
112136
{ \
@@ -126,3 +150,5 @@ PREVECTOR_TEST(Deserialize)
126150

127151
BENCHMARK(PrevectorAssign)
128152
BENCHMARK(PrevectorAssignTo)
153+
PREVECTOR_TEST(FillVectorDirect)
154+
PREVECTOR_TEST(FillVectorIndirect)

src/init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ void SetupServerArgs(ArgsManager& argsman)
771771
argsman.AddArg("-blockversion=<n>", "Override block version to test forking scenarios", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
772772

773773
argsman.AddArg("-rest", strprintf("Accept public REST requests (default: %u)", DEFAULT_REST_ENABLE), ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
774-
argsman.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24). This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
774+
argsman.AddArg("-rpcallowip=<ip>", "Allow JSON-RPC connections from specified source. Valid values for <ip> are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0), a network/CIDR (e.g. 1.2.3.4/24), all ipv4 (0.0.0.0/0), or all ipv6 (::/0). This option can be specified multiple times", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);
775775
argsman.AddArg("-rpcauth=<userpw>", "Username and HMAC-SHA-256 hashed password for JSON-RPC connections. The field <userpw> comes in the format: <USERNAME>:<SALT>$<HASH>. A canonical python script is included in share/rpcuser. The client then connects normally using the rpcuser=<USERNAME>/rpcpassword=<PASSWORD> pair of arguments. This option can be specified multiple times", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
776776
argsman.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost, or if -rpcallowip has been specified, 0.0.0.0 and :: i.e., all addresses)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY | ArgsManager::SENSITIVE, OptionsCategory::RPC);
777777
argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::RPC);

src/prevector.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,10 @@ class prevector {
286286
fill(item_ptr(0), other.begin(), other.end());
287287
}
288288

289-
prevector(prevector<N, T, Size, Diff>&& other) {
290-
swap(other);
289+
prevector(prevector<N, T, Size, Diff>&& other) noexcept
290+
: _union(std::move(other._union)), _size(other._size)
291+
{
292+
other._size = 0;
291293
}
292294

293295
prevector& operator=(const prevector<N, T, Size, Diff>& other) {
@@ -298,8 +300,13 @@ class prevector {
298300
return *this;
299301
}
300302

301-
prevector& operator=(prevector<N, T, Size, Diff>&& other) {
302-
swap(other);
303+
prevector& operator=(prevector<N, T, Size, Diff>&& other) noexcept {
304+
if (!is_direct()) {
305+
free(_union.indirect_contents.indirect);
306+
}
307+
_union = std::move(other._union);
308+
_size = other._size;
309+
other._size = 0;
303310
return *this;
304311
}
305312

src/support/allocators/secure.h

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,14 @@
1818
// out of memory and clears its contents before deletion.
1919
//
2020
template <typename T>
21-
struct secure_allocator : public std::allocator<T> {
22-
using base = std::allocator<T>;
23-
using traits = std::allocator_traits<base>;
24-
using size_type = typename traits::size_type;
25-
using difference_type = typename traits::difference_type;
26-
using pointer = typename traits::pointer;
27-
using const_pointer = typename traits::const_pointer;
28-
using value_type = typename traits::value_type;
29-
secure_allocator() noexcept {}
30-
secure_allocator(const secure_allocator& a) noexcept : base(a) {}
21+
struct secure_allocator {
22+
using value_type = T;
23+
24+
secure_allocator() = default;
3125
template <typename U>
32-
secure_allocator(const secure_allocator<U>& a) noexcept : base(a)
33-
{
34-
}
35-
~secure_allocator() noexcept {}
36-
template <typename _Other>
37-
struct rebind {
38-
typedef secure_allocator<_Other> other;
39-
};
26+
secure_allocator(const secure_allocator<U>&) noexcept {}
4027

41-
T* allocate(std::size_t n, const void* hint = nullptr)
28+
T* allocate(std::size_t n)
4229
{
4330
T* allocation = static_cast<T*>(LockedPoolManager::Instance().alloc(sizeof(T) * n));
4431
if (!allocation) {
@@ -54,6 +41,17 @@ struct secure_allocator : public std::allocator<T> {
5441
}
5542
LockedPoolManager::Instance().free(p);
5643
}
44+
45+
template <typename U>
46+
friend bool operator==(const secure_allocator&, const secure_allocator<U>&) noexcept
47+
{
48+
return true;
49+
}
50+
template <typename U>
51+
friend bool operator!=(const secure_allocator&, const secure_allocator<U>&) noexcept
52+
{
53+
return false;
54+
}
5755
};
5856

5957
// This is exactly like std::string, but with a custom allocator.

src/support/allocators/zeroafterfree.h

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,36 @@
1212
#include <vector>
1313

1414
template <typename T>
15-
struct zero_after_free_allocator : public std::allocator<T> {
16-
using base = std::allocator<T>;
17-
using traits = std::allocator_traits<base>;
18-
using size_type = typename traits::size_type;
19-
using difference_type = typename traits::difference_type;
20-
using pointer = typename traits::pointer;
21-
using const_pointer = typename traits::const_pointer;
22-
using value_type = typename traits::value_type;
23-
zero_after_free_allocator() noexcept {}
24-
zero_after_free_allocator(const zero_after_free_allocator& a) noexcept : base(a) {}
15+
struct zero_after_free_allocator {
16+
using value_type = T;
17+
18+
zero_after_free_allocator() noexcept = default;
2519
template <typename U>
26-
zero_after_free_allocator(const zero_after_free_allocator<U>& a) noexcept : base(a)
20+
zero_after_free_allocator(const zero_after_free_allocator<U>&) noexcept
21+
{
22+
}
23+
24+
T* allocate(std::size_t n)
2725
{
26+
return std::allocator<T>{}.allocate(n);
2827
}
29-
~zero_after_free_allocator() noexcept {}
30-
template <typename _Other>
31-
struct rebind {
32-
typedef zero_after_free_allocator<_Other> other;
33-
};
3428

3529
void deallocate(T* p, std::size_t n)
3630
{
3731
if (p != nullptr)
3832
memory_cleanse(p, sizeof(T) * n);
39-
std::allocator<T>::deallocate(p, n);
33+
std::allocator<T>{}.deallocate(p, n);
34+
}
35+
36+
template <typename U>
37+
friend bool operator==(const zero_after_free_allocator&, const zero_after_free_allocator<U>&) noexcept
38+
{
39+
return true;
40+
}
41+
template <typename U>
42+
friend bool operator!=(const zero_after_free_allocator&, const zero_after_free_allocator<U>&) noexcept
43+
{
44+
return false;
4045
}
4146
};
4247

src/validation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <stdint.h>
3939
#include <string>
4040
#include <thread>
41+
#include <type_traits>
4142
#include <utility>
4243
#include <vector>
4344

@@ -338,6 +339,11 @@ class CScriptCheck
338339
ScriptError GetScriptError() const { return error; }
339340
};
340341

342+
// CScriptCheck is used a lot in std::vector, make sure that's efficient
343+
static_assert(std::is_nothrow_move_assignable_v<CScriptCheck>);
344+
static_assert(std::is_nothrow_move_constructible_v<CScriptCheck>);
345+
static_assert(std::is_nothrow_destructible_v<CScriptCheck>);
346+
341347
/** Initializes the script-execution cache */
342348
void InitScriptExecutionCache();
343349

test/functional/interface_usdt_net.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,10 @@ def __repr__(self):
116116
fn_name="trace_outbound_message")
117117
bpf = BPF(text=net_tracepoints_program, usdt_contexts=[ctx], debug=0, cflags=["-Wno-error=implicit-function-declaration"])
118118

119-
# The handle_* function is a ctypes callback function called from C. When
120-
# we assert in the handle_* function, the AssertError doesn't propagate
121-
# back to Python. The exception is ignored. We manually count and assert
122-
# that the handle_* functions succeeded.
123119
EXPECTED_INOUTBOUND_VERSION_MSG = 1
124120
checked_inbound_version_msg = 0
125121
checked_outbound_version_msg = 0
122+
events = []
126123

127124
def check_p2p_message(event, inbound):
128125
nonlocal checked_inbound_version_msg, checked_outbound_version_msg
@@ -142,12 +139,13 @@ def check_p2p_message(event, inbound):
142139
checked_outbound_version_msg += 1
143140

144141
def handle_inbound(_, data, __):
142+
nonlocal events
145143
event = ctypes.cast(data, ctypes.POINTER(P2PMessage)).contents
146-
check_p2p_message(event, True)
144+
events.append((event, True))
147145

148146
def handle_outbound(_, data, __):
149147
event = ctypes.cast(data, ctypes.POINTER(P2PMessage)).contents
150-
check_p2p_message(event, False)
148+
events.append((event, False))
151149

152150
bpf["inbound_messages"].open_perf_buffer(handle_inbound)
153151
bpf["outbound_messages"].open_perf_buffer(handle_outbound)
@@ -158,12 +156,15 @@ def handle_outbound(_, data, __):
158156
bpf.perf_buffer_poll(timeout=200)
159157

160158
self.log.info(
161-
"check that we got both an inbound and outbound version message")
159+
"check receipt and content of in- and outbound version messages")
160+
for event, inbound in events:
161+
check_p2p_message(event, inbound)
162162
assert_equal(EXPECTED_INOUTBOUND_VERSION_MSG,
163163
checked_inbound_version_msg)
164164
assert_equal(EXPECTED_INOUTBOUND_VERSION_MSG,
165165
checked_outbound_version_msg)
166166

167+
167168
bpf.cleanup()
168169

169170

test/functional/interface_usdt_utxocache.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,16 @@ def handle_utxocache_uncache(_, data, __):
190190
nonlocal handle_uncache_succeeds
191191
event = ctypes.cast(data, ctypes.POINTER(UTXOCacheChange)).contents
192192
self.log.info(f"handle_utxocache_uncache(): {event}")
193-
assert_equal(block_1_coinbase_txid, bytes(event.txid[::-1]).hex())
194-
assert_equal(0, event.index) # prevout index
195-
assert_equal(EARLY_BLOCK_HEIGHT, event.height)
196-
assert_equal(500 * COIN, event.value)
197-
assert_equal(True, event.is_coinbase)
198-
199-
handle_uncache_succeeds += 1
193+
try:
194+
assert_equal(block_1_coinbase_txid, bytes(event.txid[::-1]).hex())
195+
assert_equal(0, event.index) # prevout index
196+
assert_equal(EARLY_BLOCK_HEIGHT, event.height)
197+
assert_equal(50 * COIN, event.value)
198+
assert_equal(True, event.is_coinbase)
199+
except AssertionError:
200+
self.log.exception("Assertion failed")
201+
else:
202+
handle_uncache_succeeds += 1
200203

201204
bpf["utxocache_uncache"].open_perf_buffer(handle_utxocache_uncache)
202205

@@ -262,24 +265,32 @@ def handle_utxocache_add(_, data, __):
262265
event = ctypes.cast(data, ctypes.POINTER(UTXOCacheChange)).contents
263266
self.log.info(f"handle_utxocache_add(): {event}")
264267
add = expected_utxocache_adds.pop(0)
265-
assert_equal(add["txid"], bytes(event.txid[::-1]).hex())
266-
assert_equal(add["index"], event.index)
267-
assert_equal(add["height"], event.height)
268-
assert_equal(add["value"], event.value)
269-
assert_equal(add["is_coinbase"], event.is_coinbase)
270-
handle_add_succeeds += 1
268+
try:
269+
assert_equal(add["txid"], bytes(event.txid[::-1]).hex())
270+
assert_equal(add["index"], event.index)
271+
assert_equal(add["height"], event.height)
272+
assert_equal(add["value"], event.value)
273+
assert_equal(add["is_coinbase"], event.is_coinbase)
274+
except AssertionError:
275+
self.log.exception("Assertion failed")
276+
else:
277+
handle_add_succeeds += 1
271278

272279
def handle_utxocache_spent(_, data, __):
273280
nonlocal handle_spent_succeeds
274281
event = ctypes.cast(data, ctypes.POINTER(UTXOCacheChange)).contents
275282
self.log.info(f"handle_utxocache_spent(): {event}")
276283
spent = expected_utxocache_spents.pop(0)
277-
assert_equal(spent["txid"], bytes(event.txid[::-1]).hex())
278-
assert_equal(spent["index"], event.index)
279-
assert_equal(spent["height"], event.height)
280-
assert_equal(spent["value"], event.value)
281-
assert_equal(spent["is_coinbase"], event.is_coinbase)
282-
handle_spent_succeeds += 1
284+
try:
285+
assert_equal(spent["txid"], bytes(event.txid[::-1]).hex())
286+
assert_equal(spent["index"], event.index)
287+
assert_equal(spent["height"], event.height)
288+
assert_equal(spent["value"], event.value)
289+
assert_equal(spent["is_coinbase"], event.is_coinbase)
290+
except AssertionError:
291+
self.log.exception("Assertion failed")
292+
else:
293+
handle_spent_succeeds += 1
283294

284295
bpf["utxocache_add"].open_perf_buffer(handle_utxocache_add)
285296
bpf["utxocache_spent"].open_perf_buffer(handle_utxocache_spent)
@@ -364,7 +375,7 @@ def handle_utxocache_flush(_, data, __):
364375
bpf["utxocache_flush"].open_perf_buffer(handle_utxocache_flush)
365376

366377
self.log.info("stop the node to flush the UTXO cache")
367-
UTXOS_IN_CACHE = 104 # might need to be changed if the eariler tests are modified
378+
UTXOS_IN_CACHE = 104 # might need to be changed if the earlier tests are modified
368379
# A node shutdown causes two flushes. One that flushes UTXOS_IN_CACHE
369380
# UTXOs and one that flushes 0 UTXOs. Normally the 0-UTXO-flush is the
370381
# second flush, however it can happen that the order changes.

test/functional/interface_usdt_validation.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,10 @@ def __repr__(self):
8585
self.sigops,
8686
self.duration)
8787

88-
# The handle_* function is a ctypes callback function called from C. When
89-
# we assert in the handle_* function, the AssertError doesn't propagate
90-
# back to Python. The exception is ignored. We manually count and assert
91-
# that the handle_* functions succeeded.
9288
BLOCKS_EXPECTED = 2
9389
blocks_checked = 0
9490
expected_blocks = dict()
91+
events = []
9592

9693
self.log.info("hook into the validation:block_connected tracepoint")
9794
ctx = USDT(path=str(self.options.bitcoind))
@@ -101,7 +98,7 @@ def __repr__(self):
10198
usdt_contexts=[ctx], debug=0, cflags=["-Wno-error=implicit-function-declaration"])
10299

103100
def handle_blockconnected(_, data, __):
104-
nonlocal expected_blocks, blocks_checked
101+
nonlocal events, blocks_checked
105102
event = ctypes.cast(data, ctypes.POINTER(Block)).contents
106103
self.log.info(f"handle_blockconnected(): {event}")
107104
block_hash = bytes(event.hash[::-1]).hex()
@@ -126,12 +123,24 @@ def handle_blockconnected(_, data, __):
126123
expected_blocks[block_hash] = self.nodes[0].getblock(block_hash, 2)
127124

128125
bpf.perf_buffer_poll(timeout=200)
129-
bpf.cleanup()
130126

131-
self.log.info(f"check that we traced {BLOCKS_EXPECTED} blocks")
127+
self.log.info(f"check that we correctly traced {BLOCKS_EXPECTED} blocks")
128+
for event in events:
129+
block_hash = bytes(event.hash[::-1]).hex()
130+
block = expected_blocks[block_hash]
131+
assert_equal(block["hash"], block_hash)
132+
assert_equal(block["height"], event.height)
133+
assert_equal(len(block["tx"]), event.transactions)
134+
assert_equal(len([tx["vin"] for tx in block["tx"]]), event.inputs)
135+
assert_equal(0, event.sigops) # no sigops in coinbase tx
136+
# only plausibility checks
137+
assert event.duration > 0
138+
del expected_blocks[block_hash]
132139
assert_equal(BLOCKS_EXPECTED, blocks_checked)
133140
assert_equal(0, len(expected_blocks))
134141

142+
bpf.cleanup()
143+
135144

136145
if __name__ == '__main__':
137146
ValidationTracepointTest().main()

test/lint/spelling.ignore-words.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ hights
1010
hist
1111
inout
1212
invokable
13+
lief
1314
mor
1415
nin
1516
ser

0 commit comments

Comments
 (0)