Solidität: Array in einer Struktur verwenden

Ich entwerfe / entwickle einen intelligenten Vertrag, in dem wir 2 Arten von Objekten haben: bewegliches Objekt und nicht bewegliches Objekt. Der Status beider Typen wird von Zeit zu Zeit geändert. ex. Im Falle eines sich bewegenden Objekts kann sein Standort geändert werden, aber bei einem sich nicht bewegenden Objekt haben wir keine Standortänderung, aber auch z. Wir haben den Eigentümer des Objekts geändert. Also habe ich a structwie folgt definiert:

struct Object{
    byte[] nonMoveState;
    byte[] MoveState;
  }
  mapping(address => Object) state;

Und ich habe auch ein Ereignis wie folgt definiert, um den Änderungsverlauf aufzubewahren, um ihn im Transaktions-Hash anzuzeigen:

event changeAction(address indexed objectAdd, byte actionType, byte actionValue);

Jetzt muss ich alle Änderungen aufzeichnen, z. im Falle eines sich bewegenden Objekts wird sein Ort von Paris nach London geändert. Wenn ich es dann so mache:

function setAction(address indexed objectAdd, byte actionType, byte actionValue) public returns (bool) {

    state[objectAdd].MoveState[].push("actionValue");
    emit changeAction(address indexed objectAdd, byte actionType, byte actionValue);

    return true;
  }

Und aufrufende Funktion:

setAction(0xE07b6e5a2026CC916A4E2Beb03767ae0ED6af773, "change place", "Paris");

setAction(0xE07b6e5a2026CC916A4E2Beb03767ae0ED6af773, "change place", "London");

Stimmt irgendetwas nicht?

***Zusätzliche Informationen: Tatsächlich wird im Falle eines sich bewegenden Objekts die neue „Aktion“ von RFID/NFC gelesen/geschrieben und dann wird der neue Zustand in der Blockchain gespeichert.

Antworten (1)

Sie können Arrays (und mappingund struct) verwenden, die in Strukturen verschachtelt sind. Ganz so würde ich es nicht machen.

byte[]ist ein Array von Single-Byte. Eine natürliche Art, damit zu arbeiten, ist, wenn Sie jeweils ein Byte verbrauchen oder anhängen möchten. Für einen Brocken wie „Paris“ wäre es nicht meine erste Wahl.

Sie erwähnen die Notwendigkeit, alle Änderungen aufzuzeichnen. Sie haben nicht gesagt, für wessen Konsum. Dies ist wichtig, weil es einen billigen und natürlichen Weg gibt, basierend auf der Annahme, dass der Vertrag immer am aktuellen Stand interessiert ist. Das heißt, der Vertrag benötigt keinen Zugriff auf die Historie, Beobachter jedoch schon. Verwenden Sie dazu Ereignisse.

Die Verwendung eines addressfür einen Schlüssel ist natürlich, wenn das Thema ein Benutzer oder ein Vertrag ist. Ich könnte vorschlagen, in anderen Fällen ein Bedeutungslos zu verwenden bytes32.

Hier ist ein allgemeines Muster, das für Ihr Beispiel angepasst wurde. Siehe Gibt es gut gelöste und einfache Speichermuster für Solidity?

pragma solidity 0.4.19; 

contract Object {

    struct ObjectStruct {
        bytes32 location;
        address owner; // caution about using "owner" because it has a de facto meaning in standard contracts. Landlord, titleHolder ... 
        bool isObject;
    }

    mapping(bytes32 => ObjectStruct) public objectStructs;
    bytes32[] public objectList;

    event LogNewObject(address sender, bytes32 uid, bytes32 location, address owner);
    event LogChangeObjectLocation(address sender, bytes32 uid, bytes32 newLocation);
    event LogChangeObjectOwner(address sender, bytes32 uid, address newOwner);

    function isObject(bytes32 _uid) public view returns(bool isIndeed) {
        return objectStructs[_uid].isObject;
    }

    function getObjectCount() public view returns(uint count) {
        return objectList.length;
    }

    function newObject(bytes32 _uid, bytes32 _location, address _owner) public returns(bool success) {
        require(!isObject(_uid));
        objectStructs[_uid].location = _location;
        objectStructs[_uid].owner = _owner;
        objectStructs[_uid].isObject = true;
        objectList.push(_uid);
        LogNewObject(msg.sender, _uid, _location, _owner);
        return true;
    }

    function changeObjectLocation(bytes32 _uid, bytes32 _newLocation) public returns(bool success) {
        require(isObject(_uid));
        objectStructs[_uid].location = _newLocation;
        LogChangeObjectLocation(msg.sender, _uid, _newLocation);
        return true;
    }

    function changeObjectOwner(bytes32 _uid, address _newOwner) public returns(bool success) {
        require(isObject(_uid));
        objectStructs[_uid].owner = _newOwner;
        LogChangeObjectOwner(msg.sender, _uid, _newOwner);
        return true;
    }

}

Ich hoffe es hilft.

Sicher hilft es zu viel. Danke. Ich hatte nur eine Frage: "Wann" müssen wir die Objektbesitzeradresse ändern (mit der Funktion changeObjectOwner)? eigentlich, in welcher Situation? Können Sie bitte ein Beispiel nennen? Danke. In der Zwischenzeit füge ich meiner Frage einige zusätzliche Informationen hinzu.
Ich hätte auch noch eine Frage: Wenn wir "bytes32 location;" verallgemeinern wollen; in struct, so dass sein Name "state" wäre, was mehrere sub_state ex enthält. "Standort", "Preis", "verkauft" usw. Wie können wir einen solchen "Zustand" in unserer Struktur definieren? Danke noch einmal.
Ich habe meine Frage hier ausführlicher erklärt: ethereum.stackexchange.com/questions/47529/… Vielen Dank für Ihre Hilfe.