Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test: Add integration test of setfinalizers after transition #192

Merged
merged 3 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions libraries/chain/block_header_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ const proposer_policy& block_header_state::get_last_proposed_proposer_policy() c
void finish_next(const block_header_state& prev,
block_header_state& next_header_state,
vector<digest_type> new_protocol_feature_activations,
instant_finality_extension if_ext) {
instant_finality_extension if_ext,
bool log) { // only log on assembled blocks, to avoid double logging
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nicer if we could move the logging out of this method to the caller, without adding this parameter just for logging. But detailed information we want to log is not accessible in the caller.

// activated protocol features
// ---------------------------
if (!new_protocol_feature_activations.empty()) {
Expand Down Expand Up @@ -240,8 +241,9 @@ void finish_next(const block_header_state& prev,
// Add this new proposal to the `finalizer_policies` multimap which tracks the in-flight proposals,
// increment the generation number, and log that proposal (debug level).
// ------------------------------------------------------------------------------------------------
dlog("New finalizer policy proposed in block ${id}..: ${pol}",
("id", prev.block_id.str().substr(8,16))("pol", new_finalizer_policy));
if (log)
dlog("New finalizer policy proposed in block ${id}..: ${pol}",
("id", prev.block_id.str().substr(8,16))("pol", new_finalizer_policy));
next_header_state.finalizer_policy_generation = new_finalizer_policy.generation;
next_header_state.finalizer_policies.emplace(
next_header_state.block_num(),
Expand All @@ -259,9 +261,11 @@ void finish_next(const block_header_state& prev,
// -----------------------------------------------------------------
if (next_header_state.active_finalizer_policy != prev.active_finalizer_policy) {
const auto& act = next_header_state.active_finalizer_policy;
ilog("Finalizer policy generation change: ${old_gen} -> ${new_gen}",
("old_gen", prev.active_finalizer_policy->generation)("new_gen",act->generation));
ilog("New finalizer policy becoming active in block ${id}: ${pol}",("id", next_header_state.block_id)("pol", *act));
if (log) {
ilog("Finalizer policy generation change: ${old_gen} -> ${new_gen}",
("old_gen", prev.active_finalizer_policy->generation)("new_gen",act->generation));
ilog("New finalizer policy becoming active in block ${id}: ${pol}",("id", next_header_state.block_id)("pol", *act));
}
}
}

Expand Down Expand Up @@ -308,7 +312,7 @@ block_header_state block_header_state::next(block_header_state_input& input) con
next_header_state.header_exts.emplace(ext_id, std::move(pfa_ext));
}

finish_next(*this, next_header_state, std::move(input.new_protocol_feature_activations), std::move(new_if_ext));
finish_next(*this, next_header_state, std::move(input.new_protocol_feature_activations), std::move(new_if_ext), true);

return next_header_state;
}
Expand Down Expand Up @@ -365,7 +369,7 @@ block_header_state block_header_state::next(const signed_block_header& h, valida
("f", next_core_metadata.final_on_strong_qc_block_num));
};

finish_next(*this, next_header_state, std::move(new_protocol_feature_activations), if_ext);
finish_next(*this, next_header_state, std::move(new_protocol_feature_activations), if_ext, false);

return next_header_state;
}
Expand Down
40 changes: 23 additions & 17 deletions tests/TestHarness/Cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -1002,17 +1002,33 @@ def parseClusterKeys(totalNodes):
return producerKeys

def activateInstantFinality(self, biosFinalizer=True, waitForFinalization=True, signatureProviderForNonProducer=False):
# call setfinalizer
numFins = 0
nodes = self.nodes.copy()
nodes.append(self.biosNode)
for n in (self.nodes + [self.biosNode]):
if not n or not n.keys or not n.keys[0].blspubkey:
nodes.remove(n)
continue
if not signatureProviderForNonProducer and not n.isProducer:
nodes.remove(n)
continue
if n.nodeId == 'bios' and not biosFinalizer:
nodes.remove(n)
continue
numFins = numFins + 1

transId = self.setFinalizers(nodes)
if transId is None:
return None, 0
if waitForFinalization:
if not self.biosNode.waitForTransFinalization(transId, timeout=21 * 12 * 3):
Utils.Print(f'ERROR: Failed to validate setfinalizer transaction {transId} got rolled into a '
f'LIB block on server port {self.biosNode.port}.')
return None, transId
return True, transId

