Solidity

如何通過 web3.py 將 Solidity bytes32 轉換/解碼為 Python 字元串

  • August 25, 2021

在 Solidity 合約中,我有這個變數: zBytes32 = “HelloBytes32”;

在 Python web3.py 檢索該變數之後,

zbytes32 = contractInstance.functions.getzBytes32().call()

print(zbytes32) 顯示 zbytes32 的值是什麼:

# b'HelloBytes32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

zbytes32 = zBytes32.decode('utf8')# shows HelloBytes32
print(zbytes32) 

decode(‘utf8’) 刪除前面的 b,print() 將隱藏所有 \x00,但它們仍然存在!為了證明它:

zBytes32str= str(zbytes32)
print('zbytes32 = '+ zBytes32str)
if zBytes32str == 'HelloBytes32':
   print('zbytes32str == "HelloBytes32"')
else:
   print('zbytes32str != "HelloBytes32"')

zbytes32str != “HelloBytes32” 顯示!!!那麼如何在 Python 中正確解碼 byte32 ???

print('\ngetBytes32 raw: {}'.format(zbytes32))# shows HelloBytes32
print('zbytes32.decode("utf8") as string = '+ zbytes32)# shows HelloBytes32

儘管它們看起來與 HelloBytes32 相同,但實際上它們不是!

也許這解釋了以下情況:

arr = contractInstance.functions.getVariables().call()
print('arr[4] in str()= '+ str(arr[4]))#must be converted to string
b2= arr[4].decode('utf8')
print('b2.decode("utf8")= '+ b2)
arr[4] = ''
print('after arr[4] = "", arr[4]= '+ arr[4])
arr[4] = b2
print('after arr[4] = b2, arr[4]= '+ arr[4])
arr[0] = 'What man?'
print('after arr[0] = "What man?", arr[0]= '+ arr[0])
print('\nget many variables: {}'.format(arr))

它顯示在終端中:

arr[4] in str()= b'HelloBytes32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
b2.decode("utf8")= HelloBytes32
after arr[4] = "", arr[4]= 
after arr[4] = b2, arr[4]= HelloBytes32
after arr[0] = "What man?", arr[0]= What man?

get many variables: ['What man?', '0x583031D11...', 111111, False, 'HelloBytes32\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', ['0xCA35b7d...', '0x14723A...'], [9999999, 555555]]

請參閱上面的數組。當我將新值設置為 arr

$$ 0 $$, 有用。 但是當我為 arr 設置一個新值時

$$ 4 $$,它有點工作…… 為什麼當我顯示整個數組時,arr

$$ 4 $$仍然顯示那些 \x00 ??? 我需要將這些值傳遞給另一個腳本,因此我必須確保它們與那些 \x00. 請幫忙。謝謝

這裡的問題是您的變數具有 32 個字節的固定長度,這解釋了右側的零。您可以在 python 中去除零:

zbytes32 = contractInstance.functions.getzBytes32().call()
zbytes32 = zbytes32.hex().rstrip("0")
if len(zbytes32) % 2 != 0:
   zbytes32 = zbytes32 + '0'
zbytes32 = bytes.fromhex(zbytes32).decode('utf8')

列印變數 zbytes32 給出: ‘HelloBytes32’ 和: zbytes32=='HelloBytes32'True

條件部分if len(zbytes32) % 2 != 0在那裡,因為它可能是最後一個字元確實為零並且我們正在刪除它,知道這一點的方法是每個字節都由兩個十六進製字元表示,所以如果刪除零後變數 zbytes32 的長度是奇數,右邊必須加一個零。

希望這可以幫助

引用自:https://ethereum.stackexchange.com/questions/49127