Skip to content

Commit

Permalink
Merge pull request #532 from qtumproject/time/QTUMCORE-125
Browse files Browse the repository at this point in the history
Add callcontract support to "createrawtransaction" rpc call (QTUMCORE-125)
  • Loading branch information
qtum-neil authored Apr 3, 2018
2 parents 65f25e9 + 3540686 commit da13773
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 32 deletions.
4 changes: 2 additions & 2 deletions qa/rpc-tests/qtum-many-value-refunds-from-same-tx.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ def run_test(self):
contract Test {
function () {}
}
"""
"""
contract_bytecode = "60606040523415600e57600080fd5b5b603f80601c6000396000f30060606040525b3415600f57600080fd5b5b5b0000a165627a7a7230582058c936974fe6daaa8267ff5da1c805b0e7442b9cc687162114dfb1cb6d6f62bd0029"
contract_address = self.node.createcontract(contract_bytecode)['address']
self.node.generate(1)
tx = CTransaction()
tx.vin = [make_vin(self.node, int(20000*COIN))]
tx.vin = [make_vin(self.node, int(2*(COIN + QTUM_MIN_GAS_PRICE*100000)))]
tx.vout = []
tx.vout.append(CTxOut(int(COIN), CScript([b"\x04", CScriptNum(100000), CScriptNum(QTUM_MIN_GAS_PRICE), hex_str_to_bytes("00"), hex_str_to_bytes(contract_address), OP_CALL])))
tx.vout.append(CTxOut(int(COIN), CScript([b"\x04", CScriptNum(100000), CScriptNum(QTUM_MIN_GAS_PRICE), hex_str_to_bytes("00"), hex_str_to_bytes(contract_address), OP_CALL])))
Expand Down
25 changes: 14 additions & 11 deletions qa/rpc-tests/qtum-opcall.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,14 @@ def send_multiple_op_call_txs_with_counter_check(self, num_txs, outputs, counter
while i < num_txs and len(unspents) > 0:
# Select as input a tx which has at least 5 qtum spendable
for tx_i in range(len(unspents)):
if unspents[tx_i]['amount'] > 5.00000000 and unspents[tx_i]['spendable']:
if int(unspents[tx_i]['amount']*COIN) == 1000000*QTUM_MIN_GAS_PRICE and unspents[tx_i]['spendable']:
break

else:
assert(False)

inpt = CTxIn(COutPoint(int(unspents[tx_i]['txid'], 16), unspents[tx_i]['vout']), nSequence=0)
tx = make_transaction(self.node, [inpt], outputs)
self.node.sendrawtransaction(tx)
txid = self.node.sendrawtransaction(tx)
unspents = self.node.listunspent()
i += 1

Expand Down Expand Up @@ -101,13 +103,13 @@ def many_calls_in_same_tx_test(self):
outputs = []
outputs.append(make_op_call_output(0, b"\x04", CScriptNum(1000000), CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
outputs.append(make_op_call_output(0, b"\x04", CScriptNum(1000000), CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
self.send_one_op_call_tx_with_counter_check(outputs, counter_should_increase_by=2)
self.send_one_op_call_tx_with_counter_check(outputs, counter_should_increase_by=2, input_value=2*1000000*QTUM_MIN_GAS_PRICE)

# Sends a normal raw op_call tx with a single output.
def normal_op_call_output_test(self):
outputs = []
outputs.append(make_op_call_output(0, b"\x04", b"\xff\x7f", CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
self.send_one_op_call_tx_with_counter_check(outputs, counter_should_increase_by=1)
self.send_one_op_call_tx_with_counter_check(outputs, counter_should_increase_by=1, input_value=0x7fff*QTUM_MIN_GAS_PRICE)

# Sends a tx containing 1 op_call output where txfee == gas_price*gas_limit.
def gas_equal_to_tx_fee_test(self):
Expand Down Expand Up @@ -141,7 +143,7 @@ def gas_limit_signedness_test(self):
gas_limit = b"\xff"
while len(gas_limit) < 20:
outputs.append(make_op_call_output(0, b"\x04", gas_limit, CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True)
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True, input_value=min(max(int(bytes_to_hex_str(gas_limit), 16)*QTUM_MIN_GAS_PRICE, 10000000), 1000000000))
gas_limit += b"\xff"

# sends a tx containing 1 op_call output with a (if interpreted with a signed integer) negative gas limit calling inc()
Expand All @@ -150,19 +152,19 @@ def gas_limit_signedness_one_valid_test(self):
gas_limit = b"\xff"
outputs.append(make_op_call_output(0, b"\x04", b"\xff\xff\x00", CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
outputs.append(make_op_call_output(0, b"\x04", b"\xff\xff", CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True)
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True, input_value=2*0xffff*QTUM_MIN_GAS_PRICE)

# sends a tx containing 1 op_call output with a (if interpreted with a signed integer) negative gas price calling inc()
def gas_price_signedness_test(self):
outputs = []
outputs.append(make_op_call_output(0, b"\x04", b"\x01\x00", b"\xff\xff", bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True)
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True, input_value=10000000)

# sends a tx containing 1 op_call output with a possible negative gas limit and price calling inc()
def gas_limit_and_price_signedness_test(self):
outputs = []
outputs.append(make_op_call_output(0, b"\x04", b"\xff\xff", b"\xff", bytes.fromhex("371303c0"), bytes.fromhex(self.contract_address)))
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True)
self.send_one_op_call_tx_with_counter_check(outputs, should_throw=True, input_value=0xff*0xffff)

# Sends 100 valid op_call txs
def send_100_txs_test(self):
Expand All @@ -174,7 +176,7 @@ def send_tx_with_value_test(self):
outputs = []
# d0e30db0 deposit()
outputs.append(make_op_call_output(100000000, b"\x04", CScriptNum(1000000), CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("d0e30db0"), bytes.fromhex(self.contract_address)))
self.send_one_op_call_tx_with_counter_check(outputs, counter_should_increase_by=0)
self.send_one_op_call_tx_with_counter_check(outputs, counter_should_increase_by=0, input_value=100000000+1000000*QTUM_MIN_GAS_PRICE)

# 12065fe0 getBalance()
balance = int(self.node.callcontract(self.contract_address, "12065fe0")['executionResult']['output'], 16)
Expand All @@ -184,7 +186,8 @@ def send_tx_with_value_test(self):


def run_test(self):
self.nodes[0].generate(100+COINBASE_MATURITY)
self.nodes[0].generate(200+COINBASE_MATURITY)
self.node.sendmany("", {self.node.getnewaddress(): 1000000*QTUM_MIN_GAS_PRICE / Decimal('100000000') for i in range(200)})
print("Creating contract")
self.create_contract_test()
print("Calling inc() in two outputs")
Expand Down
9 changes: 5 additions & 4 deletions qa/rpc-tests/qtum-opcreate.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def basic_contract_is_created_raw_tx_test(self):
}
"""
tx = make_transaction(node,
[self.vins.pop(-1)],
[make_vin(node, 500000*QTUM_MIN_GAS_PRICE)],
[make_op_create_output(node, 0, 4, CScriptNum(500000), CScriptNum(QTUM_MIN_GAS_PRICE), bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820e3bed070fd3a81dd00e02efd22d18a3b47b70860155d6063e47e1e2674fc5acb0029"))]
)
#node.createcontract("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a72305820e3bed070fd3a81dd00e02efd22d18a3b47b70860155d6063e47e1e2674fc5acb0029");
Expand Down Expand Up @@ -128,7 +128,7 @@ def gas_limit_signedness_test(self):
}
"""
tx = make_transaction(node,
[self.vins.pop(-1)],
[make_vin(node, 0xffff*1000)],
# changing the gas limit \xff\xff -> \xff\xff\x00 results in success.
[make_op_create_output(node, 0, b"\x04", b"\xff\xff", 1000, bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a7230582092926a9814888ff08700cbd86cf4ff8c50052f5fd894e794570d9551733591d60029"))]
)
Expand All @@ -139,7 +139,7 @@ def gas_limit_signedness_test(self):
pass


def gas_limit_signedness_test(self):
def gas_limit_signedness_2_test(self):
node = self.nodes[0]
num_old_contracts = len(node.listcontracts(1, 1000))

Expand All @@ -150,7 +150,7 @@ def gas_limit_signedness_test(self):
}
"""
tx = make_transaction(node,
[self.vins.pop(-1)],
[make_vin(node, 2*0xffff*1000)],
# changing the gas limit \xff\xff -> \xff\xff\x00 results in success.
[make_op_create_output(node, 0, b"\x04", b"\xff\x4f", 1000, bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a7230582092926a9814888ff08700cbd86cf4ff8c50052f5fd894e794570d9551733591d60029")),
make_op_create_output(node, 0, b"\x04", b"\xff\xff", 1000, bytes.fromhex("60606040523415600b57fe5b5b60398060196000396000f30060606040525b600b5b5b565b0000a165627a7a7230582092926a9814888ff08700cbd86cf4ff8c50052f5fd894e794570d9551733591d60029"))]
Expand All @@ -170,6 +170,7 @@ def run_test(self):
self.many_contracts_in_one_block_test()
self.contract_reorg_test()
self.gas_limit_signedness_test()
self.gas_limit_signedness_2_test()

if __name__ == '__main__':
OpCreateTest().main()
3 changes: 2 additions & 1 deletion qa/rpc-tests/qtum-soft-block-gas-limits.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ def send_raw_to_contract(self, node, contract_address, gas_limit, gas_price, num
unspent = node.listunspent()[0]
tx = CTransaction()
tx.vin = [CTxIn(COutPoint(int(unspent['txid'], 16), unspent['vout']), nSequence=0)]
amount = int((float(str(unspent['amount'])) - 1000)*COIN // num_outputs)
amount = int((float(str(unspent['amount']))*COIN)) // num_outputs - gas_price*gas_limit

tx.vout = [CTxOut(amount, scriptPubKey=CScript([b"\x04", CScriptNum(gas_limit), CScriptNum(gas_price), b"\x00", hex_str_to_bytes(contract_address), OP_CALL])) for i in range(num_outputs)]
tx_hex_signed = node.signrawtransaction(bytes_to_hex_str(tx.serialize()))['hex']
return node.sendrawtransaction(tx_hex_signed)
Expand Down
12 changes: 6 additions & 6 deletions qa/rpc-tests/qtum-transaction-prioritization.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,17 @@ def verify_contract_ancestor_txs_test(self, with_restart=False, use_staking=Fals
address = self.node.getnewaddress()
expected_tx_order = []

for (expected_tx_index, gas_price) in [(1, 100900), (2, 800), (7, 100), (8, 9900)]:
for (expected_tx_index, gas_price) in [(1, 60), (2, 50), (7, 40), (8, 50)]:
tx = CTransaction()
tx.vin = [CTxIn(COutPoint(int(unspent['txid'], 16), unspent['vout']), nSequence=0)]
tx.vout = [
CTxOut(0, scriptPubKey=CScript([b"\x04", CScriptNum(30000), CScriptNum(gas_price), b"\x00", hex_str_to_bytes(contract_address), OP_CALL])),
CTxOut(int((unspent['amount'] - 100)*COIN), scriptPubKey=CScript([OP_DUP, OP_HASH160, hex_str_to_bytes(p2pkh_to_hex_hash(address)), OP_EQUALVERIFY, OP_CHECKSIG]))
CTxOut(int((unspent['amount'] - Decimal('0.1'))*COIN), scriptPubKey=CScript([OP_DUP, OP_HASH160, hex_str_to_bytes(p2pkh_to_hex_hash(address)), OP_EQUALVERIFY, OP_CHECKSIG]))
]
tx_raw = self.node.signrawtransaction(bytes_to_hex_str(tx.serialize()))['hex']

# Make the next vin refer to this tx.
unspent['amount'] -= 101
unspent['amount'] -= Decimal('0.1')
unspent['txid'] = self.node.sendrawtransaction(tx_raw)
unspent['vout'] = 1
expected_tx_order.append((expected_tx_index, unspent['txid']))
Expand All @@ -216,17 +216,17 @@ def verify_contract_ancestor_txs_test(self, with_restart=False, use_staking=Fals
break

# The list of tuples specifies (expected position in block txs, gas_price)
for (expected_tx_index, gas_price) in [(3, 600), (4, 300), (5, 200), (6, 9800)]:
for (expected_tx_index, gas_price) in [(3, 49), (4, 48), (5, 47), (6, 46)]:
tx = CTransaction()
tx.vin = [CTxIn(COutPoint(int(unspent['txid'], 16), unspent['vout']), nSequence=0)]
tx.vout = [
CTxOut(0, scriptPubKey=CScript([b"\x04", CScriptNum(30000), CScriptNum(gas_price), b"\x00", hex_str_to_bytes(contract_address), OP_CALL])),
CTxOut(int((unspent['amount'] - 100)*COIN), scriptPubKey=CScript([OP_DUP, OP_HASH160, hex_str_to_bytes(p2pkh_to_hex_hash(address)), OP_EQUALVERIFY, OP_CHECKSIG]))
CTxOut(int((unspent['amount'] - Decimal('0.1'))*COIN), scriptPubKey=CScript([OP_DUP, OP_HASH160, hex_str_to_bytes(p2pkh_to_hex_hash(address)), OP_EQUALVERIFY, OP_CHECKSIG]))
]
tx_raw = self.node.signrawtransaction(bytes_to_hex_str(tx.serialize()))['hex']

# Make the next vin refer to this tx.
unspent['amount'] -= 101
unspent['amount'] -= Decimal('0.1')
unspent['txid'] = self.node.sendrawtransaction(tx_raw)
unspent['vout'] = 1
expected_tx_order.append((expected_tx_index, unspent['txid']))
Expand Down
Loading

0 comments on commit da13773

Please sign in to comment.