Decodieren Sie die Eingabedaten bei der Transaktion

Ich habe einen ABI und den inputWert der Transaktion und möchte wissen, welche Funktion für einen Vertrag aufgerufen wurde und mit welchen Argumenten (einem oder mehreren unterschiedlichen Typen), vorzugsweise mit gethund JSON-RPCetwas Pseudocode, den ich dann in Ruby übersetzen kann.

Es gibt ein paar ähnliche Fragen zu SO, aber keine davon hat die Frage wirklich auf eine Weise beantwortet, die für jemanden verständlich ist, der neu bei Ethereum ist.

Als Beispiel verwende ich den MetaCoin von Truffle generierten Vertrag . Ich rufe die Methode getBalance('0xfd46f749f9d916122fe958d7f8d5ad033b187472')auf und erhalte die Eingabe 0xf8b2cb4f000000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472.

truffle(development)> web3.eth.getTransaction('0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff')
{Hash: '0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff',
  einmal: 5,
  blockHash: '0xd150b520eb69a621a7218722c0de5b270c9abc499a90a81ca96340e274599c28',
  Blocknummer: 6,
  Transaktionsindex: 0,
  aus: '0xfd46f749f9d916122fe958d7f8d5ad033b187472',
  zu: '0x8dec2f9cccbe718c7c51e9154f223eb226bb7942',
  Wert: { [String: '0'] s: 1, e: 0, c: [ 0 ] },
  Benzin: 4712388,
  gasPrice: { [String: '100000000000'] s: 1, e: 11, c: [ 100000000000 ] },
  Eingabe: '0xf8b2cb4f00000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472' }

Der ABI lautet wie folgt:

[
    {
      "Konstante": falsch,
      "Eingänge": [
        {
          "name": "adr",
          "Typ": "Adresse"
        }
      ],
      "name": "getBalanceInEth",
      "Ausgänge": [
        {
          "Name": "",
          "Typ": "uint256"
        }
      ],
      "zahlbar": falsch,
      "Typ": "Funktion"
    },
    {
      "Konstante": falsch,
      "Eingänge": [
        {
          "Name": "Empfänger",
          "Typ": "Adresse"
        },
        {
          "Name": "Betrag",
          "Typ": "uint256"
        }
      ],
      "name": "sendCoin",
      "Ausgänge": [
        {
          "name": "ausreichend",
          "typ": "boolesch"
        }
      ],
      "zahlbar": falsch,
      "Typ": "Funktion"
    },
    {
      "Konstante": falsch,
      "Eingänge": [
        {
          "name": "adr",
          "Typ": "Adresse"
        }
      ],
      "name": "getBalance",
      "Ausgänge": [
        {
          "Name": "",
          "Typ": "uint256"
        }
      ],
      "zahlbar": falsch,
      "Typ": "Funktion"
    },
    {
      "Eingaben": [],
      "zahlbar": falsch,
      "Typ": "Konstruktor"
    },
    {
      "anonym": falsch,
      "Eingänge": [
        {
          "indiziert": wahr,
          "name": "_von",
          "Typ": "Adresse"
        },
        {
          "indiziert": wahr,
          "name": "_to",
          "Typ": "Adresse"
        },
        {
          "indiziert": falsch,
          "name": "_wert",
          "Typ": "uint256"
        }
      ],
      "name": "Überweisung",
      "Typ": "Ereignis"
    }
  ]

Wie kann ich jede Eingabe dekodieren, um zu wissen, welche Methode aufgerufen wurde und welche Argumente übergeben wurden?

Aktualisieren

Ich habe alle Daten des Blocks mit dem Eingabefeld ganz unten in den Logs hinzugefügt.

{"number"=>"0x09",
 "hash"=>"0xf543eba0c80d49beea1f934c0f0ad9f0babe272a8318312545d43e6b612e4006",
 "parentHash"=>
  "0xde7a61e8dd84b5e080da8e16430951f7f138347c77ed263d0093e367c9d30775",
 "nonce"=>"0x0",
 "sha3Uncles"=>
  "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
 "logsBloom"=>
  "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 "transactionsRoot"=>
  "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
 "stateRoot"=>
  "0x269cfa04ca1fe73202f788397ece62c520c64d5da7225ba2af2d673a2e9892f2",
 "receiptRoot"=>
  "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
 "miner"=>"0x0000000000000000000000000000000000000000",
 "difficulty"=>"0x0",
 "totalDifficulty"=>"0x0",
 "extraData"=>"0x0",
 "size"=>"0x03e8",
 "gasLimit"=>"0x47e7c4",
 "gasUsed"=>"0x5a3e",
 "timestamp"=>"0x58c83fda",
 "transactions"=>
  [{"hash"=>
     "0xce1eaf03dd1dfa5898243711ebcc1dc5c6357701f5a6c19f0b1f84130cb651fa",
    "nonce"=>"0x08",
    "blockHash"=>
     "0xf543eba0c80d49beea1f934c0f0ad9f0babe272a8318312545d43e6b612e4006",
    "blockNumber"=>"0x09",
    "transactionIndex"=>"0x0",
    "from"=>"0xfd46f749f9d916122fe958d7f8d5ad033b187472",
    "to"=>"0x8dec2f9cccbe718c7c51e9154f223eb226bb7942",
    "value"=>"0x0",
    "gas"=>"0x47e7c4",
    "gasPrice"=>"0x174876e800",
    "input"=>
     "0xf8b2cb4f000000000000000000000000fd46f749f9d916122fe958d7f8d5ad033b187472"}],
 "uncles"=>[]}
