New Repositroy management:
+ Repository encapsulattion of all the local peer data + NewContractDetails - will be renamed for ContractDetails + NewContractDetails - saves now the storage table and the program code + RepositoryTest testing for the abilities of Repository design
This commit is contained in:
parent
d2a3259fdf
commit
9d650350f0
|
@ -63,6 +63,15 @@ public class AccountState {
|
|||
return nonce;
|
||||
}
|
||||
|
||||
public byte[] getStateRoot() {
|
||||
return stateRoot;
|
||||
}
|
||||
|
||||
public void setStateRoot(byte[] stateRoot) {
|
||||
rlpEncoded = null;
|
||||
this.stateRoot = stateRoot;
|
||||
}
|
||||
|
||||
public void incrementNonce(){
|
||||
rlpEncoded = null;
|
||||
this.nonce = nonce.add(BigInteger.ONE);
|
||||
|
@ -81,9 +90,11 @@ public class AccountState {
|
|||
return balance;
|
||||
}
|
||||
|
||||
public void addToBalance(BigInteger value){
|
||||
public BigInteger addToBalance(BigInteger value){
|
||||
if (value.signum() != 0) rlpEncoded = null;
|
||||
this.balance = balance.add(value);
|
||||
|
||||
return this.balance;
|
||||
}
|
||||
|
||||
public void subFromBalance(BigInteger value) {
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
package org.ethereum.db;
|
||||
|
||||
import org.ethereum.trie.Trie;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPElement;
|
||||
import org.ethereum.util.RLPItem;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.ethereum.vm.DataWord;
|
||||
|
||||
import javax.enterprise.inject.New;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 24/06/2014 00:12
|
||||
*/
|
||||
|
||||
public class NewContractDetails {
|
||||
|
||||
private byte[] rlpEncoded;
|
||||
|
||||
List<DataWord> storageKeys = new ArrayList<DataWord>();
|
||||
List<DataWord> storageValues = new ArrayList<DataWord>();
|
||||
|
||||
byte[] code;
|
||||
|
||||
Trie storageTrie = new Trie(null);
|
||||
|
||||
|
||||
public NewContractDetails(){}
|
||||
public NewContractDetails(byte[] rlpCode) {
|
||||
decode(rlpCode);
|
||||
}
|
||||
|
||||
public NewContractDetails(Map<DataWord, DataWord> storage, byte[] code) {}
|
||||
|
||||
public void put(DataWord key, DataWord value){
|
||||
|
||||
storageTrie.update(key.getData(), value.getData());
|
||||
storageKeys.add(key);
|
||||
storageValues.add(value);
|
||||
this.rlpEncoded = null;
|
||||
}
|
||||
|
||||
public DataWord get(DataWord key){
|
||||
|
||||
if (storageKeys.size() == 0)
|
||||
return null;
|
||||
|
||||
int foundIndex = -1;
|
||||
for (int i = 0; i < storageKeys.size(); ++i){
|
||||
if (storageKeys.get(i).equals(key) ){
|
||||
foundIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundIndex != -1)
|
||||
return storageValues.get(foundIndex);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(byte[] code) {
|
||||
this.code = code;
|
||||
this.rlpEncoded = null;
|
||||
}
|
||||
|
||||
public byte[] getStorageHash(){
|
||||
return storageTrie.getRootHash();
|
||||
}
|
||||
|
||||
public void decode(byte[] rlpCode){
|
||||
RLPList data = RLP.decode2(rlpCode);
|
||||
RLPList rlpList = (RLPList)data.get(0);
|
||||
|
||||
RLPList keys = (RLPList)rlpList.get(0);
|
||||
RLPList values = (RLPList)rlpList.get(1);
|
||||
RLPElement code = (RLPElement)rlpList.get(2);
|
||||
|
||||
if (keys.size() > 0){
|
||||
storageKeys = new ArrayList<>();
|
||||
storageValues = new ArrayList<>();
|
||||
}
|
||||
|
||||
for (int i = 0; i < keys.size(); ++i){
|
||||
|
||||
RLPItem rlpItem = (RLPItem)keys.get(i);
|
||||
storageKeys.add(new DataWord(rlpItem.getRLPData()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < values.size(); ++i){
|
||||
RLPItem rlpItem = (RLPItem)values.get(i);
|
||||
storageValues.add(new DataWord(rlpItem.getRLPData()));
|
||||
}
|
||||
|
||||
for (int i = 0; i < keys.size(); ++i){
|
||||
|
||||
DataWord key = storageKeys.get(i);
|
||||
DataWord value = storageValues.get(i);
|
||||
storageTrie.update(key.getData(), value.getData());
|
||||
}
|
||||
|
||||
this.code = code.getRLPData();
|
||||
|
||||
this.rlpEncoded = rlpCode;
|
||||
}
|
||||
|
||||
public byte[] getEncoded(){
|
||||
|
||||
if(rlpEncoded == null) {
|
||||
|
||||
int size = storageKeys == null ? 0 : storageKeys.size();
|
||||
|
||||
byte[][] keys = new byte[size][];
|
||||
byte[][] values = new byte[size][];
|
||||
|
||||
|
||||
for (int i = 0; i < size; ++i){
|
||||
DataWord key = storageKeys.get(i);
|
||||
keys[i] = RLP.encodeElement(key.getData());
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; ++i){
|
||||
DataWord value = storageValues.get(i);
|
||||
values[i] = RLP.encodeElement( value.getData() );
|
||||
}
|
||||
|
||||
byte[] rlpKeysList = RLP.encodeList(keys);
|
||||
byte[] rlpValuesList = RLP.encodeList(values);
|
||||
byte[] rlpCode = RLP.encodeElement(code);
|
||||
|
||||
this.rlpEncoded = RLP.encodeList(rlpKeysList, rlpValuesList, rlpCode);
|
||||
}
|
||||
return rlpEncoded;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public Map<DataWord, DataWord> getStorage(){
|
||||
|
||||
Map<DataWord, DataWord> storage = Collections.unmodifiableMap(new HashMap<DataWord, DataWord>());
|
||||
|
||||
for (int i = 0;
|
||||
storageKeys != null &&
|
||||
i < storageKeys.size(); ++i){
|
||||
storage.put(storageKeys.get(i), storageValues.get(i));
|
||||
}
|
||||
|
||||
return storage;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
package org.ethereum.db;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.trie.TrackTrie;
|
||||
import org.ethereum.trie.Trie;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
***********************************************************************************
|
||||
MainRepository
|
||||
|
|
||||
--> AccountState ---> Trie ---> leveldb (state) /key=address
|
||||
--> nonce
|
||||
--> balance
|
||||
--> stateRoot
|
||||
--> codeHash
|
||||
|
|
||||
--> ContractDetails ---> leveldb(details) /key=address
|
||||
--> code ---> sha3(code) // saved into AccountInfo.codeHash
|
||||
--> storage ---> Trie // to calculate the AccountInfo.stateRoot
|
||||
***********************************************************************************
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 23/06/2014 23:01
|
||||
*/
|
||||
public class Repository {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("repository");
|
||||
|
||||
TrackTrie accountStateDB;
|
||||
TrackDatabase contractDetailsDB;
|
||||
|
||||
// todo: Listeners listeners
|
||||
// todo: cash impl
|
||||
|
||||
DatabaseImpl detailsDB = null;
|
||||
DatabaseImpl stateDB = null;
|
||||
|
||||
|
||||
public Repository() {
|
||||
|
||||
detailsDB = new DatabaseImpl("details");
|
||||
contractDetailsDB = new TrackDatabase(detailsDB);
|
||||
|
||||
|
||||
stateDB = new DatabaseImpl("state");
|
||||
Trie worldState = new Trie(stateDB.getDb());
|
||||
accountStateDB = new TrackTrie(worldState);
|
||||
}
|
||||
|
||||
private Repository(TrackTrie accountStateDB, TrackDatabase contractDetailsDB){
|
||||
this.accountStateDB = accountStateDB;
|
||||
this.contractDetailsDB = contractDetailsDB;
|
||||
}
|
||||
|
||||
public Repository getTrack(){
|
||||
|
||||
TrackTrie trackState = new TrackTrie(accountStateDB);
|
||||
TrackDatabase trackDetails = new TrackDatabase(contractDetailsDB);
|
||||
|
||||
return new Repository (trackState, trackDetails);
|
||||
}
|
||||
|
||||
public void startTracking(){
|
||||
|
||||
logger.info("start tracking");
|
||||
accountStateDB.startTrack();
|
||||
contractDetailsDB.startTrack();
|
||||
}
|
||||
|
||||
public void commit(){
|
||||
logger.info("commit changes");
|
||||
accountStateDB.commitTrack();
|
||||
contractDetailsDB.commitTrack();
|
||||
}
|
||||
|
||||
public void rollback(){
|
||||
logger.info("rollback changes");
|
||||
accountStateDB.rollbackTrack();
|
||||
contractDetailsDB.rollbackTrack();
|
||||
}
|
||||
|
||||
public AccountState createAccount(byte[] addr){
|
||||
|
||||
// 1. Save AccountState
|
||||
AccountState state = new AccountState();
|
||||
accountStateDB.update(addr, state.getEncoded());
|
||||
|
||||
// 2. Save ContractDetails
|
||||
NewContractDetails details = new NewContractDetails();
|
||||
contractDetailsDB.put(addr, details.getEncoded());
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
public AccountState getAccountState(byte[] addr){
|
||||
|
||||
byte[] accountStateRLP = accountStateDB.get(addr);
|
||||
if (accountStateRLP.length == 0){
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("No account: [ {} ]", Hex.toHexString(addr));
|
||||
return null;
|
||||
}
|
||||
|
||||
AccountState state = new AccountState(accountStateRLP);
|
||||
return state;
|
||||
}
|
||||
|
||||
public NewContractDetails getContractDetails(byte[] addr){
|
||||
|
||||
byte[] accountDetailsRLP = contractDetailsDB.get(addr);
|
||||
|
||||
if (accountDetailsRLP == null){
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("No account: [ {} ]", Hex.toHexString(addr));
|
||||
return null;
|
||||
}
|
||||
|
||||
NewContractDetails details = new NewContractDetails(accountDetailsRLP);
|
||||
return details;
|
||||
}
|
||||
|
||||
public BigInteger addBalance(byte[] address, BigInteger value){
|
||||
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return BigInteger.ZERO;
|
||||
|
||||
BigInteger newBalance = state.addToBalance(value);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Changing balance: account: [ {} ] new balance: [ {} ]",
|
||||
Hex.toHexString(address), newBalance.longValue());
|
||||
|
||||
accountStateDB.update(address, state.getEncoded());
|
||||
|
||||
return newBalance;
|
||||
}
|
||||
|
||||
public BigInteger getBalance(byte[] address){
|
||||
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return BigInteger.ZERO;
|
||||
|
||||
return state.getBalance();
|
||||
}
|
||||
|
||||
public BigInteger getNonce(byte[] address){
|
||||
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return BigInteger.ZERO;
|
||||
|
||||
return state.getNonce();
|
||||
}
|
||||
|
||||
|
||||
public BigInteger increaseNonce(byte[] address){
|
||||
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return BigInteger.ZERO;
|
||||
|
||||
state.incrementNonce();
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Incerement nonce: account: [ {} ] new nonce: [ {} ]",
|
||||
Hex.toHexString(address), state.getNonce().longValue());
|
||||
|
||||
accountStateDB.update(address, state.getEncoded());
|
||||
return state.getNonce();
|
||||
}
|
||||
|
||||
public void addStorageRow(byte[] address, DataWord key, DataWord value){
|
||||
|
||||
if (address == null || key == null) return;
|
||||
AccountState state = getAccountState(address);
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
|
||||
if (state == null || details == null) return;
|
||||
details.put(key, value);
|
||||
|
||||
byte[] storageHash = details.getStorageHash();
|
||||
state.setStateRoot(storageHash);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Storage key/value saved: account: [ {} ]\n key: [ {} ] value: [ {} ]\n new storageHash: [ {} ]",
|
||||
Hex.toHexString(address),
|
||||
Hex.toHexString(key.getNoLeadZeroesData()),
|
||||
Hex.toHexString(value.getNoLeadZeroesData()),
|
||||
Hex.toHexString(storageHash));
|
||||
|
||||
accountStateDB.update(address, state.getEncoded());
|
||||
contractDetailsDB.put(address, details.getEncoded());
|
||||
}
|
||||
|
||||
public DataWord getStorageValue(byte[] address, DataWord key){
|
||||
|
||||
if (key == null) return null;
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return null;
|
||||
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
DataWord value = details.get(key);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public byte[] getCode(byte[] address){
|
||||
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
if (details == null) return null;
|
||||
|
||||
return details.getCode();
|
||||
}
|
||||
|
||||
public void saveCode(byte[] address, byte[] code){
|
||||
|
||||
if (code == null) return;
|
||||
|
||||
AccountState state = getAccountState(address);
|
||||
if (state == null) return;
|
||||
|
||||
NewContractDetails details = getContractDetails(address);
|
||||
details.setCode(code);
|
||||
|
||||
byte[] codeHash = HashUtil.sha3(code);
|
||||
state.setCodeHash(codeHash);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Program code saved: account: [ {} ] codeHash: [ {} ] \n code: [ {} ]",
|
||||
Hex.toHexString(address),
|
||||
Hex.toHexString(codeHash),
|
||||
Hex.toHexString(code));
|
||||
|
||||
accountStateDB.update(address, state.getEncoded());
|
||||
contractDetailsDB.put(address, details.getEncoded());
|
||||
}
|
||||
|
||||
|
||||
public void close(){
|
||||
|
||||
if (this.stateDB != null)
|
||||
stateDB.close();
|
||||
|
||||
if (this.detailsDB != null)
|
||||
detailsDB.close();
|
||||
}
|
||||
}
|
|
@ -49,6 +49,9 @@ public class Cache {
|
|||
if (this.nodes.get(keyObj) != null) {
|
||||
return this.nodes.get(keyObj).getValue();
|
||||
}
|
||||
|
||||
if (db != null) return new Value(null);
|
||||
|
||||
// Get the key of the database instead and cache it
|
||||
byte[] data = this.db.get(key);
|
||||
Value value = new Value(data);
|
||||
|
@ -61,10 +64,15 @@ public class Cache {
|
|||
public void delete(byte[] key) {
|
||||
ByteArrayWrapper keyObj = new ByteArrayWrapper(key);
|
||||
this.nodes.remove(keyObj);
|
||||
|
||||
if (db == null) return;
|
||||
this.db.delete(key);
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
|
||||
if (db == null) return;
|
||||
|
||||
// Don't try to commit if it isn't dirty
|
||||
if (!this.isDirty) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,353 @@
|
|||
package org.ethereum.db;
|
||||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.ContractDetails;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.junit.*;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 23/06/2014 23:52
|
||||
*/
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class RepositoryTest {
|
||||
|
||||
|
||||
@Test // create account,
|
||||
// get account
|
||||
public void test1(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
Repository repository = new Repository();
|
||||
AccountState createdState = repository.createAccount(Hex.decode(addr));
|
||||
|
||||
AccountState fetchedState =
|
||||
repository.getAccountState(Hex.decode(addr));
|
||||
|
||||
assertEquals(createdState.getEncoded(), fetchedState.getEncoded());
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // increase nonce
|
||||
public void test2(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
Repository repository = new Repository();
|
||||
BigInteger nonce0 = repository.getNonce(Hex.decode(addr));
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
BigInteger nonce1 = repository.getNonce(Hex.decode(addr));
|
||||
|
||||
repository.increaseNonce(Hex.decode(addr));
|
||||
BigInteger nonce2 = repository.getNonce(Hex.decode(addr));
|
||||
|
||||
assertEquals(0, nonce0.intValue());
|
||||
assertEquals(0, nonce1.intValue());
|
||||
assertEquals(1, nonce2.intValue());
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test // increase nonce
|
||||
public void test3(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
Repository repository = new Repository();
|
||||
BigInteger nonce0 = repository.getNonce(Hex.decode(addr));
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
BigInteger nonce1 = repository.getNonce(Hex.decode(addr));
|
||||
|
||||
repository.increaseNonce(Hex.decode(addr));
|
||||
repository.increaseNonce(Hex.decode(addr));
|
||||
repository.increaseNonce(Hex.decode(addr));
|
||||
BigInteger nonce2 = repository.getNonce(Hex.decode(addr));
|
||||
|
||||
assertEquals(0, nonce0.intValue());
|
||||
assertEquals(0, nonce1.intValue());
|
||||
assertEquals(3, nonce2.intValue());
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // change balance
|
||||
public void test4(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
Repository repository = new Repository();
|
||||
BigInteger balance0 = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
BigInteger balance1 = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
repository.addBalance(Hex.decode(addr), BigInteger.valueOf(300));
|
||||
BigInteger balance2 = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
assertEquals(0, balance0.intValue());
|
||||
assertEquals(0, balance1.intValue());
|
||||
assertEquals(300, balance2.intValue());
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // change balance
|
||||
public void test5(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
Repository repository = new Repository();
|
||||
BigInteger balance0 = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
BigInteger balance1 = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
repository.addBalance(Hex.decode(addr), BigInteger.valueOf(300));
|
||||
BigInteger balance2 = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
repository.addBalance(Hex.decode(addr), BigInteger.valueOf(-150));
|
||||
BigInteger balance3 = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
assertEquals(0, balance0.intValue());
|
||||
assertEquals(0, balance1.intValue());
|
||||
assertEquals(300, balance2.intValue());
|
||||
assertEquals(150, balance3.intValue());
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // get/set code
|
||||
public void test6() {
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
Repository repository = new Repository();
|
||||
byte[] code = repository.getCode(Hex.decode(addr));
|
||||
|
||||
assertTrue(code == null);
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test // get/set code
|
||||
public void test7() {
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
String codeString = "7f60c860005461012c602054000000000000000000000000000000000000000000600060206000f200";
|
||||
String codeHash = "8f0d7fc8cc6fdd688fa58ae9256310069f5659ed2a8a3af994d80350fbf1e798";
|
||||
|
||||
Repository repository = new Repository();
|
||||
byte[] code0 = repository.getCode(Hex.decode(addr));
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
repository.saveCode(Hex.decode(addr), Hex.decode(codeString));
|
||||
byte[] code1 = repository.getCode(Hex.decode(addr));
|
||||
AccountState accountState = repository.getAccountState(Hex.decode(addr));
|
||||
|
||||
assertTrue(code0 == null);
|
||||
assertEquals(codeString, Hex.toHexString(code1));
|
||||
assertEquals(codeHash, Hex.toHexString(accountState.getCodeHash()));
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // get/set code
|
||||
public void test8() {
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
String codeHash = "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470";
|
||||
|
||||
Repository repository = new Repository();
|
||||
byte[] code0 = repository.getCode(Hex.decode(addr));
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
repository.saveCode(Hex.decode(addr), null);
|
||||
byte[] code1 = repository.getCode(Hex.decode(addr));
|
||||
AccountState accountState = repository.getAccountState(Hex.decode(addr));
|
||||
|
||||
assertTrue(code0 == null);
|
||||
assertNull(code1);
|
||||
assertEquals(codeHash, Hex.toHexString(accountState.getCodeHash()));
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // storage set/get
|
||||
public void test9(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
byte[] keyBytes = Hex.decode("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||
DataWord key = new DataWord(keyBytes);
|
||||
|
||||
Repository repository = new Repository();
|
||||
DataWord value = repository.getStorageValue(Hex.decode(addr), key);
|
||||
|
||||
assertNull(value);
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test // storage set/get
|
||||
public void test10(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
Repository repository = new Repository();
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
|
||||
byte[] keyBytes = Hex.decode("cd2a3d9f938e13cd947ec05abc7fe734df8dd826");
|
||||
DataWord key = new DataWord(keyBytes);
|
||||
|
||||
byte[] valueBytes = Hex.decode("0F4240");
|
||||
DataWord value = new DataWord(valueBytes);
|
||||
|
||||
repository.addStorageRow(Hex.decode(addr), key, value);
|
||||
|
||||
DataWord fetchedValue = repository.getStorageValue(Hex.decode(addr), key);
|
||||
|
||||
assertEquals(value, fetchedValue);
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
@Test // storage set/get
|
||||
public void test11(){
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
String expectedStorageHash = "365ed874ad42c2b4af335212465291e03dcd1f0c5b600f40f048ed238ad61fd3";
|
||||
|
||||
Repository repository = new Repository();
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
|
||||
byte[] keyBytes = Hex.decode("03E8");
|
||||
DataWord key1 = new DataWord(keyBytes);
|
||||
|
||||
keyBytes = Hex.decode("03E9");
|
||||
DataWord key2 = new DataWord(keyBytes);
|
||||
|
||||
keyBytes = Hex.decode("03F0");
|
||||
DataWord key3 = new DataWord(keyBytes);
|
||||
|
||||
|
||||
byte[] valueBytes = Hex.decode("0F4240");
|
||||
DataWord value1 = new DataWord(valueBytes);
|
||||
|
||||
valueBytes = Hex.decode("0F4241");
|
||||
DataWord value2 = new DataWord(valueBytes);
|
||||
|
||||
valueBytes = Hex.decode("0F4242");
|
||||
DataWord value3 = new DataWord(valueBytes);
|
||||
|
||||
repository.addStorageRow(Hex.decode(addr), key1, value1);
|
||||
repository.addStorageRow(Hex.decode(addr), key2, value2);
|
||||
repository.addStorageRow(Hex.decode(addr), key3, value3);
|
||||
|
||||
DataWord fetchedValue1 = repository.getStorageValue(Hex.decode(addr), key1);
|
||||
DataWord fetchedValue2 = repository.getStorageValue(Hex.decode(addr), key2);
|
||||
DataWord fetchedValue3 = repository.getStorageValue(Hex.decode(addr), key3);
|
||||
|
||||
AccountState accountState = repository.getAccountState(Hex.decode(addr));
|
||||
String stateRoot = Hex.toHexString(accountState.getStateRoot());
|
||||
|
||||
assertEquals(value1, fetchedValue1);
|
||||
assertEquals(value2, fetchedValue2);
|
||||
assertEquals(value3, fetchedValue3);
|
||||
assertEquals(expectedStorageHash, stateRoot);
|
||||
|
||||
repository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // commit/rollback
|
||||
public void test12() {
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
String expectedStorageHash = "365ed874ad42c2b4af335212465291e03dcd1f0c5b600f40f048ed238ad61fd3";
|
||||
long expectedBalance = 333;
|
||||
|
||||
Repository origRepository = new Repository();
|
||||
Repository repository = origRepository.getTrack();
|
||||
repository.startTracking();
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
repository.addBalance(Hex.decode(addr), BigInteger.valueOf(expectedBalance));
|
||||
|
||||
repository.commit();
|
||||
|
||||
BigInteger balance = repository.getBalance(Hex.decode(addr));
|
||||
|
||||
assertEquals(expectedBalance, balance.longValue());
|
||||
|
||||
origRepository.close();
|
||||
}
|
||||
|
||||
@Test // commit/rollback
|
||||
public void test13() {
|
||||
|
||||
String addr = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
String expectedStorageHash = "365ed874ad42c2b4af335212465291e03dcd1f0c5b600f40f048ed238ad61fd3";
|
||||
long expectedBalance_1 = 55500;
|
||||
long expectedBalance_2 = 0;
|
||||
|
||||
Repository origRepository = new Repository();
|
||||
Repository repository = origRepository.getTrack();
|
||||
repository.startTracking();
|
||||
|
||||
repository.createAccount(Hex.decode(addr));
|
||||
repository.addBalance(Hex.decode(addr), BigInteger.valueOf(55500));
|
||||
|
||||
BigInteger balance = repository.getBalance(Hex.decode(addr));
|
||||
assertEquals(expectedBalance_1, balance.longValue());
|
||||
repository.rollback();
|
||||
|
||||
balance = repository.getBalance(Hex.decode(addr));
|
||||
assertEquals(expectedBalance_2, balance.longValue());
|
||||
|
||||
origRepository.close();
|
||||
}
|
||||
|
||||
|
||||
@Test // commit/rollback
|
||||
public void test14() {
|
||||
|
||||
String addr_1 = "cd2a3d9f938e13cd947ec05abc7fe734df8dd826";
|
||||
String addr_2 = "77045e71a7a2c50903d88e564cd72fab11e82051";
|
||||
String codeString = "7f60c860005461012c602054000000000000000000000000000000000000000000600060206000f200";
|
||||
|
||||
long expectedBalance = 55500;
|
||||
|
||||
Repository origRepository = new Repository();
|
||||
Repository repository = origRepository.getTrack();
|
||||
|
||||
repository.createAccount(Hex.decode(addr_1));
|
||||
repository.addBalance(Hex.decode(addr_1), BigInteger.valueOf(expectedBalance));
|
||||
repository.startTracking();
|
||||
|
||||
repository.createAccount(Hex.decode(addr_2));
|
||||
repository.saveCode(Hex.decode(addr_2), Hex.decode(codeString));
|
||||
repository.addStorageRow(Hex.decode(addr_2), new DataWord(101), new DataWord(1000001));
|
||||
repository.addStorageRow(Hex.decode(addr_2), new DataWord(102), new DataWord(1000002));
|
||||
repository.addStorageRow(Hex.decode(addr_2), new DataWord(103), new DataWord(1000003));
|
||||
repository.rollback();
|
||||
|
||||
BigInteger balance = repository.getBalance(Hex.decode(addr_1));
|
||||
assertEquals(expectedBalance, balance.longValue());
|
||||
|
||||
DataWord value = repository.getStorageValue(Hex.decode(addr_2), new DataWord(101));
|
||||
assertNull(value);
|
||||
|
||||
origRepository.close();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue