use of org.ethereum.db.ByteArrayWrapper in project rskj by rsksmart.
the class MutableTrieCache method getStorageKeys.
public Iterator<DataWord> getStorageKeys(RskAddress addr) {
byte[] accountStoragePrefixKey = trieKeyMapper.getAccountStoragePrefixKey(addr);
ByteArrayWrapper accountWrapper = getAccountWrapper(new ByteArrayWrapper(accountStoragePrefixKey));
boolean isDeletedAccount = deleteRecursiveLog.contains(accountWrapper);
Map<ByteArrayWrapper, byte[]> accountItems = cache.get(accountWrapper);
if (accountItems == null && isDeletedAccount) {
return Collections.emptyIterator();
}
if (isDeletedAccount) {
// lower level is deleted, return cached items
return new StorageKeysIterator(Collections.emptyIterator(), accountItems, addr, trieKeyMapper);
}
Iterator<DataWord> storageKeys = trie.getStorageKeys(addr);
if (accountItems == null) {
// uncached account
return storageKeys;
}
return new StorageKeysIterator(storageKeys, accountItems, addr, trieKeyMapper);
}
use of org.ethereum.db.ByteArrayWrapper in project rskj by rsksmart.
the class MutableTrieCache method deleteRecursive.
// //////////////////////////////////////////////////////////////////////////////////
// The semantic of implementations is special, and not the same of the MutableTrie
// It is DELETE ON COMMIT, which means that changes are not applies until commit()
// is called, and changes are applied last.
// //////////////////////////////////////////////////////////////////////////////////
@Override
public void deleteRecursive(byte[] key) {
// Can there be wrongly unhandled interactions interactions between put() and deleteRecurse()
// In theory, yes. In practice, never.
// Suppose that a contract X calls a contract S.
// Contract S calls itself with CALL.
// Contract S suicides with SUICIDE opcode.
// This causes a return to prev contract.
// But the SUICIDE DOES NOT cause the storage keys to be removed YET.
// Now parent contract S is still running, and it then can create a new storage cell
// with SSTORE. This will be stored in the cache as a put(). The cache later receives a
// deleteRecursive, BUT NEVER IN THE OTHER order.
// See TransactionExecutor.finalization(), when it iterates the list with getDeleteAccounts().forEach()
ByteArrayWrapper wrap = new ByteArrayWrapper(key);
deleteRecursiveLog.add(wrap);
cache.remove(wrap);
}
use of org.ethereum.db.ByteArrayWrapper in project rskj by rsksmart.
the class MutableTrieCache method put.
// This method optimizes cache-to-cache transfers
@Override
public void put(ByteArrayWrapper wrapper, byte[] value) {
// If value==null, do we have the choice to either store it
// in cache with null or in deleteCache. Here we have the choice to
// to add it to cache with null value or to deleteCache.
ByteArrayWrapper accountWrapper = getAccountWrapper(wrapper);
Map<ByteArrayWrapper, byte[]> accountMap = cache.computeIfAbsent(accountWrapper, k -> new HashMap<>());
accountMap.put(wrapper, value);
}
use of org.ethereum.db.ByteArrayWrapper in project rskj by rsksmart.
the class RLP method encodeSet.
public static byte[] encodeSet(Set<ByteArrayWrapper> data) {
int dataLength = 0;
Set<byte[]> encodedElements = new HashSet<>();
for (ByteArrayWrapper element : data) {
byte[] encodedElement = RLP.encodeElement(element.getData());
dataLength += encodedElement.length;
encodedElements.add(encodedElement);
}
byte[] listHeader = encodeListHeader(dataLength);
byte[] output = new byte[listHeader.length + dataLength];
System.arraycopy(listHeader, 0, output, 0, listHeader.length);
int cummStart = listHeader.length;
for (byte[] element : encodedElements) {
System.arraycopy(element, 0, output, cummStart, element.length);
cummStart += element.length;
}
return output;
}
use of org.ethereum.db.ByteArrayWrapper in project rskj by rsksmart.
the class HashMapDB method updateBatch.
@Override
public synchronized void updateBatch(Map<ByteArrayWrapper, byte[]> rows, Set<ByteArrayWrapper> keysToRemove) {
if (rows.containsKey(null) || rows.containsValue(null)) {
throw new IllegalArgumentException("Cannot update null values");
}
rows.keySet().removeAll(keysToRemove);
for (Map.Entry<ByteArrayWrapper, byte[]> entry : rows.entrySet()) {
ByteArrayWrapper wrappedKey = entry.getKey();
byte[] key = wrappedKey.getData();
byte[] value = entry.getValue();
put(key, value);
}
for (ByteArrayWrapper keyToRemove : keysToRemove) {
delete(keyToRemove.getData());
}
}
Aggregations