Neues Strukturelement kann nicht zu Mapping oder Array hinzugefügt werden

Versuchen Sie, ein Beispiel basierend auf Struct zu erstellen, und speichern Sie eine Liste von Structs als Zuordnung. Aber wenn ich ein Element hinzufüge und versuche, es abzurufen, kann ich dieses Element nicht in der Zuordnung finden

Unten ist mein Vertrag

contract ItemListContract {
    struct  item 
    {
      bytes iname;
      uint16 itemid;
      bytes icode;
      uint ivalue;
    }
    uint itemcount;
    mapping(bytes => item) itemlist;
    item[] itemarray;
    function ItemListContract()
    {
       log0('hi');
    }
    function AddItem(bytes name, uint16 iid, bytes code, uint val)
    {        
       var itemnew = item(name, iid ,code, val);
       log0(itemnew);
       itemlist[code] = itemnew;
       itemarray.push(itemnew);
       itemcount++;
    }
    function countitemlist() returns (uint count)
    {     
      return itemcount;
    }

    function removeitem(bytes code)
    {
    delete itemlist[code];
    itemcount--;
    }
    function getitem(bytes code) returns (bytes iname, uint val)
    {   
      return (itemlist[code].iname,itemlist[code].ivalue);
    }
}

Ich habe versucht, Artikel mit den folgenden Anweisungen hinzuzufügen

