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

zero-pad signature bytes of messages, return r & s as integers #477

Merged
merged 2 commits into from
Dec 1, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
44 changes: 36 additions & 8 deletions tests/core/eth-module/test_accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from web3 import (
Account,
Web3,
)

from web3.utils.datastructures import HexBytes
Expand Down Expand Up @@ -236,12 +237,23 @@ def test_eth_account_hash_message_hexstr(acct, message, expected):
b'Some data',
HexBytes('0x1da44b586eb0729ff70a73c326926f6ed5a25f5b056e7f47fbc6e58d86871655'),
28,
HexBytes('0xb91467e570a6466aa9e9876cbcd013baba02900b8979d43fe208a4a4f339f5fd'),
HexBytes('0x6007e74cd82e037b800186422fc2da167c747ef045e5d18a5f5d4300f8e1a029'),
83713930994764734002432606962255364472443135907807238282514898577139886061053,
43435997768575461196683613590576722655951133545204789519877940758262837256233,
HexBytes('0xb91467e570a6466aa9e9876cbcd013baba02900b8979d43fe208a4a4f339f5fd6007e74cd82e037b800186422fc2da167c747ef045e5d18a5f5d4300f8e1a0291c'), # noqa: E501
),
(
'10284',
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318',
b'10284',
HexBytes('0x0a162a5efbba02f38db3114531c8acba39fe676f09f7e471d93e8a06c471821c'),
27,
143748089818580655331728101695676826715814583506606354117109114714663470502,
227853308212209543997879651656855994238138056366857653269155208245074180053,
HexBytes('0x00515bc8fd32264e21ec0820e8c5123ed58c1195c9ea17cb018b1ad4073cc5a60080f5dcec397a5a8c523082bfa41771568903aa554ec06ba8475ca9050fb7d51b'), # noqa: E501
),

),
ids=['account_1']
ids=['web3js_example', '31byte_r_and_s'],
)
def test_eth_account_sign(acct, message, key, expected_bytes, expected_hash, v, r, s, signature):
signed = acct.sign(message_text=message, private_key=key)
Expand Down Expand Up @@ -271,20 +283,36 @@ def test_eth_account_sign(acct, message, key, expected_bytes, expected_hash, v,
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318',
HexBytes('0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'), # noqa: E501
HexBytes('0xd8f64a42b57be0d565f385378db2f6bf324ce14a594afc05de90436e9ce01f60'),
HexBytes('0x09ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9c'),
HexBytes('0x440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428'),
4487286261793418179817841024889747115779324305375823110249149479905075174044,
30785525769477805655994251009256770582792548537338581640010273753578382951464,
37,
),
(
{
'to': '0xF0109fC8DF283027b6285cc889F5aA624EaC1F55',
'value': 0,
'gas': 31853,
'gasPrice': 0,
'nonce': 0,
'chainId': 1
},
'0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318',
HexBytes('0xf85d8080827c6d94f0109fc8df283027b6285cc889f5aa624eac1f558080269f22f17b38af35286ffbb0c6376c86ec91c20ecbad93f84913a0cc15e7580cd99f83d6e12e82e3544cb4439964d5087da78f74cefeec9a450b16ae179fd8fe20'), # noqa: E501
HexBytes('0xb0c5e2c6b29eeb0b9c1d63eaa8b0f93c02ead18ae01cb7fc795b0612d3e9d55a'),
61739443115046231975538240097110168545680205678104352478922255527799426265,
232940010090391255679819602567388136081614408698362277324138554019997613600,
38,
),
),
ids=['account_1']
ids=['web3js_example', '31byte_r_and_s'],
)
def test_eth_account_sign_transaction(acct, txn, private_key, expected_raw_tx, tx_hash, r, s, v):
signed = acct.signTransaction(txn, private_key)
assert signed.hash == tx_hash
assert signed.r == r
assert signed.s == s
assert signed.v == v
assert signed.rawTransaction == expected_raw_tx
assert signed.hash == tx_hash

account = acct.privateKeyToAccount(private_key)
assert account.signTransaction(txn) == signed
Expand All @@ -304,7 +332,7 @@ def test_eth_account_sign_transaction_from_eth_test(acct, transaction):
# author's ignorance. The example test fixtures and implementations seem to agree, so far.
# See ecdsa_raw_sign() in /eth_keys/backends/native/ecdsa.py
signed = acct.signTransaction(transaction, key)
assert signed.r == HexBytes(expected_raw_txn[-130:-66])
assert signed.r == Web3.toInt(hexstr=expected_raw_txn[-130:-66])

# confirm that signed transaction can be recovered to the sender
expected_sender = acct.privateKeyToAccount(key).address
Expand Down
8 changes: 4 additions & 4 deletions web3/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ def sign(self, message=None, private_key=None, message_hexstr=None, message_text
return AttributeDict({
'message': HexBytes(msg_bytes),
'messageHash': msg_hash,
'r': HexBytes(r),
's': HexBytes(s),
'r': r,
's': s,
'v': v,
'signature': HexBytes(eth_signature_bytes),
})
Expand All @@ -171,7 +171,7 @@ def signTransaction(self, transaction_dict, private_key):
return AttributeDict({
'rawTransaction': HexBytes(rlp_encoded),
'hash': HexBytes(transaction_hash),
'r': HexBytes(r),
's': HexBytes(s),
'r': r,
's': s,
'v': v,
})
8 changes: 8 additions & 0 deletions web3/utils/encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,14 @@ def to_int(value=None, hexstr=None, text=None):
return int(value)


@curry
def pad_bytes(fill_with, num_bytes, unpadded):
return unpadded.rjust(num_bytes, fill_with)


zpad_bytes = pad_bytes(b'\0')


def to_bytes(primitive=None, hexstr=None, text=None):
assert_one_val(primitive, hexstr=hexstr, text=text)

Expand Down
26 changes: 20 additions & 6 deletions web3/utils/signing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
from cytoolz import (
compose,
)

from web3.utils.encoding import (
to_bytes,
to_int,
zpad_bytes,
)

from web3.utils.transactions import (
Expand Down Expand Up @@ -107,21 +112,30 @@ def to_standard_v(enhanced_v):
return v_standard


def sign_transaction_hash(account, transaction_hash, chain_id):
signature = account.sign_msg_hash(transaction_hash)
(v_raw, r, s) = signature.vrs
def to_eth_v(v_raw, chain_id=None):
if chain_id is None:
v = v_raw + V_OFFSET
else:
v = v_raw + CHAIN_ID_OFFSET + 2 * chain_id
return v


to_bytes32 = compose(zpad_bytes(32), to_bytes)


def sign_transaction_hash(account, transaction_hash, chain_id):
signature = account.sign_msg_hash(transaction_hash)
(v_raw, r, s) = signature.vrs
v = to_eth_v(v_raw, chain_id)
return (v, r, s)


def sign_message_hash(key, msg_hash):
signature = key.sign_msg_hash(msg_hash)
(v_standard, r, s) = signature.vrs
v = v_standard + V_OFFSET
eth_signature_bytes = b''.join(map(to_bytes, (r, s, v)))
(v_raw, r, s) = signature.vrs
v = to_eth_v(v_raw)
(r_bytes, s_bytes) = map(to_bytes32, (r, s))
Copy link
Member

Choose a reason for hiding this comment

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

r_bytes, s_bytes = to_bytes32(r), to_bytes32(s)
# or
r_bytes = to_bytes32(r)
s_bytes = to_bytes32(s)

Minor readability improvements?

eth_signature_bytes = r_bytes + s_bytes + to_bytes(v)
return (v, r, s, eth_signature_bytes)


Expand Down