Wie wird eine Karte im Speicher initialisiert?

Ich habe gerade angefangen, solidity zu schreiben, und ich habe einige Fragen, auf die ich keine Antwort finden konnte.

Wenn Sie eine Karte wie diese deklarieren:

struct UserAccount{
    string name;
    uint id;
}

mapping (address => UserAccount) public accounts;

Wie wird das initialisiert? oder womit?

Zugriff zum Beispiel

accounts[0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc]

wird eine Instanz eines Benutzerkontos zurückgegeben? Wenn ja, bedeutet das, dass die Karte für jede mögliche Adresse eine Instanz von UserAccount erstellt? Verbraucht das nicht sehr viel Speicher? Wenn nicht, wie kommt es, dass Sie dies tun können:

accounts[_address].name = _name;

?

Und die zweite Frage:

Ich verweise in meinem Vertrag auf eine Adresse, die der Eigentümer ist, die Adresse, die den Vertrag erstellt hat:

address public owner;
constructor() public {
    owner = msg.sender;
}

Nachdem ich diese Funktion aufgerufen habe:

uint userCount=0;
mapping (address => UserAccount) public accounts;

function createAccount(string _name, uint _id, address _address) onlyOwner() public {
    UserAccount user;
    user.name = _name;
    user.id = _id;
    accounts[_address] = user;
    userCount += 1;
    // accounts[_address].name = _name;
    // accounts[_address].id = _id;
    // userCount += 1;
    emit UserCreated(_address, _id, _name);
}

modifier onlyOwner() {
    require(msg.sender == owner);
    _;        
}

die Besitzeradresse ändert sich. Die kommentierten Zeilen der createAccount-Funktion sind der Weg, es zu tun, ich weiß, aber ich möchte verstehen, warum es nicht funktioniert.

Um mein Problem zu klären, werde ich auch einen js-Test posten.

beforeEach(async () => {
    voting = await Voting.new({from: owner});
});

it("Should delete poll, as owner", async () =>{
    var name = "Sandu";
    console.log("LOCAL OWNER= " + owner);
    console.log("OWNER BEFORE CREATE ACCOUNT FROM SOL= " + await voting.owner());
    await voting.createAccount(name, 1, firstUser,{from:owner});
    console.log("OWNER AFTER CREATE ACCOUNT FROM SOL= " + await voting.owner());
    var pollName = "First Poll";
    var endDateS="2018-08-11T10:20:30Z";
    var endDate=new Date(endDateS)
    await voting.createPoll(pollName, 1, endDate.getTime()/1000,{from:firstUser});


    try{
        await voting.deletePollById(1,{from: owner});
    }catch(err){
        console.log(err.message);
    }

    assert.notEqual(pollName, await voting.getPollById(1));
});

Der obige Test gibt Folgendes aus:

LOCAL OWNER= 0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc //Owner that o have in my js file local, first address from the ganache accounts.
OWNER BEFORE CREATE ACCOUNT FROM SOL= 0x79d66c53ad6f1847288c0d06c01a2b38c38f15bc  //The owner account from my contract before calling the function
OWNER AFTER CREATE ACCOUNT FROM SOL= 0x000000000000000000000000000000000000000a   //The owner account from my contract after calling the function

Ich kann nicht verstehen, warum sich der Wert des Eigentümers ändert, da ich das in meiner Funktion nicht anfasse.

Wenn jemand helfen kann, würde es sehr geschätzt werden. Auch hier kenne ich den richtigen Weg, aber ich poste dies aus dem Wunsch heraus zu verstehen, was ich tue, um die Arbeit nicht zu erledigen.

Alexandru, du solltest das in mehrere Fragen aufteilen.
Sie hängen irgendwie zusammen, alleine machen die meisten meiner Meinung nach keinen Sinn
Wenn Sie so viel Hilfe wie möglich erhalten möchten, müssen Sie Ihre Fragen konzentrieren. Ich denke, das ist viel zu viel für einen einzelnen Beitrag.

Antworten (1)

Ich würde vorschlagen, dass Sie die Solidity-Dokumentation überprüfen.

Hier sind relevante Standorte:

Kurz gesagt: Es findet keine Initialisierung des Datensatzes/Mappings statt. Nahezu alle Datensätze sind mit Nullen vorinitialisiert und bereits vorhanden.

Ein allgemeines Muster, wie es gemacht wird, ist hier skizziert:

function createAccount(string _name, uint _id, address _address) onlyOwner() public {
    UserAccount storage user = accounts[_address];

    require(user.id == 0);

    user.name = _name;
    user.id = _id;

    userCount += 1;

    emit UserCreated(_address, _id, _name);
}
Verbraucht das nicht mehr Gas, als die Referenz der Konten [_Adresse] nicht im Benutzer zu behalten? Das heißt, Sie erstellen keine Speichervariable, rufen Sie einfach aaccounts[_address].name=_name usw. auf.
Danke für die Dokumentation, sie war sehr nützlich, sie beantwortet einige meiner Fragen
UserAccount storage user = accounts[_address];Sie können sich das als Hinweis auf den Speicher vorstellen . Es ist nicht so, dass der gesamte Datensatz kopiert wird. Siehe Speichermodifikator in der Dokumentation.
Thx, Sie waren sehr hilfreich. Ich werde Ihre Antwort noch nicht akzeptieren, da dann der Rest der Fragen unbeantwortet zurückgesendet wird. Ich verspreche, dass ich es irgendwann tun werde.