Skip to content

Commit 7a305e9

Browse files
committed
Add signing message with eth_key lib
1 parent 5a24eea commit 7a305e9

File tree

8 files changed

+99
-66
lines changed

8 files changed

+99
-66
lines changed

sdk/celo_account/account.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ def _sign_hash(self, message_hash, private_key):
587587
r=r,
588588
s=s,
589589
v=v,
590+
vrs=[v, r, s],
590591
signature=HexBytes(eth_signature_bytes),
591592
)
592593

sdk/celo_account/datastructures.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class SignedMessage(NamedTuple):
3030
r: int
3131
s: int
3232
v: int
33+
vrs: list
3334
signature: HexBytes
3435

3536
def __getitem__(self, index):

sdk/contracts/AccountsWrapper.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ def authorize_attestation_signer(self, signer: str, proof_of_signing_key_possess
197197
Transaction hash
198198
"""
199199
func_call = self._contract.functions.authorizeAttestationSigner(
200-
signer, proof_of_signing_key_possession.v, proof_of_signing_key_possession.r, proof_of_signing_key_possession.s)
200+
signer, proof_of_signing_key_possession.v, self.web3.toBytes(proof_of_signing_key_possession.r), self.web3.toBytes(proof_of_signing_key_possession.s))
201201
return self.__wallet.send_transaction(func_call)
202202

203203
def authorize_vote_signer(self, signer: str, proof_of_signing_key_possession: SignedMessage) -> str:
@@ -213,7 +213,7 @@ def authorize_vote_signer(self, signer: str, proof_of_signing_key_possession: Si
213213
Transaction hash
214214
"""
215215
func_call = self._contract.functions.authorizeVoteSigner(
216-
signer, proof_of_signing_key_possession.v, proof_of_signing_key_possession.r, proof_of_signing_key_possession.s)
216+
signer, proof_of_signing_key_possession.v, self.web3.toBytes(proof_of_signing_key_possession.r), self.web3.toBytes(proof_of_signing_key_possession.s))
217217
return self.__wallet.send_transaction(func_call)
218218

219219
def authorize_validator_signer(self, signer: str, proof_of_signing_key_possession: SignedMessage) -> str:
@@ -237,11 +237,11 @@ def authorize_validator_signer(self, signer: str, proof_of_signing_key_possessio
237237
pub_key = PublicKey.recover_from_msg_hash(
238238
prefixed_message_hash, proof_of_signing_key_possession).to_hex()
239239
func_call = self._contract.functions.authorizeValidatorSignerWithPublicKey(
240-
signer, proof_of_signing_key_possession.v, proof_of_signing_key_possession.r, proof_of_signing_key_possession.s, pub_key)
240+
signer, proof_of_signing_key_possession.v, self.web3.toBytes(proof_of_signing_key_possession.r), self.web3.toBytes(proof_of_signing_key_possession.s), pub_key)
241241
return self.__wallet.send_transaction(func_call)
242242
else:
243243
func_call = self._contract.functions.authorizeValidatorSigner(
244-
signer, proof_of_signing_key_possession.v, proof_of_signing_key_possession.r, proof_of_signing_key_possession.s)
244+
signer, proof_of_signing_key_possession.v, self.web3.toBytes(proof_of_signing_key_possession.r), self.web3.toBytes(proof_of_signing_key_possession.s))
245245
return self.__wallet.send_transaction(func_call)
246246

