Skip to content

Commit

Permalink
Merge pull request #547 from eosnetworkfoundation/backport-cleos-tran…
Browse files Browse the repository at this point in the history
…saction-signature-keys

[3.2] Backport cleos transaction signature keys
  • Loading branch information
oschwaldp-oci authored Jun 29, 2022
2 parents 85b9825 + bea59c1 commit 58971d3
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 181 deletions.
302 changes: 165 additions & 137 deletions programs/cleos/main.cpp

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions tests/Cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ def bootstrap(self, biosNode, totalNodes, prodCount, totalProducers, pfSetupPoli
wasmFile="%s.wasm" % (contract)
abiFile="%s.abi" % (contract)
Utils.Print("Publish %s contract" % (contract))
trans=biosNode.publishContract(eosioAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True)
trans=biosNode.publishContract(eosioAccount, contractDir, wasmFile, abiFile, waitForTransBlock=True)
if trans is None:
Utils.Print("ERROR: Failed to publish contract %s." % (contract))
return None
Expand Down Expand Up @@ -1238,7 +1238,7 @@ def bootstrap(self, biosNode, totalNodes, prodCount, totalProducers, pfSetupPoli
wasmFile="%s.wasm" % (contract)
abiFile="%s.abi" % (contract)
Utils.Print("Publish %s contract" % (contract))
trans=biosNode.publishContract(eosioTokenAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True)
trans=biosNode.publishContract(eosioTokenAccount, contractDir, wasmFile, abiFile, waitForTransBlock=True)
if trans is None:
Utils.Print("ERROR: Failed to publish contract %s." % (contract))
return None
Expand Down Expand Up @@ -1294,7 +1294,7 @@ def bootstrap(self, biosNode, totalNodes, prodCount, totalProducers, pfSetupPoli
wasmFile="%s.wasm" % (contract)
abiFile="%s.abi" % (contract)
Utils.Print("Publish %s contract" % (contract))
trans=biosNode.publishContract(eosioAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True)
trans=biosNode.publishContract(eosioAccount, contractDir, wasmFile, abiFile, waitForTransBlock=True)
if trans is None:
Utils.Print("ERROR: Failed to publish contract %s." % (contract))
return None
Expand Down
91 changes: 61 additions & 30 deletions tests/Node.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,11 @@ def isTransFinalized(self, transId):


# Create & initialize account and return creation transactions. Return transaction json object
def createInitializeAccount(self, account, creatorAccount, stakedDeposit=1000, waitForTransBlock=False, stakeNet=100, stakeCPU=100, buyRAM=10000, exitOnError=False, additionalArgs=''):
def createInitializeAccount(self, account, creatorAccount, stakedDeposit=1000, waitForTransBlock=False, stakeNet=100, stakeCPU=100, buyRAM=10000, exitOnError=False, sign=False, additionalArgs=''):
signStr = Node.__sign_str(sign, [ creatorAccount.activePublicKey ])
cmdDesc="system newaccount"
cmd='%s -j %s %s \'%s\' \'%s\' --stake-net "%s %s" --stake-cpu "%s %s" --buy-ram "%s %s" %s' % (
cmdDesc, creatorAccount.name, account.name, account.ownerPublicKey,
cmd='%s -j %s %s %s \'%s\' \'%s\' --stake-net "%s %s" --stake-cpu "%s %s" --buy-ram "%s %s" %s' % (
cmdDesc, signStr, creatorAccount.name, account.name, account.ownerPublicKey,
account.activePublicKey, stakeNet, CORE_SYMBOL, stakeCPU, CORE_SYMBOL, buyRAM, CORE_SYMBOL, additionalArgs)
msg="(creator account=%s, account=%s)" % (creatorAccount.name, account.name);
trans=self.processCleosCmd(cmd, cmdDesc, silentErrors=False, exitOnError=exitOnError, exitMsg=msg)
Expand All @@ -389,12 +390,13 @@ def createInitializeAccount(self, account, creatorAccount, stakedDeposit=1000, w

return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)

def createAccount(self, account, creatorAccount, stakedDeposit=1000, waitForTransBlock=False, exitOnError=False):
def createAccount(self, account, creatorAccount, stakedDeposit=1000, waitForTransBlock=False, exitOnError=False, sign=False):
"""Create account and return creation transactions. Return transaction json object.
waitForTransBlock: wait on creation transaction id to appear in a block."""
signStr = Node.__sign_str(sign, [ creatorAccount.activePublicKey ])
cmdDesc="create account"
cmd="%s -j %s %s %s %s" % (
cmdDesc, creatorAccount.name, account.name, account.ownerPublicKey, account.activePublicKey)
cmd="%s -j %s %s %s %s %s" % (
cmdDesc, signStr, creatorAccount.name, account.name, account.ownerPublicKey, account.activePublicKey)
msg="(creator account=%s, account=%s)" % (creatorAccount.name, account.name);
trans=self.processCleosCmd(cmd, cmdDesc, silentErrors=False, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)
Expand Down Expand Up @@ -524,16 +526,23 @@ def __call__(self):
def waitForIrreversibleBlock(self, blockNum, timeout=None, reportInterval=None):
return self.waitForBlock(blockNum, timeout=timeout, blockType=BlockType.lib, reportInterval=reportInterval)

def __transferFundsCmdArr(self, source, destination, amountStr, memo, force, retry):
def __transferFundsCmdArr(self, source, destination, amountStr, memo, force, retry, sign):
assert isinstance(amountStr, str)
assert(source)
assert(isinstance(source, Account))
assert(destination)
assert(isinstance(destination, Account))

cmd="%s %s -v transfer --expiration 90 %s -j %s %s" % (
Utils.EosClientPath, self.eosClientArgs(), self.getRetryCmdArg(retry), source.name, destination.name)
cmd="%s %s -v transfer --expiration 90 %s -j" % (
Utils.EosClientPath, self.eosClientArgs(), self.getRetryCmdArg(retry))
cmdArr=cmd.split()
# not using __sign_str, since cmdArr messes up the string
if sign:
cmdArr.append("--sign-with")
cmdArr.append("[ \"%s\" ]" % (source.activePublicKey))

cmdArr.append(source.name)
cmdArr.append(destination.name)
cmdArr.append(amountStr)
cmdArr.append(memo)
if force:
Expand All @@ -543,8 +552,8 @@ def __transferFundsCmdArr(self, source, destination, amountStr, memo, force, ret
return cmdArr

# Trasfer funds. Returns "transfer" json return object
def transferFunds(self, source, destination, amountStr, memo="memo", force=False, waitForTransBlock=False, exitOnError=True, reportStatus=True, retry=None):
cmdArr = self.__transferFundsCmdArr(source, destination, amountStr, memo, force, retry)
def transferFunds(self, source, destination, amountStr, memo="memo", force=False, waitForTransBlock=False, exitOnError=True, reportStatus=True, retry=None, sign=False):
cmdArr = self.__transferFundsCmdArr(source, destination, amountStr, memo, force, retry, sign)
trans=None
start=time.perf_counter()
try:
Expand All @@ -569,8 +578,8 @@ def transferFunds(self, source, destination, amountStr, memo="memo", force=False
return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)

# Trasfer funds. Returns (popen, cmdArr) for checkDelayedOutput
def transferFundsAsync(self, source, destination, amountStr, memo="memo", force=False, exitOnError=True, retry=None):
cmdArr = self.__transferFundsCmdArr(source, destination, amountStr, memo, force, retry)
def transferFundsAsync(self, source, destination, amountStr, memo="memo", force=False, exitOnError=True, retry=None, sign=False):
cmdArr = self.__transferFundsCmdArr(source, destination, amountStr, memo, force, retry, sign)
start=time.perf_counter()
try:
popen=Utils.delayedCheckOutput(cmdArr)
Expand Down Expand Up @@ -744,8 +753,9 @@ def getAccountCodeHash(self, account):
return None

# publish contract and return transaction as json object
def publishContract(self, account, contractDir, wasmFile, abiFile, waitForTransBlock=False, shouldFail=False):
cmd="%s %s -v set contract -j %s %s" % (Utils.EosClientPath, self.eosClientArgs(), account, contractDir)
def publishContract(self, account, contractDir, wasmFile, abiFile, waitForTransBlock=False, shouldFail=False, sign=False):
signStr = Node.__sign_str(sign, [ account.activePublicKey ])
cmd="%s %s -v set contract -j %s %s %s" % (Utils.EosClientPath, self.eosClientArgs(), signStr, account.name, contractDir)
cmd += "" if wasmFile is None else (" "+ wasmFile)
cmd += "" if abiFile is None else (" " + abiFile)
if Utils.Debug: Utils.Print("cmd: %s" % (cmd))
Expand Down Expand Up @@ -846,9 +856,13 @@ def pushTransaction(self, trans, opts="", silentErrors=False, permissions=None):
return (False, msg)

# returns tuple with transaction execution status and transaction
def pushMessage(self, account, action, data, opts, silentErrors=False):
def pushMessage(self, account, action, data, opts, silentErrors=False, signatures=None):
cmd="%s %s push action -j %s %s" % (Utils.EosClientPath, self.eosClientArgs(), account, action)
cmdArr=cmd.split()
# not using __sign_str, since cmdArr messes up the string
if signatures is not None:
cmdArr.append("--sign-with")
cmdArr.append("[ \"%s\" ]" % ("\", \"".join(signatures)))
if data is not None:
cmdArr.append(data)
if opts is not None:
Expand All @@ -870,55 +884,72 @@ def pushMessage(self, account, action, data, opts, silentErrors=False):
Utils.Print("ERROR: Exception during push message. cmd Duration=%.3f sec. %s" % (end - start, msg))
return (False, msg)

def setPermission(self, account, code, pType, requirement, waitForTransBlock=False, exitOnError=False):
@staticmethod
def __sign_str(sign, keys):
assert(isinstance(sign, bool))
assert(isinstance(keys, list))
if not sign:
return ""

return "--sign-with '[ \"" + "\", \"".join(keys) + "\" ]'"

def setPermission(self, account, code, pType, requirement, waitForTransBlock=False, exitOnError=False, sign=False):
assert(isinstance(account, Account))
assert(isinstance(code, Account))
signStr = Node.__sign_str(sign, [ account.activePublicKey ])
Utils.Print("REMOVE signStr: <%s>" % (signStr))
cmdDesc="set action permission"
cmd="%s -j %s %s %s %s" % (cmdDesc, account, code, pType, requirement)
cmd="%s -j %s %s %s %s %s" % (cmdDesc, signStr, account.name, code.name, pType, requirement)
trans=self.processCleosCmd(cmd, cmdDesc, silentErrors=False, exitOnError=exitOnError)
self.trackCmdTransaction(trans)

return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)

def delegatebw(self, fromAccount, netQuantity, cpuQuantity, toAccount=None, transferTo=False, waitForTransBlock=False, exitOnError=False, reportStatus=True):
def delegatebw(self, fromAccount, netQuantity, cpuQuantity, toAccount=None, transferTo=False, waitForTransBlock=False, exitOnError=False, reportStatus=True, sign=False):
if toAccount is None:
toAccount=fromAccount

signStr = Node.__sign_str(sign, [ fromAccount.activePublicKey ])
cmdDesc="system delegatebw"
transferStr="--transfer" if transferTo else ""
cmd="%s -j %s %s \"%s %s\" \"%s %s\" %s" % (
cmdDesc, fromAccount.name, toAccount.name, netQuantity, CORE_SYMBOL, cpuQuantity, CORE_SYMBOL, transferStr)
cmd="%s -j %s %s %s \"%s %s\" \"%s %s\" %s" % (
cmdDesc, signStr, fromAccount.name, toAccount.name, netQuantity, CORE_SYMBOL, cpuQuantity, CORE_SYMBOL, transferStr)
msg="fromAccount=%s, toAccount=%s" % (fromAccount.name, toAccount.name);
trans=self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans, reportStatus=reportStatus)

return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)

def undelegatebw(self, fromAccount, netQuantity, cpuQuantity, toAccount=None, waitForTransBlock=False, exitOnError=False):
def undelegatebw(self, fromAccount, netQuantity, cpuQuantity, toAccount=None, waitForTransBlock=False, exitOnError=False, sign=False):
if toAccount is None:
toAccount=fromAccount

signStr = Node.__sign_str(sign, [ fromAccount.activePublicKey ])
cmdDesc="system undelegatebw"
cmd="%s -j %s %s \"%s %s\" \"%s %s\"" % (
cmdDesc, fromAccount.name, toAccount.name, netQuantity, CORE_SYMBOL, cpuQuantity, CORE_SYMBOL)
cmd="%s -j %s %s %s \"%s %s\" \"%s %s\"" % (
cmdDesc, signStr, fromAccount.name, toAccount.name, netQuantity, CORE_SYMBOL, cpuQuantity, CORE_SYMBOL)
msg="fromAccount=%s, toAccount=%s" % (fromAccount.name, toAccount.name);
trans=self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)

return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)