Wenn Sie "Eingabe" sagen, meinen Sie Ausgabe? Weil Ihr Beispiel darauf hinzudeuten scheint, dass Sie die Ausgabe analysieren möchten.
@SamuelHawksby-Robinson Ich habe am Ende der Frage weitere Details hinzugefügt, um sie zu klären.

Antworten (5)

Sie können auf ein von Consensys entwickeltes Paket verweisen https://github.com/ConsenSys/abi-decoder

Genial. Dies funktioniert sehr gut und gibt den Namen der Methode ( getBalance), den Namen jedes in ( receiver) übergebenen Arguments und den in ( ) übergebenen Wert 0xfd46f749f9d916122fe958d7f8d5ad033b187472für jedes Argument zurück. Es gibt jedoch nicht den Typ des Arguments zurück?
Ja. Der Typ der Argumente wird nicht zurückgegeben
Ich habe ein Problem eröffnet, ein freundlicher Betreuer des Repos hat es bereits hinzugefügt
Kühl. Schnelle Arbeit

Ah ok, ich verstehe was du fragst. Sie können dies tun web3.toAscii(transactionID.input), um ein für Menschen lesbares Format zu erhalten.

Siehe web3.toAscii https://github.com/ethereum/wiki/wiki/JavaScript-API#web3toascii

Also mit deinem Code wäre es:

transaction = web3.eth.getTransaction('0x5d7a91c9f068d723ac52480c0ef61b9bf3f7b52dc726046e0b47f1beaa2f44ff')
input = web3.toAscii(transaction.input)
console.log(input)
Das gibt mir 'ø²ËO\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000ýF÷IùÙ\u0016\u0012/éX×øÕ­\u0003;\u0018tr'. Ich kenne mich mit Ascii nicht aus und weiß nicht, wie ich aus diesem String ableiten könnte, dass die Methode getBalance(address)mit dem Argument aufgerufen wurde 0xfd46f749f9d916122fe958d7f8d5ad033b187472.
@Samuel Hawksby-Robinson Ich habe Ihren Befehl für meinen Tx-Hash verwendet (0x37361fd8eb5f78c7558ccfaa338c1935ecbc3d486f7a63c5b3e1b245779bc90e). Ich erhalte jedoch diese Fehler: "TypeError: web3.toAscii is not a function" und auch "ReferenceError: input is not defined" Danke
@Questioner verwendet web3.hexToAscii für spätere Versionen von web3js
@migu Da diese Antwort falsch ist, können Sie keine TX-Daten decodieren, ohne abi zu kennen, da die ersten 4 Bytes der Daten Funktionsselektor sind und der Rest gemäß abi-Arg-Typen und -Größen decodiert wird.

Sie können die web3.eth.abi.decodeLogFunktion jetzt verwenden (web3 1.0).

Beispiel aus der Dokumentation:

web3.eth.abi.decodeLog([{
    type: 'string',
    name: 'myString'
},{
    type: 'uint256',
    name: 'myNumber',
    indexed: true
},{
    type: 'uint8',
    name: 'mySmallNumber',
    indexed: true
}],
'0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000748656c6c6f252100000000000000000000000000000000000000000000000000',
['0x000000000000000000000000000000000000000000000000000000000000f310', '0x0000000000000000000000000000000000000000000000000000000000000010']);
> Result {
    '0': 'Hello%!',
    '1': '62224',
    '2': '16',
    myString: 'Hello%!',
    myNumber: '62224',
    mySmallNumber: '16'
}

Sie können das Tool ethereum-input-data-decoder zum Decodieren von Transaktionseingabedaten verwenden, wenn Sie die ABI haben.

Beispiel:

const InputDataDecoder = require('ethereum-input-data-decoder');
const decoder = new InputDataDecoder(`${__dirname}/abi.json`);

const data = `0x67043cae0000000000000000000000005a9dac9315fdd1c3d13ef8af7fdfeb522db08f020000000000000000000000000000000000000000000000000000000058a20230000000000000000000000000000000000000000000000000000000000040293400000000000000000000000000000000000000000000000000000000000000a0f3df64775a2dfb6bc9e09dced96d0816ff5055bf95da13ce5b6c3f53b97071c800000000000000000000000000000000000000000000000000000000000000034254430000000000000000000000000000000000000000000000000000000000`;

const result = decoder.decodeData(data);

console.log(result);

{
  "name": "registerOffChainDonation",
  "types": [
    "address",
    "uint256",
    "uint256",
    "string",
    "bytes32"
    ],
    "inputs": [
      <BN: 5a9dac9315fdd1c3d13ef8af7fdfeb522db08f02>,
      <BN: 58a20230>,
      <BN: 402934>,
      "BTC",
      <Buffer f3 df ... 71 c8>
    ]
}

Auf dem neuen web3.js 1.0 müssen Sie Folgendes verwenden: web3.utils.toAscii(transaction.input).

Manchmal sollten Sie eine tun let input = transaction.input.replace(/^0x/, ``);, um diese nutzlosen Zeichen vom Anfang der Zeichenfolge zu entfernen.

Siehe Dokumente .