247247
def authorize_validator_signer_and_bls(self, signer: str, proof_of_signing_key_possession: SignedMessage, bls_public_key: str, bls_pop: str) -> str:
@@ -267,8 +267,8 @@ def authorize_validator_signer_and_bls(self, signer: str, proof_of_signing_key_p
267267
pub_key = PublicKey.recover_from_msg_hash(
268268
prefixed_message_hash, proof_of_signing_key_possession).to_hex()
269269

270-
func_call = self._contract.functions.authorizeValidatorSignerWithKeys(signer, proof_of_signing_key_possession.v, proof_of_signing_key_possession.r,
271-
proof_of_signing_key_possession.s, pub_key, hash_utils.is_leading_with_0x(bls_public_key), hash_utils.is_leading_with_0x(bls_pop))
270+
func_call = self._contract.functions.authorizeValidatorSignerWithKeys(signer, proof_of_signing_key_possession.v, self.web3.toBytes(proof_of_signing_key_possession.r),
271+
self.web3.toBytes(proof_of_signing_key_possession.s), pub_key, hash_utils.is_leading_with_0x(bls_public_key), hash_utils.is_leading_with_0x(bls_pop))
272272
return self.__wallet.send_transaction(func_call)
273273

274274
def generate_proof_of_key_possession(self, account: str, signer: str) -> SignedMessage:
@@ -352,7 +352,7 @@ def set_account(self, name: str, data_encryption_key: str, wallet_address: str,
352352
"""
353353
if proof_of_possession:
354354
func_call = self._contract.functions.setAccount(
355-
name, data_encryption_key, wallet_address, proof_of_possession.v, proof_of_possession.r, proof_of_possession.s)
355+
name, data_encryption_key, wallet_address, proof_of_possession.v, self.web3.toBytes(proof_of_possession.r), self.web3.toBytes(proof_of_possession.s))
356356
else:
357357
func_call = self._contract.functions.setAccount(
358358
name, data_encryption_key, wallet_address, '0x0', '0x0', '0x0')
@@ -370,7 +370,7 @@ def set_name(self, name: str) -> str:
370370
"""
371371
func_call = self._contract.functions.setName(name)
372372
return self.__wallet.send_transaction(func_call)
373-
373+
374374
def set_metadata_url(self, url: str) -> str:
375375
"""
376376
Sets the metadataURL for the account
@@ -397,7 +397,9 @@ def set_wallet_address(self, wallet_address: str, proof_of_possession: SignedMes
397397
Transaction hash
398398
"""
399399
if proof_of_possession:
400-
func_call = self._contract.functions.setWalletAddress(wallet_address, proof_of_possession.v, proof_of_possession.r, proof_of_possession.s)
400+
func_call = self._contract.functions.setWalletAddress(
401+
wallet_address, proof_of_possession.v, self.web3.toBytes(proof_of_possession.r), self.web3.toBytes(proof_of_possession.s))
401402
else:
402-
func_call = self._contract.functions.setWalletAddress(wallet_address, '0x0', '0x0', '0x0')
403+
func_call = self._contract.functions.setWalletAddress(
404+
wallet_address, 0, self.web3.toBytes('0x0'), self.web3.toBytes('0x0'))
403405
return self.__wallet.send_transaction(func_call)

sdk/contracts/GovernanceWrapper.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,9 +336,23 @@ def withdraw(self) -> str:
336336

337337
return self.__wallet.send_transaction(func_call)
338338

339-
def propose(self, values: List[int], destinations: List[str], data: bytes, data_lengths: List[int], description_url: str, parameters: dict = None) -> int:
340-
func_call = self._contract.functions.propose(
341-
values, destinations, data, data_lengths, description_url)
339+
def proposal_to_params(self, values: List[int], description_url: str) -> list:
340+
data = []
341+
for el in values:
342+
addr = el['input'].lstrip('0x')
343+
data.append([elem.encode("hex") for elem in addr])
344+
return [
345+
[el['value'] for el in values],
346+
[el['to'] for el in values if 'to' in el],
347+
self.web3.toBytes('0x'+bytes(data).hex()),
348+
[len(el) for el in data],
349+
description_url
350+
]
351+
352+
def propose(self, values: List[int], description_url: str, parameters: dict = None) -> int:
353+
data = self.proposal_to_params(values, description_url)
354+
355+
func_call = self._contract.functions.propose(data[0], data[1], data[2], data[3], data[4])
342356

343357
return self.__wallet.send_transaction(func_call, parameters)
344358

sdk/contracts/MultiSigWrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def __init__(self, web3: Web3, registry: Registry, address: str, abi: list, wall
3333
self._contract = self.web3.eth.contract(self.address, abi=abi)
3434
self.__wallet = wallet
3535

36-
def submit_or_confirm_transaction(self, destination: str, tx_data: str, value: str = '0', parameters: dict = None) -> str:
36+
def submit_or_confirm_transaction(self, destination: str, tx_data: str, value: int = 0, parameters: dict = None) -> str:
3737
"""
3838
Allows an owner to submit and confirm a transaction.
3939
If an unexecuted transaction matching `tx_object` exists on the multisig, adds a confirmation to that tx ID.

sdk/contracts/SortedOraclesWrapper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ def report_expiry_seconds(self) -> int:
110110
"""
111111
return self._contract.functions.reportExpirySeconds().call()
112112

113-
def is_oldest_report_expired(self, token: str) -> List[bool, str]:
113+
def is_oldest_report_expired(self, token: str) -> list:
114114
"""
115115
Checks if the oldest report for a given token is expired
116116

sdk/utils/utils.py

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,35 +41,12 @@ def linked_list_changes(sorted_list: list, change_list: list):
4141

4242
return {'lessers': lessers, 'greaters': greaters, 'sorted_list': sorted_list}
4343

44-
if __name__ == "__main__":
45-
# lst = [
46-
# { 'address': 'address 1', 'value': 7 },
47-
# { 'address': 'address 2', 'value': 5 },
48-
# { 'address': 'address 3', 'value': 4 },
49-
# { 'address': 'address 4', 'value': 3 },
50-
# { 'address': 'address 5', 'value': 2 },
51-
# { 'address': 'address 6', 'value': 2 },
52-
# { 'address': 'address 7', 'value': 1 },
53-
# ]
54-
# changes = [{'address': 'address 3', 'value': 2}]
55-
# expected = {
56-
# greaters: ['address 6'],
57-
# lessers: ['address 7'],
58-
# }
44+
def int_to_bytes(x: int) -> bytes:
45+
return x.to_bytes((x.bit_length() + 7) // 8, 'big')
5946

60-
lst = [
61-
{ 'address': 'address 1', 'value': 7 },
62-
{ 'address': 'address 2', 'value': 5 },
63-
{ 'address': 'address 3', 'value': 4 },
64-
{ 'address': 'address 4', 'value': 3 },
65-
{ 'address': 'address 5', 'value': 2 },
66-
{ 'address': 'address 6', 'value': 2 },
67-
{ 'address': 'address 7', 'value': 1 },
68-
]
69-
changes = [{'address': 'address 3', 'value': 2}, {'address': 'address 2', 'value': 0}]
70-
#expected = {
71-
# greaters: ['address 6', 'address 7'],
72-
# lessers: ['address 7', NULL_ADDRESS],
73-
# }
74-
75-
print(linked_list_changes(lst, changes))
47+
def string_to_bytes32(data):
48+
if len(data) > 32:
49+
myBytes32 = data[:32]
50+
else:
51+
myBytes32 = data.ljust(32, '0')
52+
return bytes(myBytes32, 'utf-8')

sdk/wallet.py

Lines changed: 58 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from sdk.celo_account.datastructures import SignedTransaction
77
from hexbytes import HexBytes
88
from web3 import Web3
9+
import eth_keys
10+
from sdk.utils import hash_utils
911

1012

1113
class Wallet:
@@ -27,7 +29,9 @@ def __init__(self, web3: Web3, priv_key: bytes, gas_price_contract: "GasPriceCon
2729
self.__accounts = {}
2830
acc = Account()
2931
self.active_account = acc.from_key(priv_key)
30-
self.__accounts.update({self.active_account.address: self.active_account})
32+
self.sign_with_provider = False
33+
self.__accounts.update(
34+
{self.active_account.address: self.active_account})
3135
self._gas_price_contract = gas_price_contract
3236
self._fee_currency = None
3337
self._gateway_fee_recipient = None
@@ -56,15 +60,15 @@ def gas_price(self) -> int:
5660
@property
5761
def gas(self) -> int:
5862
return self._gas
59-
63+
6064
@property
6165
def threshold_gas_value(self) -> int:
6266
return self._threshold_gas_value
6367

6468
@property
6569
def accounts(self) -> dict:
6670
return self.__accounts
67-
71+
6872
@property
6973
def gas_price_contract(self) -> 'GasPriceMinimum':
7074
return self._gas_price_contract
@@ -98,7 +102,7 @@ def gas(self, new_gas: int):
98102
if type(new_gas) != int:
99103
raise TypeError("Incorrect new gas type data")
100104
self._gas = new_gas
101-
105+
102106
@threshold_gas_value.setter
103107
def threshold_gas_value(self, new_threshold_gas_value: int):
104108
if type(new_threshold_gas_value) != int:
@@ -111,22 +115,24 @@ def accounts(self, new_acc: Account):
111115
raise TypeError("Incorrect new account type")
112116
self.__accounts.update({new_acc.address: new_acc})
113117
self.active_account = new_acc
114-
118+
115119
@gas_price_contract.setter
116120
def gas_price_contract(self, gas_price_wrapper: 'GasPriceMinimum'):
117121
self._gas_price_contract = gas_price_wrapper
118122

119123
def add_new_key(self, priv_key: bytes):
120124
acc = Account()
121125
self.active_account = acc.from_key(priv_key)
122-
self.__accounts.update({self.active_account.address: self.active_account})
126+
self.__accounts.update(
127+
{self.active_account.address: self.active_account})
123128

124129
def remove_account(self, account_address: str):
125130
del self.__accounts[account_address]
126131

127132
def change_account(self, account_address: str):
128133
if account_address not in self.__accounts:
129-
raise KeyError("There is no account with such an address in wallet")
134+
raise KeyError(
135+
"There is no account with such an address in wallet")
130136
self.active_account = self.__accounts[account_address]
131137

132138
def construct_transaction(self, contract_method: web3._utils.datatypes, parameters: dict = None) -> dict:
@@ -144,17 +150,18 @@ def construct_transaction(self, contract_method: web3._utils.datatypes, paramete
144150
raise ValueError(
145151
"Can't construct transaction without fee currency, set fee currency please")
146152

147-
nonce = self.web3.eth.getTransactionCount(self.active_account.address)
153+
nonce = self.web3.eth.getTransactionCount(
154+
self.active_account.address)
148155
gas_price = self._gas_price if self._gas_price else self.get_network_gas_price()
149156
base_rows = {'nonce': nonce, 'gasPrice': gas_price, 'gas': self._gas,
150-
'feeCurrency': self._fee_currency, 'from': self.active_account.address}
157+
'feeCurrency': self._fee_currency, 'from': self.active_account.address}
151158

152159
if self._gateway_fee_recipient:
153160
base_rows['gatewayFeeRecipient'] = self._gateway_fee_recipient
154161

155162
if self._gateway_fee:
156163
base_rows['gatewayFee'] = self._gateway_fee
157-
164+
158165
if parameters:
159166
for k, item in parameters.items():
160167
base_rows[k] = item
@@ -166,36 +173,62 @@ def construct_transaction(self, contract_method: web3._utils.datatypes, paramete
166173
raise Exception(
167174
f"Error while construct transaction: {sys.exc_info()[1]}")
168175

169-
def sign_transaction(self, tx: dict) -> SignedTransaction:
176+
def sign_transaction(self, tx: dict) -> 'RawSignedTransaction':
170177
"""
171-
Takes transaction dict, signs it and sends to the blockchain
178+
Takes transaction dict, signs it and returns raw signed transaciton
172179
173180
Parameters:
174181
tx: dict
175182
transaction data in dict
176183
Returns:
177-
signed transaction object
184+
signed raw transaction
178185
"""
179186
try:
180187
signed_tx = self.active_account.sign_transaction(tx)
181-
return signed_tx
188+
print(f"Signed tx localy: {signed_tx}")
189+
return signed_tx.rawTransaction
190+
except:
191+
raise Exception(
192+
f"Error while sign transaction: {sys.exc_info()[1]}")
193+
194+
def sign_message(self, message: 'bytes str') -> 'Signature':
195+
signer_priv_key = eth_keys.keys.PrivateKey(self.active_account._private_key)
196+
signature = signer_priv_key.sign_msg(message)
197+
return signature
198+
199+
def sign_transaction_with_provider(self, tx: dict) -> 'RawSignedTransaction':
200+
"""
201+
Takes transaction dict, signs it and returns raw signed transaciton
202+
203+
Parameters:
204+
tx: dict
205+
transaction data in dict
206+
Returns:
207+
signed raw transaction
208+
"""
209+
try:
210+
signed_tx = self.web3.eth.signTransaction(tx)
211+
return signed_tx.raw
182212
except:
183213
raise Exception(
184214
f"Error while sign transaction: {sys.exc_info()[1]}")
185215

186-
def construct_and_sign_transaction(self, contract_method: web3._utils.datatypes) -> SignedTransaction:
216+
def construct_and_sign_transaction(self, contract_method: web3._utils.datatypes) -> 'RawSignedTransaction':
187217
"""
188218
Takes contract method call object, call method to build transaction and return signed transaction
189219
190220
Parameters:
191221
contract_method: web3._utils.datatypes
192222
object of contract method call
193223
Returns:
194-
signed transaction object
224+
signed raw transaction
195225
"""
196226
try:
197227
tx = self.construct_transaction(contract_method)
198-
signed_tx = self.sign_transaction(tx)
228+
if self.sign_with_provider:
229+
signed_tx = self.sign_transaction_with_provider(tx)
230+
else:
231+
signed_tx = self.sign_transaction(tx)
199232
return signed_tx
200233
except:
201234
raise Exception(
@@ -214,14 +247,19 @@ def send_transaction(self, contract_method: web3._utils.datatypes, parameters: d
214247
"""
215248
try:
216249
tx = self.construct_transaction(contract_method, parameters)
217-
signed_tx = self.sign_transaction(tx)
218-
return self.push_tx_to_blockchain(signed_tx.rawTransaction)
250+
if self.sign_with_provider:
251+
signed_tx = self.sign_transaction_with_provider(tx)
252+
else:
253+
signed_tx = self.sign_transaction(tx)
254+
255+
return self.push_tx_to_blockchain(signed_tx)
219256
except ValueError as e:
220257
error_message = ast.literal_eval(str(e))['message']
221258
if error_message == 'intrinsic gas too low':
222259
gas = gas + self.gas_increase_step if gas else self._gas + self.gas_increase_step
223260
if gas > self.threshold_gas_value:
224-
raise Exception(f"Transaction requires a lot of gas use({gas}), if you want to send transaction set higher gas value and increase threshold gas value")
261+
raise Exception(
262+
f"Transaction requires a lot of gas use({gas}), if you want to send transaction set higher gas value and increase threshold gas value")
225263
self.send_transaction(contract_method, parameters={'gas': gas})
226264
else:
227265
raise ValueError(error_message)

0 commit comments

Comments
 (0)