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

[3.2] Backport cleos transaction signature keys #547

Merged
merged 6 commits into from
Jun 29, 2022
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 @@ -309,7 +309,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 @@ -576,12 +576,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 @@ -590,14 +591,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