Actualicé de python 2 a python 3 y parte del código que solía funcionar ahora está roto. Parece que no puedo arreglarlo. ¿Alguna sugerencia?
Trabajó en python 2
# Convert hex string to byte array
hex_string = "0x00012345...."
data_bytearray = bytearray.fromhex(hex_string.replace("0x", ""))
# Then I pass data_bytearray into transactions.Transaction and it works.
try:
return {'error': False, 'sign': rlp.encode(transactions.Transaction(nonce, gasPrice_int, gas_int, to, value, data_bytearray).sign(privkey)).encode('hex')}
except Exception as msg:
return {'error': True, 'message': msg}
El mismo código no funciona en python 3 y tenga en cuenta que el tipo de datos de la matriz de bytes ha cambiado a
<class 'bytearray'> # python 3 produces this from bytearray.fromhex
<type 'bytearray'> # python 2 produces this from bytearray.fromhex
Obtuve el siguiente error:
{'error': True, 'message': ObjectSerializationError('Serialization failed because of field data ("Object is not a serializable (<class \'bytearray\'>)")',)}
Intenté serializar la salida usando pickle, pero obtuve otro error:
import pickle
data_bytearray = pickle.dumps(data_bytearray)
{'error': True, 'message': AttributeError("'bytes' object has no attribute 'encode'",)}
¿Qué estoy haciendo mal aquí?
Solución:
try:
data_hex_with0xRemoved = data_hex.replace("0x", "")
# If I use bytearray.fromhex, it results in {'error': True, 'message': ObjectSerializationError('Serialization failed because of field data ("Object is not a serializable (<class \'bytearray\'>)")',)}
# data = bytearray.fromhex('deadbeef')
# So instead I use bytes.fromhex
data = bytes.fromhex(data_hex_with0xRemoved)
unsigned_transaction = transactions.Transaction(nonce, gasPrice_int, gas_int, to, value, data)
raw_transaction_bytes = rlp.encode(unsigned_transaction.sign(privkey))
raw_transaction_hex = Web3.toHex(raw_transaction_bytes)
raw_transaction_hex_0xRemoved = raw_transaction_hex.replace("0x", "")
return {'error': False, 'sign': raw_transaction_hex_0xRemoved}
except Exception as msg:
return {'error': True, 'message': msg}
try:
unsigned_transaction = transactions.Transaction(nonce, gasPrice_int, gas_int, to, value, data_bytearray)
raw_transaction = rlp.encode(unsigned_transaction.sign(privkey))
return {'error': False, 'sign': Web3.toHex(raw_transaction)}
except Exception as msg:
return {'error': True, 'message': msg}
El único cambio notable es de raw_transaction.encode('hex')
a Web3.toHex(raw_transaction)
.
Las otras diferencias con la línea original eran simplemente para reducir la cantidad de lógica por línea.
ambos bytes y Web3.toBytes me dieron un error similar a pickle.dumps:
{'error': True, 'message': AttributeError("'bytes' object has no attribute 'encode'",)}
Este ^ comentario fue el más útil, aunque no explica por qué no obtienes el mismo error con bytearray
(creo que deberías). Ver:
In [1]: b'\xaf'.encode('hex')
AttributeError: 'bytes' object has no attribute 'encode'
In [2]: bytearray(b'\xaf').encode('hex')
AttributeError: 'bytearray' object has no attribute 'encode'
Esto realmente no tiene nada que ver con Ethereum, solo con aprender cómo funciona la codificación y el decapado en Python 3. Por ejemplo, esperaría que lo siguiente se comporte exactamente como lo hace el primer ejemplo de código de la pregunta:
try:
return {'error': False, 'sign': bytearray(b'\xaf').encode('hex')}
except Exception as msg:
return {'error': True, 'message': msg}
La codificación en Python 2 tenía una API descuidada y permitía a las personas hacer cosas sin sentido, como "codificar" datos binarios (que ya están codificados, siendo binarios). Por lo tanto, se eliminó por completo del tipo encode()
Python 3 . bytes
Si desea convertir bytes
a hexadecimal en Python 3, hay algunas formas de hacerlo:
> Web3.toHex(b'\xaf')
'0xaf'
> b'\xaf'.hex()
'af'
# note that you don't get the "0x" prefix
> import binascii
> hex_in_bytes = binascii.hexlify(b'\xaf')
b'af'
# binascii made the nonsensical choice to return the hex value in a `bytes` type
# which you can fix up by decoding to a string
> hex_in_bytes.decode('utf8')
'af'
(Todos estos excepto Web3
trabajar con bytearray
también).
data = Web3.toBytes(hexstr=data_hex)
.
tallista
bytes
en lugar debytearray
? Además, te puede interesar:data_bytes = Web3.toBytes(hexstr="0x00012345")
de web3.pyacebo rosenberg
Pantalla de lámpara