def regproducer(self, producer, url, location, waitForTransBlock=False, exitOnError=False):
def regproducer(self, producer, url, location, waitForTransBlock=False, exitOnError=False, sign=False):
signStr = Node.__sign_str(sign, [ producer.activePublicKey ])
cmdDesc="system regproducer"
cmd="%s -j %s %s %s %s" % (
cmdDesc, producer.name, producer.activePublicKey, url, location)
cmd="%s -j %s %s %s %s %s" % (
cmdDesc, signStr, producer.name, producer.activePublicKey, url, location)
msg="producer=%s" % (producer.name);
trans=self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)

return self.waitForTransBlockIfNeeded(trans, waitForTransBlock, exitOnError=exitOnError)

def vote(self, account, producers, waitForTransBlock=False, exitOnError=False):
def vote(self, account, producers, waitForTransBlock=False, exitOnError=False, sign=False):
signStr = Node.__sign_str(sign, [ account.activePublicKey ])
cmdDesc = "system voteproducer prods"
cmd="%s -j %s %s" % (
cmdDesc, account.name, " ".join(producers))
cmd="%s -j %s %s %s" % (
cmdDesc, signStr, account.name, " ".join(producers))
msg="account=%s, producers=[ %s ]" % (account.name, ", ".join(producers));
trans=self.processCleosCmd(cmd, cmdDesc, exitOnError=exitOnError, exitMsg=msg)
self.trackCmdTransaction(trans)
Expand Down
10 changes: 5 additions & 5 deletions tests/nodeos_run_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@
wasmFile="eosio.token.wasm"
abiFile="eosio.token.abi"
Print("Publish contract")
trans=node.publishContract(currencyAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True)
trans=node.publishContract(currencyAccount, contractDir, wasmFile, abiFile, waitForTransBlock=True)
if trans is None:
cmdError("%s set contract currency1111" % (ClientName))
errorExit("Failed to publish contract.")
Expand Down Expand Up @@ -584,12 +584,13 @@
errorExit("Failed to lock wallet %s" % (defproduceraWallet.name))


