Ich speichere ausstehende Operationen in einer Datenstruktur ähnlich der Multisig. Wallet- Vertrag , dh
struct PendingState {
uint yetNeeded;
uint ownersDone;
uint index;
}
und mein Vertrags-Pseudo-ish-Code:
contract c {
mapping(bytes32 => PendingState) m_pending;
bytes32[] m_pendingIndex;
// initialize operation:
var pending = m_pending[_h];
pending.yetNeeded = bla;
pending.ownersDone = bla;
pending.index = m_pendingIndex.length++;
m_pendingIndex[pending.index] = _h;
// remove the current operation when finished
delete m_pendingIndex[m_pending[_h].index];
delete m_pending[_h];
}
Wenn es jedoch drei (Index = 0, 1, 2) ausstehende Operationen gab, als wir die zweite abgeschlossen und entfernt haben, dann sind wir am Ende gefüllt und m_pendingIndex[0]
leer . Erhöht sich dadurch der Gasbedarf für spätere Operationen? Soll ich die Objekte zurückschieben, bis keine freie Stelle mehr vorhanden ist? Ich kann mir vorstellen, dass dieser Prozess selbst Kosten verursacht, aber er könnte vorzuziehen sein, um DOS-Angriffe zu verhindern.m_pendingIndex[2]
m_pendingIndex[1]
Danke für jede Hilfe,
Diese Zeilen
delete m_pendingIndex[m_pending[_h].index];
delete m_pending[_h];
tun Sie nicht, was Sie wahrscheinlich denken, dass sie tun. Es genügt zu sagen, dass Sie keine Informationen aus einer unveränderlichen Blockchain entfernen können.
Wie Edmund sagte, verknüpfte Listen. Es gibt eine Möglichkeit, ein Element effizient aus einem ungeordneten Array zu entfernen (damit es nicht unbegrenzt wächst) und dies mit begrenzten Gaskosten. Die Löschoperation ist also in jeder Größenordnung gleich teuer. In Summe:
Ich habe eine Kombination von Zuordnungen mit Zeigern auf Array-Zeilen verwendet, um ein logisches Löschen aus Arrays und eine Reihe anderer Vorteile zu ermöglichen. Funktioniert in vielen Situationen:
Ausführlichere Beschreibung: https://medium.com/@robhitchens/solidity-crud-part-1-824ffa69509a#.c3e5nom01
Möglicherweise kann das Muster in dieser Situation helfen.
Wenn Sie alles hochschalten müssen, haben Sie möglicherweise unbegrenzte Benzinkosten, was Sie im Allgemeinen vermeiden möchten, es sei denn, Sie wissen, dass es eine praktische Grenze gibt. Aber wenn Sie die Elemente nicht entfernen, haben Sie stattdessen möglicherweise endlos wachsende Kosten, wenn Sie stattdessen die Daten durchlaufen müssen, da Sie alle fehlenden Einträge lesen und feststellen müssen, dass sie nicht vorhanden sind.
Die Lösung besteht oft darin, anstelle eines Arrays eine verkettete Liste (oder manchmal eine doppelt verkettete Liste) zusammen mit einer Variablen zu verwenden, die Ihnen sagt, welches Element das erste in der Liste ist. Auf diese Weise können Sie Artikel mit vorhersehbaren, begrenzten Benzinkosten aus der Liste entfernen, unabhängig von der Anzahl der Artikel in der Liste.
Ich würde empfehlen, zuerst den zu löschenden Index und den letzten Index auszutauschen und dann einfach 'pop()' zu verwenden.
Jaybee
length
Rücken nach unten stellen0
?Rob Hitchens
Jaybee
Rob Hitchens
Jaybee
userStructs
Zuordnung "löschen", setzen Sie ihn nieuserStructs[userAddress].index
auf seinen Standardzustand zurück (der verwirrenderweise0
) ist. Es scheint keine Rolle zu spielen, daisUser()
überprüft wird, ob der Benutzer an diesem bestimmten Index derselbe ist wie der, nach dem Sie suchen, aber es ist schlecht, wenn ein falscher Index in einem "deleted" hängtUserStruct
?Rob Hitchens
delete userStructs[userAddress]
:-) Sie können (angepasst an Ihren Anwendungsfall) überlegen , aber die Logik des Systems benötigt es nicht . Tatsächliche Löschungen können dazu beitragen, die Größe des Zustandsversuchs zu reduzieren, was dazu beitragen kann, die Synchronisierung für einige Clients zu optimieren. Es gibt negative Gaskosten für diese OP (Rückerstattung), aber in der Praxis habe ich festgestellt, dass die Gesamttransaktionskosten fürdelete
gewöhnlich steigen, sonst wäre es Teil des Musters.