Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #10253 from EOSIO/bdj__privacy-simple-test-improve…
Browse files Browse the repository at this point in the history
…ments_EPE-832

Added Privacy Test Scenario #3 to privacy-simple-network.py
  • Loading branch information
brianjohnson5972 authored Apr 16, 2021
2 parents 5e82833 + fafcfaa commit ca8a056
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 95 deletions.
2 changes: 1 addition & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ add_test(NAME eosio_blocklog_prune_test COMMAND tests/eosio_blocklog_prune_test.
set_property(TEST eosio_blocklog_prune_test PROPERTY LABELS nonparallelizable_tests)
add_test(NAME privacy_startup_network COMMAND tests/privacy_startup_network.py -p 1 -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST privacy_startup_network PROPERTY LABELS nonparallelizable_tests)
add_test(NAME privacy_simple_network COMMAND tests/privacy_simple_network.py -p 2 -n 3 -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
add_test(NAME privacy_simple_network COMMAND tests/privacy_simple_network.py -p 2 -n 4 -v --clean-run --dump-error-detail WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
set_property(TEST privacy_simple_network PROPERTY LABELS nonparallelizable_tests)

# Long running tests
Expand Down
40 changes: 22 additions & 18 deletions tests/Cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,8 @@ def connectGroup(group, producerNodes, bridgeNodes) :
if onlyBios:
self.nodes=[biosNode]

self.totalNodes = totalNodes

# ensure cluster node are inter-connected by ensuring everyone has block 1
Utils.Print("Cluster viability smoke test. Validate every cluster node has block 1. ")
if not self.waitOnClusterBlockNumSync(1):
Expand Down Expand Up @@ -1032,24 +1034,6 @@ def parseProducerKeys(configFile, nodeName):

return producerKeys

@staticmethod
def parseProducers(nodeNum):
"""Parse node config file for producers."""

configFile=Utils.getNodeConfigDir(nodeNum, "config.ini")
if Utils.Debug: Utils.Print("Parsing config file %s" % configFile)
configStr=None
with open(configFile, 'r') as f:
configStr=f.read()

pattern=r"^\s*producer-name\s*=\W*(\w+)\W*$"
producerMatches=re.findall(pattern, configStr, re.MULTILINE)
if producerMatches is None:
if Utils.Debug: Utils.Print("Failed to find producers.")
return None

return producerMatches

@staticmethod
def parseClusterKeys(totalNodes):
"""Parse cluster config file. Updates producer keys data members."""
Expand Down Expand Up @@ -1877,3 +1861,23 @@ def verifyInSync(self, sourceNodeNum=0, specificNodes=None):
if error:
self.reportInfo()
Utils.errorExit(error)

def getParticipantNum(self, nodeToIdentify):
num = 0
for node in self.nodes:
if node == nodeToIdentify:
return num
num += 1
assert nodeToIdentify == self.biosNode
return self.totalNodes

def getProducingNodeIndex(self, blockProducer):
featureProdNum = 0
while featureProdNum < pnodes:
if blockProducer in self.nodes[featureProdNum].getProducers():
return featureProdNum

featureProdNum += 1

assert blockProducer in self.biosNode.getProducers(), "Checked all nodes but could not find producer: {}".format(blockProducer)
return "bios"
94 changes: 75 additions & 19 deletions tests/Node.py
Original file line number Diff line number Diff line change
Expand Up @@ -1200,7 +1200,7 @@ def getBlockProducerByNum(self, blockNum, timeout=None, waitForBlock=True, exitO
block=self.getBlock(blockNum, exitOnError=exitOnError)
return Node.getBlockAttribute(block, "producer", blockNum, exitOnError=exitOnError)

def getBlockProducer(self, timeout=None, waitForBlock=True, exitOnError=True, blockType=BlockType.head):
def getBlockProducer(self, timeout=None, exitOnError=True, blockType=BlockType.head):
blockNum=self.getBlockNum(blockType=blockType)
block=self.getBlock(blockNum, exitOnError=exitOnError, blockType=blockType)
return Node.getBlockAttribute(block, "producer", blockNum, exitOnError=exitOnError)
Expand Down Expand Up @@ -1453,7 +1453,8 @@ def isDesiredProdTurn():
return beginningOfProdTurnHead

# Require producer_api_plugin
def activateFeatures(self, features):
def activateFeatures(self, features, blocksToAdvance=2):
assert blocksToAdvance >= 0
featureDigests = []
for feature in features:
protocolFeatureDigestDict = self.getSupportedProtocolFeatureDict()
Expand All @@ -1465,16 +1466,44 @@ def activateFeatures(self, features):
self.scheduleProtocolFeatureActivations(featureDigests)

# Wait for the next block to be produced so the scheduled protocol feature is activated
assert self.waitForHeadToAdvance(blocksToAdvance=2), print("ERROR: TIMEOUT WAITING FOR activating features: {}".format(",".join(features)))
assert self.waitForHeadToAdvance(blocksToAdvance=blocksToAdvance), print("ERROR: TIMEOUT WAITING FOR activating features: {}".format(",".join(features)))

def activateAndVerifyFeatures(self, features):
self.activateFeatures(features, blocksToAdvance=0)
headBlockNum = self.getBlockNum()
blockNum = headBlockNum
producers = {}
lastProducer = None
while True:
block = self.getBlock(blockNum)
blockHeaderState = self.getBlockHeaderState(blockNum)
if self.containsFeatures(features, blockHeaderState):
return

producer = block["producer"]
producers[producer] += 1
assert lastProducer != producer or producers[producer] == 1, \
"We have already cycled through a complete cycle, so feature should have been set by now. \
Initial block num: {}, looking at block num: {}".format(headBlockNum, blockNum)

# feature should be in block for this node's producers, if it is at least 2 blocks after we sent the activate
minBlocksForGuarantee = 2
assert producer not in self.getProducers() or blockNum - headBlockNum < minBlocksForGuarantee, \
"It is {} blocks past the block when we activated the features and block num: {} was produced by this \
node, so features should have been set."
self.waitForBlock(blockNum + 1)
blockNum = self.getBlockNum()



# Require producer_api_plugin
def activatePreactivateFeature(self):
return self.activateFeatures(["PREACTIVATE_FEATURE"])

def containsFeatures(self, features):
def containsFeatures(self, features, blockHeaderState=None):
protocolFeatureDict = self.getSupportedProtocolFeatureDict()
blockHeaderState = self.getLatestBlockHeaderState()
assert blockHeaderState, "blockHeaderState should not be empty"
if blockHeaderState is None:
blockHeaderState = self.getLatestBlockHeaderState()
for feature in features:
featureDigest = protocolFeatureDict[feature]["feature_digest"]
assert featureDigest, "{}'s Digest should not be empty".format(feature)
Expand Down Expand Up @@ -1520,20 +1549,26 @@ def preactivateAllBuiltinProtocolFeature(self):

def getLatestBlockHeaderState(self):
headBlockNum = self.getHeadBlockNum()
for i in range(10):
cmdDesc = "get block {} --header-state".format(headBlockNum)
latestBlockHeaderState = self.processCleosCmd(cmdDesc, cmdDesc)
Utils.Print("block num: {}, block state: {}, head: {}".format(headBlockNum, latestBlockHeaderState, self.getHeadBlockNum()))
if latestBlockHeaderState:
return latestBlockHeaderState
time.sleep(1)
return None

def getActivatedProtocolFeatures(self):
latestBlockHeaderState = self.getLatestBlockHeaderState()
if "activated_protocol_features" not in latestBlockHeaderState or "protocol_features" not in latestBlockHeaderState["activated_protocol_features"]:
return self.getBlockHeaderState(headBlockNum)

def getBlockHeaderState(self, blockNum, errorOnNone=True):
cmdDesc = "get block {} --header-state".format(blockNum)
blockHeaderState = self.processCleosCmd(cmdDesc, cmdDesc)
if blockHeaderState is None and errorOnNone:
info = self.getInfo()
lib = info["last_irreversible_block_num"]
head = info["head_block_num"]
assert head == lib + 1, "getLatestBlockHeaderState failed to retrieve the latest block. This should be investigated."
Utils.errorExit("Called getLatestBlockHeaderState, which can only retrieve blocks in reversible database, but the test setup only has one producer so there" +
" is only 1 block in the reversible database. Test should be redesigned to aquire this information via another interface.")
return blockHeaderState

def getActivatedProtocolFeatures(self, blockHeaderState=None):
if blockHeaderState is None:
blockHeaderState = self.getLatestBlockHeaderState()
if "activated_protocol_features" not in blockHeaderState or "protocol_features" not in blockHeaderState["activated_protocol_features"]:
Utils.errorExit("getLatestBlockHeaderState did not return expected output, should contain [\"activated_protocol_features\"][\"protocol_features\"]: {}".format(latestBlockHeaderState))
return latestBlockHeaderState["activated_protocol_features"]["protocol_features"]
return blockHeaderState["activated_protocol_features"]["protocol_features"]

def modifyBuiltinPFSubjRestrictions(self, featureCodename, subjectiveRestriction={}):
jsonPath = os.path.join(Utils.getNodeConfigDir(self.nodeId),
Expand Down Expand Up @@ -1687,3 +1722,24 @@ def waitForIrreversibleBlockProducedBy(self, producer, startBlockNum=0, retry=10
retry = retry - 1
startBlockNum = latestBlockNum + 1
return False

@staticmethod
def parseProducers(nodeNum):
"""Parse node config file for producers."""

configFile=Utils.getNodeConfigDir(nodeNum, "config.ini")
if Utils.Debug: Utils.Print("Parsing config file %s" % configFile)
configStr=None
with open(configFile, 'r') as f:
configStr=f.read()

pattern=r"^\s*producer-name\s*=\W*(\w+)\W*$"
producerMatches=re.findall(pattern, configStr, re.MULTILINE)
if producerMatches is None:
if Utils.Debug: Utils.Print("Failed to find producers.")
return None

return producerMatches

def getProducers(self):
return Node.parseProducers(self.nodeId)
2 changes: 1 addition & 1 deletion tests/nodeos_forked_chain_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def getMinHeadAndLib(prodNodes):
producers=[]
for i in range(0, totalNodes):
node=cluster.getNode(i)
node.producers=Cluster.parseProducers(i)
node.producers=node.getProducers()
numProducers=len(node.producers)
Print("node has producers=%s" % (node.producers))
if numProducers==0:
Expand Down
2 changes: 1 addition & 1 deletion tests/nodeos_high_transaction_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
allNodes=cluster.getNodes()
for i in range(0, totalNodes):
node=allNodes[i]
nodeProducers=Cluster.parseProducers(i)
nodeProducers=node.getProducers()
numProducers=len(nodeProducers)
Print("node has producers=%s" % (nodeProducers))
if numProducers==0:
Expand Down
2 changes: 1 addition & 1 deletion tests/nodeos_short_fork_take_over_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def getMinHeadAndLib(prodNodes):
producers=[]
for i in range(0, totalNodes):
node=cluster.getNode(i)
node.producers=Cluster.parseProducers(i)
node.producers=node.getProducers()
numProducers=len(node.producers)
Print("node has producers=%s" % (node.producers))
if numProducers==0:
Expand Down
2 changes: 1 addition & 1 deletion tests/nodeos_voting_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def verifyProductionRounds(trans, node, prodsActive, rounds):

for i in range(0, totalNodes):
node=cluster.getNode(i)
node.producers=Cluster.parseProducers(i)
node.producers=node.getProducers()
for prod in node.producers:
trans=node.regproducer(cluster.defProducerAccounts[prod], "http::/mysite.com", 0, waitForTransBlock=False, exitOnError=True)

Expand Down
Loading

0 comments on commit ca8a056

Please sign in to comment.