var listarrayinterface =[{"constant":false,"inputs":[{"name":"name","type":"bytes"},{"name":"iid","type":"uint16"},{"name":"code","type":"bytes"},{"name":"val","type":"uint256"}],"name":"AddItem","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"code","type":"bytes"}],"name":"getitem","outputs":[{"name":"iname","type":"bytes"},{"name":"val","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"countitemlist","outputs":[{"name":"count","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"code","type":"bytes"}],"name":"removeitem","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"countitemarray","outputs":[{"name":"count","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"code","type":"bytes"}],"name":"getitemfromarray","outputs":[{"name":"iname","type":"bytes"},{"name":"val","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"}];
var listarratcontract = eth.contract(listarrayinterface).at("0x62fxxx")
listarratcontract.AddItem.call({data:{name:"item2",iid:2,code:"i2",val:2}})

nach dem aufruf des vertrages mit den oben genannten daten bekam ich [] als antwort

Nun habe ich versucht die gespeicherten Daten per abzufragen

listarratcontract.countitemlist.call()
0

bekam Antwort als 0.

als ich mit anrief

listarratcontract.getitem.call("i2")
["0xo",0]

Ich kann die gespeicherten Daten nicht abrufen oder weiß nicht einmal, ob die Daten gespeichert sind oder nicht?

kann jemand darauf hinweisen, was das Problem sein könnte?

Antworten (1)

Zusammenfassung

Die Probleme sind:

  1. Das Standardgas für eine Transaktion zur Ausführung eines Kontrakts beträgt 90.000 . Ihre auszuführende Erklärung addItem()gibt die Gasmenge nicht an, daher wird von 90.000 ausgegangen. Die Ausführung dieser addItem()Methode erforderte 226.554 Gas.
  2. Die getItem(...)Methode sollte als konstant markiert werden, um die Werte korrekt zurückzugeben.
  3. Die countItemList()Methode sollte auch als konstant markiert werden, um den Wert korrekt zurückzugeben.
  4. Und wie @Tjaden Hessunten kommentiert, führt Ihre Anweisung listarratcontract.AddItem.call({data:{name:"item2",iid:2,code:"i2",val:2}})die Methode nicht als Transaktion aus, die die Blockchain-Daten ändert. Siehe unten für die Anweisung, diese Methode als Transaktion auszuführen. Siehe Was ist der Unterschied zwischen einer Transaktion und einem Anruf? Für weitere Informationen.



Einzelheiten

Ich habe einige kleinere Änderungen an Ihrem Quellcode vorgenommen:

  • Formatierung.
  • Kennzeichnung countItemList()und getItem(...)als konstant.
  • Das Auskommentieren log0(itemnew)dieser Anweisung verursacht einen Fehler in meinem Browser Solidity / geth.

Hier ist der Quellcode:

pragma solidity ^0.4.0;

contract ItemListContract {
    struct item {
        bytes iname;
        uint16 itemid;
        bytes icode;
        uint ivalue;
    }

    uint itemCount;
    mapping(bytes => item) itemList;
    item[] itemArray;

    function ItemListContract() {
        log0('hi');
    }

    function addItem(bytes name, uint16 iid, bytes code, uint val) {        
        var itemnew = item(name, iid ,code, val);
        // log0(itemnew);
        itemList[code] = itemnew;
        itemArray.push(itemnew);
        itemCount++;
    }

    function countItemList() constant returns (uint count) {     
        return itemCount;
    }

    function removeItem(bytes code) {
        delete itemList[code];
        itemCount--;
    }

    function getItem(bytes code) constant returns (bytes iname, uint val) {   
        return (itemList[code].iname, itemList[code].ivalue);
    }
}

Der folgende Screenshot Ihres Codes, der mit Browser Solidity bereitgestellt und ausgeführt wird, zeigt, dass die addItem(...)Methode 226.554 Gas verbraucht hat.

Geben Sie hier die Bildbeschreibung ein

Beim Aufrufen getItem(...)wurde der im Aufruf hinzugefügte Wert an zurückgegeben addItem(...). Und der Anruf countItemList()gab 1 zurück.

Der folgende Abschnitt zeigt die Ausführung Ihrer Kontraktmethoden über die gethKommandozeile und die erhöhte Gasmenge:

> var itemListABI = [{"constant":false,"inputs":[{"name":"code","type":"bytes"}],"name":"removeItem","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"countItemList","outputs":[{"name":"count","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"code","type":"bytes"}],"name":"getItem","outputs":[{"name":"iname","type":"bytes"},{"name":"val","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"name","type":"bytes"},{"name":"iid","type":"uint16"},{"name":"code","type":"bytes"},{"name":"val","type":"uint256"}],"name":"addItem","outputs":[],"payable":false,"type":"function"},{"inputs":[],"type":"constructor"}];
undefined
> var itemList = eth.contract(itemListABI).at("0xee7b790b638553cc95a4355d422536bad1566fd7");
undefined
> itemList.addItem("item3", 3, "i3", 3, {from: eth.accounts[0], gas: 500000});
"0xc70469c662c759627c217827845a6567ff1ac1dd2ebd5e0d52fe817aeeb7867a"
> itemList.countItemList()
3
> itemList.getItem("i3")
["0x6974656d33", 3]



Gaskostenunterschiede - Beantwortung der Frage in den Kommentaren

addItem(...)Gaskostenunterschiede

Ich habe addItem(...)4 mal angerufen mit folgenden Parametern und den dazugehörigen Spritkosten:

  • "Element1", 1, "i1", 1 - 226.554
  • "item2", 2, "i2", 2 - 196.554
  • "item3", 3, "i3", 3 - 196.554
  • "item4", 4, "i4", 4 - 196.554

Es folgt der Screenshot von Browser Solidity:Geben Sie hier die Bildbeschreibung ein

Ich habe eine debug.traceTransaction(...)für die erste und zweite Operation durchgeführt, um die Unterschiede in den Benzinkosten zu finden.

Hier ist ein Screenshot, der den ersten Unterschied bei den Benzinkosten zeigt:Geben Sie hier die Bildbeschreibung ein

Und hier ist ein Screenshot, der den zweiten Unterschied bei den Benzinkosten zeigt:Geben Sie hier die Bildbeschreibung ein

Hier ist der Code für addItem(...):

function addItem(bytes name, uint16 iid, bytes code, uint val) {        
    var itemnew = item(name, iid ,code, val);
    // log0(itemnew);
    itemList[code] = itemnew;
    itemArray.push(itemnew);
    itemCount++;
}

Die Differenz der Gaskosten zwischen dem ersten und dem zweiten Vorgang beträgt (20.000 x 2) - (5.000 x 2) = 30.000 für den SSTOREVorgang bei Zuweisung itemnewzu itemList[code]und itemArray.push(...).

Aus der Gebührenordnung im Ethereum Yellow Paper können Sie ersehen, dass die erste SSTOREOperation zum Speichern der neuen Daten itemListund itemArraySetzen des Speicherwerts von null auf ungleich null 20.000 Gas kostet (unten grün hervorgehoben).

Die zweite SSTOREOperation zum Speichern der neuen Daten itemListund itemArraysetzt den Speicherwert von ungleich null auf ungleich null und kostet 5.000 Benzin (unten rosa hervorgehoben).

Geben Sie hier die Bildbeschreibung ein


removeItem(...)Gaskostenunterschiede

Ich habe dann removeItem(...)4 mal angerufen mit folgenden Parametern und den dazugehörigen Spritkosten:

  • "Element1" - 48.181
  • "Element2" - 48.181
  • "Element3" - 48.181
  • "Element4" - 33.181

Es folgt der Screenshot von Browser Solidity:Geben Sie hier die Bildbeschreibung ein

Sie können eine debug.traceTransaction(...)für den dritten und vierten Vorgang ausführen, um die Unterschiede in den Benzinkosten zu ermitteln.

Ich denke, das wichtigste dünne OP, das fehlt, ist, dass .callin web3 eine Transaktion simuliert wird. Sie wollten eine tatsächliche Transaktion verwenden
Ich habe festgestellt, dass sich der Gasverbrauch jedes Mal ändert, wenn ich dieselbe Funktion ausführe, ich habe removeItem dreimal ausgeführt und jedes Mal unterschiedliche Transaktionskosten und Ausführungskosten angezeigt. Ergebnis: „0x“ Transaktionskosten: 24023 Gas. Ausführungskosten: 26070 Gas. Ergebnis: „0x“ Transaktionskosten: 63046 Gas. Ausführungskosten: 41070 Gas. Ergebnis: „0x“ Transaktionskosten: 48046 Gas. Ausführungskosten: 26070 Gas.
Ich habe einen neuen Abschnitt hinzugefügt, um Ihnen die Quelle der Differenz in den Benzinkosten für die addItem(...)beim ersten und zweiten Mal aufgerufene Funktion zu zeigen. Sie können die gleiche Art von Analyse verwenden, um die Differenz der Gaskosten für die removeItem(...)Funktion „Vorletztes Mal“ und „Letztes Mal“ zu ermitteln. Bitte stellen Sie eine neue Frage unter Bezugnahme auf diese Fragen und Antworten, wenn Sie weitere Fragen zu den Gaskosten haben.