Skip to content

Commit c352d28

Browse files
authored
Merge pull request #1117 from AntelopeIO/104_security_main
[1.0.4 -> main] consolidated security fixes for 1.0.4
2 parents ade9af4 + e7b5e8b commit c352d28

File tree

3 files changed

+85
-23
lines changed

3 files changed

+85
-23
lines changed

plugins/producer_plugin/producer_plugin.cpp

+21-19
Original file line numberDiff line numberDiff line change
@@ -1479,29 +1479,31 @@ void producer_plugin_impl::plugin_initialize(const boost::program_options::varia
14791479
plugin_config_exception,
14801480
"read-only-read-window-time-us (${read}) must be at least greater than ${min} us",
14811481
("read", _ro_read_window_time_us)("min", _ro_read_window_minimum_time_us));
1482-
_ro_read_window_effective_time_us = _ro_read_window_time_us - _ro_read_window_minimum_time_us;
1483-
1482+
_ro_read_window_effective_time_us = _ro_read_window_time_us;
14841483
ilog("read-only-write-window-time-us: ${ww} us, read-only-read-window-time-us: ${rw} us, effective read window time to be used: ${w} us",
14851484
("ww", _ro_write_window_time_us)("rw", _ro_read_window_time_us)("w", _ro_read_window_effective_time_us));
1486-
}
1487-
app().executor().init_read_threads(_ro_thread_pool_size);
1485+
// Make sure _ro_max_trx_time_us is always set.
1486+
// Make sure a read-only transaction can finish within the read
1487+
// window if scheduled at the very beginning of the window.
1488+
if (_max_transaction_time_ms.load() > 0) {
1489+
_ro_max_trx_time_us = fc::milliseconds(_max_transaction_time_ms.load());
1490+
} else {
1491+
// max-transaction-time can be set to negative for unlimited time
1492+
_ro_max_trx_time_us = fc::microseconds::maximum();
1493+
}
1494+
// Factor _ro_read_window_minimum_time_us into _ro_max_trx_time_us
1495+
// such that a transaction which runs less than or equal to _ro_max_trx_time_us
1496+
// can fit in effective read-only window
1497+
assert(_ro_read_window_effective_time_us > _ro_read_window_minimum_time_us);
1498+
if (_ro_max_trx_time_us > _ro_read_window_effective_time_us - _ro_read_window_minimum_time_us) {
1499+
_ro_max_trx_time_us = _ro_read_window_effective_time_us - _ro_read_window_minimum_time_us;
1500+
}
1501+
ilog("Read-only max transaction time ${rot}us set to fit in the effective read-only window ${row}us.",
1502+
("rot", _ro_max_trx_time_us)("row", _ro_read_window_effective_time_us));
1503+
ilog("read-only-threads ${s}, max read-only trx time to be enforced: ${t} us", ("s", _ro_thread_pool_size)("t", _ro_max_trx_time_us));
14881504

1489-
// Make sure _ro_max_trx_time_us is always set.
1490-
// Make sure a read-only transaction can finish within the read
1491-
// window if scheduled at the very beginning of the window.
1492-
// Add _ro_read_window_minimum_time_us for safety margin.
1493-
if (_max_transaction_time_ms.load() > 0) {
1494-
_ro_max_trx_time_us = fc::milliseconds(_max_transaction_time_ms.load());
1495-
} else {
1496-
// max-transaction-time can be set to negative for unlimited time
1497-
_ro_max_trx_time_us = fc::microseconds::maximum();
1498-
}
1499-
if (_ro_max_trx_time_us > _ro_read_window_effective_time_us) {
1500-
_ro_max_trx_time_us = _ro_read_window_effective_time_us;
1505+
app().executor().init_read_threads(_ro_thread_pool_size);
15011506
}
1502-
ilog("Read-only max transaction time ${rot}us set to fit in the effective read-only window ${row}us.",
1503-
("rot", _ro_max_trx_time_us)("row", _ro_read_window_effective_time_us));
1504-
ilog("read-only-threads ${s}, max read-only trx time to be enforced: ${t} us", ("s", _ro_thread_pool_size)("t", _ro_max_trx_time_us));
15051507