simpleDB = Account("simpledb")
contractDir="contracts/simpledb"
wasmFile="simpledb.wasm"
abiFile="simpledb.abi"
Print("Setting simpledb contract without simpledb account was causing core dump in %s." % (ClientName))
Print("Verify %s generates an error, but does not core dump." % (ClientName))
retMap=node.publishContract("simpledb", contractDir, wasmFile, abiFile, shouldFail=True)
retMap=node.publishContract(simpleDB, contractDir, wasmFile, abiFile, shouldFail=True)
if retMap is None:
errorExit("Failed to publish, but should have returned a details map")
if retMap["returncode"] == 0 or retMap["returncode"] == 139: # 139 SIGSEGV
Expand All @@ -598,14 +599,13 @@
Print("Test successful, %s returned error code: %d" % (ClientName, retMap["returncode"]))

Print("set permission")
code="currency1111"
pType="transfer"
requirement="active"
trans=node.setPermission(testeraAccount.name, code, pType, requirement, waitForTransBlock=True, exitOnError=True)
trans=node.setPermission(testeraAccount, currencyAccount, pType, requirement, waitForTransBlock=True, exitOnError=True)

Print("remove permission")
requirement="null"
trans=node.setPermission(testeraAccount.name, code, pType, requirement, waitForTransBlock=True, exitOnError=True)
trans=node.setPermission(testeraAccount, currencyAccount, pType, requirement, waitForTransBlock=True, exitOnError=True)

