Solidity-Arrays speichern keine Werte

Ich habe einen Basisvertrag wie diesen geschrieben, um Zertifikate zu speichern:

    pragma solidity ^0.4.2;

    /// @title Sending and storing certifications to the blockchain
    contract CertificationStore {

        struct Certification {
            string firstName;
            string lastName;
            string certName;
            string institution;
            string description;
            uint year;
            uint month;
            uint day;
        }

        mapping (address => Certification) public certifications;

        Certification[] public certArray;
        address[] public addressIdx;

        uint numCerts;

        Certification public aCert; 

        event Send(address indexed _from);

        function CertificationStore() {
        }

        function getCertArrayLength() returns(uint) {
            return certArray.length;
        }

        function getAddressIdxLength() returns(uint) {
            return addressIdx.length;
        }

        function sendCert(address acct, string fn, string ln, string cn, 
            string ins, string desc, uint yy, uint mm, uint dd) returns(uint certId) {


            certifications[acct] = Certification({
                    firstName: fn,
                    lastName: ln,
                    institution: ins,
                    description: desc,
                    certName: cn,
                    year: yy,
                    month: mm,
                    day: dd
                });

            certId = numCerts++;

            addressIdx[certId] = acct;
            certArray[certId] = Certification({
                    firstName: fn,
                    lastName: ln,
                    institution: ins,
                    description: desc,
                    certName: cn,
                    year: yy,
                    month: mm,
                    day: dd
                });
            Send(acct);

        }

        function getFirstName(address _from) public returns(string) {
            for (uint i = 0; i < certArray.length; i++) {
                Certification cert = certArray[i];
                string name = cert.firstName;
                address acct = addressIdx[i];
                if(acct == _from) {
                    return name;
                }
            }

            return ("no name found");
        }

    }

Ich verwende web3 und Truffle, um ein Frontend zu erstellen, um mit diesem Vertrag zu interagieren.

Wenn ich am Frontend sendCert mit allen Werten aufrufe, scheint es sie der Karte hinzuzufügen, aber NICHT dem Array. Ich habe versucht, das Array auf die oben gezeigte Weise und mit der .push() -Methode hinzuzufügen, und wenn ich die beiden Funktionen aufrufe, um die certArray-Länge und die addressIdx-Array-Länge zu überprüfen, gibt es IMMER 0 zurück.

Die Methode sendCert, die die Zertifizierungen zum Array hinzufügen soll, und die Zuordnung gibt auch 0 für diese certId zurück, egal wie oft ich Zertifizierungen hinzufüge.

Mache ich hier etwas falsch? Im Frontend habe ich einen Rückruf, der "Erfolg" protokolliert, wenn die Zertifizierung erfolgreich gesendet und durch diese Methode erfolgreich ausgeführt wird.

Gibt es schließlich eine Möglichkeit, den Inhalt der beiden Arrays an das Frontend zu senden, um sie in Javascript anstelle von Solidity zu bearbeiten?

Vielen Dank für Ihre Hilfe und Geduld!

Antworten (1)

Mit waren Sie auf dem richtigen Weg .push.

addressIdx.push(acct);
certArray.push(Certification({

Hier geht noch viel mehr. Das große Ganze ist, dass Sie die Zertifikatsstruktur zweimal speichern - einmal im mappingund einmal in einem Array. Dies ist nicht optimal. Außerdem denke ich, dass die Verwendung von addressfür die eindeutige Kennung jedes Zertifikats zu Einschränkungen und Verwirrung führt. Warum ist ein Zertifikat durch die ID von jemandem bekannt, der es erworben hat? Was ist, wenn ein Student mehr als ein Zertifikat erwirbt? Es ist wahrscheinlich besser, jedes Zertifikat mit einer beliebigen ID zu referenzieren:

mapping(bytes32 => CertificateStruct) public certificateStructs;

und dann können Sie eine iterierbare Liste davon pflegen:

bytes32[] public certificateList;

Möglicherweise möchten Sie auch eine Liste mit Zertifikaten für jede Studentenadresse, die zu etwa folgendem Ergebnis führen könnte:

mapping(address => bytes32[]) studentCertificates;

Ihre schreibgeschützten Funktionen wie function getAddressIdxLength() returns(uint)sind nicht mit dem constantModifikator gekennzeichnet, sodass Sie nicht das erwartete erhalten uint. Es kostet Gas, eine Transaktion zu senden, und Sie können die Antwort aufgrund von Verzögerungen beim Mining nicht sehen . Wenn Sie hinzufügen constant, sehen Sie das Erwartete 1und die Dinge werden wieder sinnvoll.

Für eine Plattform mit teuren Speicherkosten ist es ein wenig datenlastig, und Sie werden möglicherweise feststellen, dass eine Zuordnung von einer Adresse zu einer Zertifikats-ID zusammen mit einer Off-Chain-Speicherung das Problem des Nachweises, dass ein bestimmter Student eine Auszeichnung erhalten hat, angemessen löst gegebenes Zertifikat zu einem bestimmten Zeitpunkt. Der Schlüssel ist, zu sparen.

Die Loopy-Suchfunktion ist ein Antimuster, da sie bei einer (unberechneten) Anzahl von Iterationen die Sperrgasgrenze überschreitet und überhaupt nicht mehr funktioniert. Gestalten Sie im Allgemeinen alles so, dass es in jeder Größenordnung zu gleichbleibenden Gaskosten kommt. Entweder müssen Sie dies nicht wirklich in den Vertrag aufnehmen, da erwartet wird, dass der Zusatzspeicher die zusätzlichen Details enthält, oder Sie erstellen interne Zuordnungen, um die Suche in einem Vorgang zu lösen.

Ich habe festgestellt, pragma solidity ^0.4.2;dass es ziemlich alt ist. Wenn constantIhnen der Vorschlag Probleme bereitet, liegt das wahrscheinlich daran, dass Sie tatsächlich einen neueren Compiler verwenden. Versuchen Sie es in diesem Fall mit view.

Dieser Thread könnte Ihnen einige Ideen geben. Gibt es gut gelöste und einfache Speichermuster für Solidity?

Ich hoffe es hilft.

Hier ist der leicht modifizierte Vertrag in Remix, um zu zeigen, dass er funktioniert:

Geben Sie hier die Bildbeschreibung ein