def setFinalizers(self, nodes, node=None):
if node is None:
node = self.biosNode
numFins = len(nodes)
threshold = int(numFins * 2 / 3 + 1)
if threshold > 2 and threshold == numFins:
# nodes are often stopped, so do not require all node votes
Expand All @@ -1022,13 +1038,7 @@ def activateInstantFinality(self, biosFinalizer=True, waitForFinalization=True,
setFinStr += f' "threshold": {threshold}, '
setFinStr += f' "finalizers": ['
finNum = 1
for n in (self.nodes + [self.biosNode]):
if not n or not n.keys or not n.keys[0].blspubkey:
continue
if not signatureProviderForNonProducer and not n.isProducer:
continue
if n.nodeId == 'bios' and not biosFinalizer:
continue
for n in nodes:
setFinStr += f' {{"description": "finalizer #{finNum}", '
setFinStr += f' "weight":1, '
setFinStr += f' "public_key": "{n.keys[0].blspubkey}", '
Expand All @@ -1042,17 +1052,13 @@ def activateInstantFinality(self, biosFinalizer=True, waitForFinalization=True,
if Utils.Debug: Utils.Print("setfinalizers: %s" % (setFinStr))
Utils.Print("Setting finalizers")
opts = "--permission eosio@active"
trans = self.biosNode.pushMessage("eosio", "setfinalizer", setFinStr, opts)
trans = node.pushMessage("eosio", "setfinalizer", setFinStr, opts)
if trans is None or not trans[0]:
Utils.Print("ERROR: Failed to set finalizers")
return None, 0
return None
Node.validateTransaction(trans[1])
transId = Node.getTransId(trans[1])
if waitForFinalization:
if not self.biosNode.waitForTransFinalization(transId, timeout=21*12*3):
Utils.Print("ERROR: Failed to validate setfinalizer transaction %s got rolled into a LIB block on server port %d." % (transId, biosNode.port))
return None, transId
return True, transId
return transId

def bootstrap(self, launcher, biosNode, totalNodes, prodCount, totalProducers, pfSetupPolicy, onlyBios=False, onlySetProds=False, loadSystemContract=True, activateIF=False, biosFinalizer=True, signatureProviderForNonProducer=False):
"""Create 'prodCount' init accounts and deposits 10000000000 SYS in each. If prodCount is -1 will initialize all possible producers.
Expand Down
12 changes: 12 additions & 0 deletions tests/transition_to_if.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from TestHarness import Cluster, TestHelper, Utils, WalletMgr
from TestHarness.TestHelper import AppArgs
from TestHarness.Node import BlockType

###############################################################
# transition_to_if
Expand Down Expand Up @@ -88,13 +89,24 @@
# with setprods of (defproducera, defproducerg, defproducerl, defproducerq)
assert cluster.biosNode.waitForProducer("defproducerq"), "defproducerq did not produce"

Print("Set prods")
# should take effect in first block of defproducerg slot (so defproducerh)
assert cluster.setProds(["defproducerb", "defproducerh", "defproducerm", "defproducerr"]), "setprods failed"
setProdsBlockNum = cluster.biosNode.getBlockNum()
assert cluster.biosNode.waitForBlock(setProdsBlockNum+12+12+1), "Block of new producers not reached"
assert cluster.biosNode.getInfo(exitOnError=True)["head_block_producer"] == "defproducerh", "setprods should have taken effect"
assert cluster.getNode(4).waitForBlock(setProdsBlockNum + 12 + 12 + 1), "Block of new producers not reached on irreversible node"

Print("Set finalizers")
nodes = [cluster.getNode(0), cluster.getNode(1), cluster.getNode(2)]
transId = cluster.setFinalizers(nodes)
assert transId is not None, "setfinalizers failed"
if not cluster.biosNode.waitForTransFinalization(transId):
Utils.Print("ERROR: setfinalizer transaction %s not rolled into a LIB block" % (transId))
currentHead = cluster.biosNode.getHeadBlockNum()
assert cluster.biosNode.waitForBlock(currentHead, blockType=BlockType.lib), "LIB did not advance for setfinalizers to activate"
assert cluster.biosNode.waitForLibToAdvance(), "LIB did not advance after setfinalizers"

testSuccessful=True
finally:
TestHelper.shutdown(cluster, walletMgr, testSuccessful=testSuccessful, dumpErrorDetails=dumpErrorDetails)
Expand Down
Loading