Print("Locking all wallets.")
if not walletMgr.lockAllWallets():
Expand Down
2 changes: 1 addition & 1 deletion tests/nodeos_under_min_avail_ram.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@
wasmFile="integration_test.wasm"
abiFile="integration_test.abi"
Print("Publish contract")
trans=nodes[0].publishContract(contractAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True)
trans=nodes[0].publishContract(contractAccount, contractDir, wasmFile, abiFile, waitForTransBlock=True)
if trans is None:
Utils.cmdError("%s set contract %s" % (ClientName, contractAccount.name))
errorExit("Failed to publish contract.")
Expand Down
2 changes: 1 addition & 1 deletion tests/p2p_network_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@
wasmFile="eosio.system.wasm"
abiFile="eosio.system.abi"
Print("\nPush system contract %s %s" % (wasmFile, abiFile))
trans=node0.publishContract(eosio.name, wasmFile, abiFile, waitForTransBlock=True)
trans=node0.publishContract(eosio, wasmFile, abiFile, waitForTransBlock=True)
if trans is None:
Utils.errorExit("Failed to publish eosio.system.")
else:
Expand Down
2 changes: 1 addition & 1 deletion tests/plugin_http_api_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def activateAllBuiltinProtocolFeatures(self):
walletAccounts = [eosioAccount]
self.keosd.create(testWalletName, walletAccounts)