15061508
_incoming_block_sync_provider = app().get_method<incoming::methods::block_sync>().register_provider(
15071509
[this](const signed_block_ptr& block, const block_id_type& block_id, const block_handle& bh) {

tests/CMakeLists.txt

+3-3
Original file line numberDiff line numberDiff line change
@@ -212,13 +212,13 @@ add_test(NAME compute_transaction_test COMMAND tests/compute_transaction_test.py
212212
set_property(TEST compute_transaction_test PROPERTY LABELS nonparallelizable_tests)
213213
add_test(NAME read-only-trx-basic-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 1 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
214214
set_property(TEST read-only-trx-basic-test PROPERTY LABELS nonparallelizable_tests)
215-
add_test(NAME read-only-trx-parallel-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 16 --num-test-runs 3 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
215+
add_test(NAME read-only-trx-parallel-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 16 --num-test-runs 2 ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
216216
set_property(TEST read-only-trx-parallel-test PROPERTY LABELS nonparallelizable_tests)
217217
add_test(NAME read-only-trx-basic-if-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 1 --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
218218
set_property(TEST read-only-trx-basic-if-test PROPERTY LABELS nonparallelizable_tests)
219-
add_test(NAME read-only-trx-parallel-if-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 16 --num-test-runs 3 --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
219+
add_test(NAME read-only-trx-parallel-if-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --read-only-threads 16 --num-test-runs 2 --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
220220
set_property(TEST read-only-trx-parallel-if-test PROPERTY LABELS nonparallelizable_tests)
221-
add_test(NAME read-only-trx-parallel-if-eos-vm-oc-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --eos-vm-oc-enable all --read-only-threads 16 --num-test-runs 3 --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
221+
add_test(NAME read-only-trx-parallel-if-eos-vm-oc-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --eos-vm-oc-enable all --read-only-threads 16 --num-test-runs 2 --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
222222
set_property(TEST read-only-trx-parallel-if-eos-vm-oc-test PROPERTY LABELS nonparallelizable_tests)
223223
add_test(NAME read-only-trx-parallel-no-oc-if-test COMMAND tests/read_only_trx_test.py -p 2 -n 3 --eos-vm-oc-enable none --read-only-threads 6 --num-test-runs 2 --activate-if ${UNSHARE} WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
224224
set_property(TEST read-only-trx-parallel-no-oc-if-test PROPERTY LABELS nonparallelizable_tests)

tests/read_only_trx_test.py

+61-1
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@ def sendReadOnlyPayloadless():
210210
def sendReadOnlySlowPayloadless():
211211
return sendTransaction('payloadless', action='doitslow', data={}, auth=[], opts='--read')
212212

213+
def sendReadOnlyForeverPayloadless():
214+
return sendTransaction('payloadless', action='doitforever', data={}, auth=[], opts='--read')
215+
213216
# Send read-only trxs from mutltiple threads to bump load
214217
def sendReadOnlyTrxOnThread(startId, numTrxs):
215218
Print("start sendReadOnlyTrxOnThread")
@@ -283,7 +286,7 @@ def runReadOnlyTrxAndRpcInParallel(resource, command, fieldIn=None, expectedValu
283286
def mixedOpsTest(opt=None):
284287
Print("mixedOpsTest -- opt = ", opt)
285288

286-
numRuns = 200
289+
numRuns = 100
287290
readOnlyThread = threading.Thread(target = sendReadOnlyTrxOnThread, args = (0, numRuns ))
288291
readOnlyThread.start()
289292
sendTrxThread = threading.Thread(target = sendTrxsOnThread, args = (numRuns, numRuns, opt))
@@ -373,6 +376,60 @@ def runEverythingParallel():
373376
for thr in threadList:
374377
thr.join()
375378

379+
def fastTransactions():
380+
Print("fastTransactions")
381+
for i in range(1000):
382+
result = sendReadOnlyPayloadless()
383+
assert(result[0])
384+
385+
def slowTransactions():
386+
Print("slowTransactions")
387+
for i in range(100): # run fewer number than regular Payloadless so total running time is close
388+
result = sendReadOnlySlowPayloadless()
389+
assert(result[0])
390+
391+
def foreverTransactions():
392+
Print("foreverTransactions")
393+
for i in range(5): # run fewer number than slowPayloadless so total running time is close
394+
result = sendReadOnlyForeverPayloadless()
395+
assert(result[0] == False) # should fail
396+
397+
def timeoutTest():
398+
Print("timeoutTest")
399+
400+
# Send a forever readonly transaction. It should timeout
401+
Print("Sending a forever read only transaction")
402+
results = sendReadOnlyForeverPayloadless()
403+
# Results look like
404+
'''
405+
( False,
406+
{'processed':
407+
{
408+
...
409+
'except': {'code': 3080004, 'name': 'tx_cpu_usage_exceeded', 'message': 'Transaction exceeded the current CPU usage limit imposed on the transaction' ...}
410+
...
411+
}
412+
}
413+
)
414+
'''
415+
assert(results[0] == False)
416+
assert('except' in results[1]['processed'])
417+
assert(results[1]['processed']['except']['code'] == 3080004)
418+
assert(results[1]['processed']['except']['name'] == "tx_cpu_usage_exceeded")
419+
420+
# Send multiple different speeds of read only transactions simutaneously
421+
# to trigger forever transactions are exhausted in read window but RETRYING
422+
# at next round.
423+
threadList = []
424+
threadList.append(threading.Thread(target = fastTransactions))
425+
threadList.append(threading.Thread(target = slowTransactions))
426+
threadList.append(threading.Thread(target = foreverTransactions))
427+
Print("Sending different speeds of read only transactions simutaneously")
428+
for thr in threadList:
429+
thr.start()
430+
for thr in threadList:
431+
thr.join()
432+
376433
try:
377434
startCluster()
378435
deployTestContracts()
@@ -387,6 +444,9 @@ def runEverythingParallel():
387444
mixedOpsTest()
388445
runEverythingParallel()
389446

447+
# should be running under multiple threads but no need to run multiple times
448+
timeoutTest()
449+
390450
testSuccessful = True
391451
finally:
392452
TestHelper.shutdown(cluster, walletMgr, testSuccessful, dumpErrorDetails)

0 commit comments

Comments
 (0)