retMap = self.nodeos.publishContract(eosioAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True)
retMap = self.nodeos.publishContract(eosioAccount, contractDir, wasmFile, abiFile, waitForTransBlock=True)

self.nodeos.preactivateAllBuiltinProtocolFeature()

Expand Down
6 changes: 3 additions & 3 deletions tests/prod_preactivation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@
abiFile="%s.abi" % (contract)

Print("publish a new bios contract %s should fails because env.is_feature_activated unresolveable" % (contractDir))
retMap = node0.publishContract("eosio", contractDir, wasmFile, abiFile, True, shouldFail=True)
retMap = node0.publishContract(cluster.eosioAccount, contractDir, wasmFile, abiFile, True, shouldFail=True)

if retMap["output"].decode("utf-8").find("unresolveable") < 0:
errorExit("bios contract not result in expected unresolveable error")
Expand Down Expand Up @@ -150,7 +150,7 @@

time.sleep(0.6)
Print("publish a new bios contract %s should fails because node1 is not producing block yet" % (contractDir))
retMap = node0.publishContract("eosio", contractDir, wasmFile, abiFile, True, shouldFail=True)
retMap = node0.publishContract(cluster.eosioAccount, contractDir, wasmFile, abiFile, True, shouldFail=True)
if retMap["output"].decode("utf-8").find("unresolveable") < 0:
errorExit("bios contract not result in expected unresolveable error")

Expand All @@ -167,7 +167,7 @@
errorExit("No blocks produced by node 1")

time.sleep(0.6)
retMap = node0.publishContract("eosio", contractDir, wasmFile, abiFile, True)
retMap = node0.publishContract(cluster.eosioAccount, contractDir, wasmFile, abiFile, True)
Print("sucessfully set new contract with new intrinsic!!!")

testSuccessful=True
Expand Down

0 comments on commit 58971d3

Please sign in to comment.