adapting for poc-7 final (eth:47) :

+ Repository refactoring
This commit is contained in:
romanman 2014-12-04 14:35:18 +01:00
parent 1907c0691f
commit 254c51704a
14 changed files with 116 additions and 1479 deletions

View File

@ -130,8 +130,9 @@ public class BlockchainImpl implements Blockchain {
recordBlock(block); recordBlock(block);
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Try connect block: {}", logger.debug("Try connect block hash: {}, number: {}",
Hex.toHexString(block.getEncoded())); Hex.toHexString(block.getHash()).substring(0, 6),
block.getNumber());
if (blockStore.getBlockByHash(block.getHash()) != null){ if (blockStore.getBlockByHash(block.getHash()) != null){
// retry of well known block // retry of well known block
@ -212,6 +213,9 @@ public class BlockchainImpl implements Blockchain {
track.commit(); track.commit();
repository.flush(); // saving to the disc repository.flush(); // saving to the disc
stateLogger.info("applied reward for block: [{}] \n state: [{}]",
block.getNumber(),
Hex.toHexString(repository.getRoot()));
// Remove all wallet transactions as they already approved by the net // Remove all wallet transactions as they already approved by the net
worldManager.getWallet().removeTransactions(block.getTransactionsList()); worldManager.getWallet().removeTransactions(block.getTransactionsList());
@ -329,7 +333,7 @@ public class BlockchainImpl implements Blockchain {
track.commit(); track.commit();
receipt.setPostTxState(repository.getRoot()); receipt.setPostTxState(repository.getRoot());
stateLogger.info("executed block: [{}] tx: [{}] \n state: [{}]", block.getNumber(), i, stateLogger.info("block: [{}] executed tx: [{}] \n state: [{}]", block.getNumber(), i,
Hex.toHexString(repository.getRoot())); Hex.toHexString(repository.getRoot()));
if(block.getNumber() >= CONFIG.traceStartBlock()) if(block.getNumber() >= CONFIG.traceStartBlock())
@ -579,8 +583,7 @@ public class BlockchainImpl implements Blockchain {
BigInteger gasPrice, Repository repository, byte[] senderAddress, BigInteger gasPrice, Repository repository, byte[] senderAddress,
byte[] contractAddress, byte[] coinbase, boolean initResults) { byte[] contractAddress, byte[] coinbase, boolean initResults) {
if (result.getException() != null if (result.getException() != null) {
&& result.getException() instanceof Program.OutOfGasException) {
stateLogger.debug("contract run halted by OutOfGas: contract={}", stateLogger.debug("contract run halted by OutOfGas: contract={}",
Hex.toHexString(contractAddress)); Hex.toHexString(contractAddress));
throw result.getException(); throw result.getException();

View File

@ -24,7 +24,7 @@ public class ContractDetails {
private byte[] code = ByteUtil.EMPTY_BYTE_ARRAY; private byte[] code = ByteUtil.EMPTY_BYTE_ARRAY;
private boolean dirty = true; private boolean dirty = false;
private boolean deleted = false; private boolean deleted = false;
private Trie storageTrie = new TrieImpl(null); private Trie storageTrie = new TrieImpl(null);

View File

@ -28,6 +28,7 @@ import java.util.List;
import static org.ethereum.config.SystemProperties.CONFIG; import static org.ethereum.config.SystemProperties.CONFIG;
import static org.ethereum.crypto.SHA3Helper.*; import static org.ethereum.crypto.SHA3Helper.*;
import static org.ethereum.util.ByteUtil.wrap;
/** /**
* www.etherj.com * www.etherj.com
@ -88,40 +89,39 @@ public class RepositoryImpl implements Repository {
public void updateBatch(HashMap<ByteArrayWrapper, AccountState> stateCache, public void updateBatch(HashMap<ByteArrayWrapper, AccountState> stateCache,
HashMap<ByteArrayWrapper, ContractDetails> detailsCache) { HashMap<ByteArrayWrapper, ContractDetails> detailsCache) {
for (ByteArrayWrapper hash : detailsCache.keySet()) { for (ByteArrayWrapper hash : stateCache.keySet()) {
ContractDetails contractDetails = detailsCache.get(hash);
if (contractDetails.isDeleted())
detailsDB.delete(hash.getData());
else{
if (contractDetails.isDirty())
detailsDB.put(hash.getData(), contractDetails.getEncoded());
}
if (contractDetails.isDirty() || contractDetails.isDeleted()){
AccountState accountState = stateCache.get(hash);
accountState.setStateRoot(contractDetails.getStorageHash());
accountState.setCodeHash(sha3(contractDetails.getCode()));
}
contractDetails.setDeleted(false);
contractDetails.setDirty(false);
}
for (ByteArrayWrapper hash : detailsCache.keySet()) {
AccountState accountState = stateCache.get(hash); AccountState accountState = stateCache.get(hash);
ContractDetails contractDetails = detailsCache.get(hash);
if (accountState.isDeleted()) if (accountState.isDeleted()){
worldState.delete(hash.getData()); worldState.delete(hash.getData());
else{ detailsDB.delete(hash.getData());
if (accountState.isDirty()){
logger.debug("delete: [{}]",
Hex.toHexString(hash.getData()));
} else{
if (contractDetails.isDirty()){
detailsDB.put(hash.getData(), contractDetails.getEncoded());
accountState.setStateRoot(contractDetails.getStorageHash());
accountState.setCodeHash(sha3(contractDetails.getCode()));
worldState.update(hash.getData(), accountState.getEncoded());
if (logger.isDebugEnabled()){
logger.debug("update: [{}],nonce: [{}] balance: [{}] \n [{}]",
Hex.toHexString(hash.getData()),
accountState.getNonce(),
accountState.getBalance(),
contractDetails.getStorage());
}
}
if (!contractDetails.isDirty() && accountState.isDirty()){
worldState.update(hash.getData(), accountState.getEncoded()); worldState.update(hash.getData(), accountState.getEncoded());
if (logger.isDebugEnabled()){ if (logger.isDebugEnabled()){
logger.debug("update: [{}],nonce: [{}] balance: [{}]", logger.debug("update: [{}],nonce: [{}] balance: [{}]",
Hex.toHexString(hash.getData()), Hex.toHexString(hash.getData()),
accountState.getNonce(), accountState.getNonce(),
@ -131,8 +131,8 @@ public class RepositoryImpl implements Repository {
} }
} }
accountState.setDeleted(false); detailsCache.remove(hash.getData());
accountState.setDirty(false); stateCache.remove(hash.getData());
} }
} }
@ -404,6 +404,28 @@ public class RepositoryImpl implements Repository {
return accountState; return accountState;
} }
@Override
public void loadAccount(byte[] addr,
HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) {
AccountState account = getAccountState(addr);
ContractDetails details = getContractDetails(addr);
if (account == null)
account = new AccountState();
else
account = account.clone();
if (details == null)
details = new ContractDetails();
else
details = details.clone();
cacheAccounts.put(wrap(addr), account);
cacheDetails.put(wrap(addr), details);
}
@Override @Override
public byte[] getRoot() { public byte[] getRoot() {
return worldState.getRootHash(); return worldState.getRootHash();

View File

@ -56,30 +56,40 @@ public class RepositoryTrack implements Repository {
AccountState accountState = cacheAccounts.get(wrap(addr)); AccountState accountState = cacheAccounts.get(wrap(addr));
if (accountState == null){ if (accountState == null){
accountState = repository.getAccountState(addr); repository.loadAccount(addr, cacheAccounts, cacheDetails);
accountState = cacheAccounts.get(wrap(addr));
if (accountState == null){
accountState = createAccount(addr);
} else {
accountState = accountState.clone();
cacheAccounts.put(wrap(addr), accountState);
ContractDetails contractDetails = repository.getContractDetails(addr);
cacheDetails.put(wrap(addr), contractDetails.clone());
}
} }
return accountState; return accountState;
} }
@Override @Override
public ContractDetails getContractDetails(byte[] addr) { public ContractDetails getContractDetails(byte[] addr) {
getAccountState(addr);
ContractDetails contractDetails = cacheDetails.get(wrap(addr)); ContractDetails contractDetails = cacheDetails.get(wrap(addr));
if (contractDetails == null){
repository.loadAccount(addr, cacheAccounts, cacheDetails);
contractDetails = cacheDetails.get(wrap(addr));
}
return contractDetails; return contractDetails;
} }
@Override
public void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails){
AccountState accountState = this.cacheAccounts.get(wrap(addr));
ContractDetails contractDetails = this.cacheDetails.get(wrap(addr));
if (accountState == null){
repository.loadAccount(addr, cacheAccounts, cacheDetails);
} else {
cacheAccounts.put(wrap(addr), accountState.clone());
cacheDetails.put(wrap(addr), contractDetails.clone());
}
}
@Override @Override
public void delete(byte[] addr) { public void delete(byte[] addr) {

View File

@ -190,4 +190,6 @@ public interface Repository {
public byte[] getRoot(); public byte[] getRoot();
void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails);
} }

View File

@ -49,7 +49,9 @@ public class TestRunner {
Repository repository = new RepositoryImpl(); Repository repository = new RepositoryImpl();
try { try {
System.out.println("\nRunning test case: " + testCase.getName()); System.out.println("\n***");
System.out.println(" Running test case: [" + testCase.getName() + "]") ;
System.out.println("***\n");
List<String> results = new ArrayList<>(); List<String> results = new ArrayList<>();
System.out.println("--------- PRE ---------"); System.out.println("--------- PRE ---------");

View File

@ -42,7 +42,7 @@ import static org.ethereum.net.message.StaticMessages.GET_TRANSACTIONS_MESSAGE;
@Scope("prototype") @Scope("prototype")
public class EthHandler extends SimpleChannelInboundHandler<EthMessage> { public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
public final static byte VERSION = 46; public final static byte VERSION = 47;
public final static byte NETWORK_ID = 0x0; public final static byte NETWORK_ID = 0x0;
private final static Logger logger = LoggerFactory.getLogger("net"); private final static Logger logger = LoggerFactory.getLogger("net");

View File

@ -6,6 +6,8 @@ import org.ethereum.net.MessageQueue;
import org.ethereum.net.eth.EthHandler; import org.ethereum.net.eth.EthHandler;
import org.ethereum.net.p2p.P2pHandler; import org.ethereum.net.p2p.P2pHandler;
import org.ethereum.net.shh.ShhHandler; import org.ethereum.net.shh.ShhHandler;
import org.ethereum.net.wire.MessageDecoder;
import org.ethereum.net.wire.MessageEncoder;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -35,6 +37,14 @@ public class Channel {
@Autowired @Autowired
ShhHandler shhHandler; ShhHandler shhHandler;
@Autowired
MessageDecoder messageDecoder;
@Autowired
MessageEncoder messageEncoder;
public Channel() { public Channel() {
} }
@ -57,6 +67,14 @@ public class Channel {
return shhHandler; return shhHandler;
} }
public MessageDecoder getMessageDecoder() {
return messageDecoder;
}
public MessageEncoder getMessageEncoder() {
return messageEncoder;
}
public void sendTransaction(Transaction tx){ public void sendTransaction(Transaction tx){
ethHandler.sendTransaction(tx); ethHandler.sendTransaction(tx);
} }

View File

@ -46,12 +46,6 @@ public class EthereumChannelInitializer extends ChannelInitializer<NioSocketChan
@Autowired @Autowired
ChannelManager channelManager; ChannelManager channelManager;
@Autowired
MessageDecoder messageDecoder;
@Autowired
MessageEncoder messageEncoder;
@Autowired @Autowired
WorldManager worldManager; WorldManager worldManager;
@ -70,8 +64,8 @@ public class EthereumChannelInitializer extends ChannelInitializer<NioSocketChan
ch.pipeline().addLast("readTimeoutHandler", ch.pipeline().addLast("readTimeoutHandler",
new ReadTimeoutHandler(CONFIG.peerChannelReadTimeout(), TimeUnit.SECONDS)); new ReadTimeoutHandler(CONFIG.peerChannelReadTimeout(), TimeUnit.SECONDS));
ch.pipeline().addLast("out encoder", messageEncoder); ch.pipeline().addLast("out encoder", channel.getMessageEncoder());
ch.pipeline().addLast("in encoder", messageDecoder); ch.pipeline().addLast("in encoder", channel.getMessageDecoder());
ch.pipeline().addLast(Capability.P2P, channel.getP2pHandler()); ch.pipeline().addLast(Capability.P2P, channel.getP2pHandler());
ch.pipeline().addLast(Capability.ETH, channel.getEthHandler()); ch.pipeline().addLast(Capability.ETH, channel.getEthHandler());
ch.pipeline().addLast(Capability.SHH, channel.getShhHandler()); ch.pipeline().addLast(Capability.SHH, channel.getShhHandler());

View File

@ -178,7 +178,7 @@ public class BlockTest {
@Test @Test
public void testScenario5() throws URISyntaxException, IOException { public void testScenario1() throws URISyntaxException, IOException {
BlockchainImpl blockchain = (BlockchainImpl)worldManager.getBlockchain(); BlockchainImpl blockchain = (BlockchainImpl)worldManager.getBlockchain();
@ -199,7 +199,7 @@ public class BlockTest {
logger.info("asserting root state is: {}", Hex.toHexString( root )); logger.info("asserting root state is: {}", Hex.toHexString( root ));
//expected root: dedd258f4cee2d1b45f137a2a74a2052e14a6d7fe1b1184be0a6adcec6a1d1d3 //expected root: fb8be59e6420892916e3967c60adfdf48836af040db0072ca411d7aaf5663804
assertEquals(Hex.toHexString(root), assertEquals(Hex.toHexString(root),
Hex.toHexString(worldManager.getRepository().getRoot())); Hex.toHexString(worldManager.getRepository().getRoot()));
} }

View File

@ -2,9 +2,11 @@ package test.ethereum.db;
import org.ethereum.config.SystemProperties; import org.ethereum.config.SystemProperties;
import org.ethereum.core.Genesis; import org.ethereum.core.Genesis;
import org.ethereum.crypto.HashUtil;
import org.ethereum.facade.Repository; import org.ethereum.facade.Repository;
import org.ethereum.db.RepositoryImpl; import org.ethereum.db.RepositoryImpl;
import org.ethereum.vm.DataWord; import org.ethereum.vm.DataWord;
import org.junit.Assert;
import org.junit.FixMethodOrder; import org.junit.FixMethodOrder;
import org.junit.Test; import org.junit.Test;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;
@ -493,67 +495,26 @@ public class RepositoryTest {
Repository repository = new RepositoryImpl(); Repository repository = new RepositoryImpl();
byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826"); byte[] cow = Hex.decode("CD2A3D9F938E13CD947EC05ABC7FE734DF8DD826");
byte[] horse = Hex.decode("13978AEE95F38490E9769C39B2773ED763D9CD5F");
final BigInteger ELEVEN = BigInteger.TEN.add(BigInteger.ONE);
byte[] cowKey1 = "key-c-1".getBytes(); byte[] cowKey1 = "key-c-1".getBytes();
byte[] cowValue1 = "val-c-1".getBytes(); byte[] cowValue1 = "val-c-1".getBytes();
byte[] horseKey1 = "key-h-1".getBytes();
byte[] horseValue1 = "val-h-1".getBytes();
byte[] cowKey2 = "key-c-2".getBytes();
byte[] cowValue2 = "val-c-2".getBytes();
byte[] horseKey2 = "key-h-2".getBytes();
byte[] horseValue2 = "val-h-2".getBytes();
// changes level_1 // changes level_1
Repository track1 = repository.startTracking(); Repository track1 = repository.startTracking();
track1.addStorageRow(cow, new DataWord(cowKey1), new DataWord(cowValue1));
track1.addStorageRow(horse, new DataWord(horseKey1), new DataWord(horseValue1));
assertEquals(new DataWord(cowValue1), track1.getStorageValue(cow, new DataWord(cowKey1)));
assertEquals(new DataWord(horseValue1), track1.getStorageValue(horse, new DataWord(horseKey1)));
// changes level_2 // changes level_2
Repository track2 = track1.startTracking(); Repository track2 = track1.startTracking();
track2.addStorageRow(cow, new DataWord(cowKey2), new DataWord(cowValue2)); track2.addStorageRow(cow, new DataWord(cowKey1), new DataWord(cowValue1));
track2.addStorageRow(horse, new DataWord(horseKey2), new DataWord(horseValue2));
assertEquals(new DataWord(cowValue1), track2.getStorageValue(cow, new DataWord(cowKey1))); assertEquals(new DataWord(cowValue1), track2.getStorageValue(cow, new DataWord(cowKey1)));
assertEquals(new DataWord(horseValue1), track2.getStorageValue(horse, new DataWord(horseKey1)));
assertEquals(new DataWord(cowValue2), track2.getStorageValue(cow, new DataWord(cowKey2)));
assertEquals(new DataWord(horseValue2), track2.getStorageValue(horse, new DataWord(horseKey2)));
track2.rollback(); track2.rollback();
// leaving level_2 // leaving level_2
assertEquals(new DataWord(cowValue1), track1.getStorageValue(cow, new DataWord(cowKey1)));
assertEquals(new DataWord(horseValue1), track1.getStorageValue(horse, new DataWord(horseKey1)));
assertNull(track1.getStorageValue(cow, new DataWord(cowKey2)));
assertNull(track1.getStorageValue(horse, new DataWord(horseKey2)));
track1.commit(); track1.commit();
// leaving level_1 // leaving level_1
assertEquals(new DataWord(cowValue1), repository.getStorageValue(cow, new DataWord(cowKey1))); Assert.assertEquals( Hex.toHexString(HashUtil.EMPTY_TRIE_HASH), Hex.toHexString(repository.getRoot()) );
assertEquals(new DataWord(horseValue1), repository.getStorageValue(horse, new DataWord(horseKey1)));
assertNull(repository.getStorageValue(cow, new DataWord(cowKey2)));
assertNull(repository.getStorageValue(horse, new DataWord(horseKey2)));
repository.close(); repository.close();
} }
@Test
public void test18(){
}
} }

View File

@ -1,4 +0,0 @@
f90139f90134a0955f36d073ccb026b78ab3424c15cf966a7563aa270413859f78702b9e8e22cba01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347949d6327e4f16d48a3e4b658503d9e3256293fce75a045c8c6675b11d66a33e351d2f104830727c909b58061cf992e85d622e33962e5a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b840000000000000000000000000000080000000000000100000000000000000400000000000000000000000000000000000000000000000000000000000000000008301ff80018609184e72a000830f3e6f80845466342180a0b8605c26e6d37aac4986bd952f36b6f595e96d76fec99eee832af740e454f42ac0c0
f90139f90134a0dc24d5c43ad451400404f9255b7f63bdceeb11310a2b9ece302626cda9b41ff7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347949d6327e4f16d48a3e4b658503d9e3256293fce75a05c2fcc83b43e09eee6801174a2db881187fbbdaf51e201350ec5009f8231e389a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b840000000000000000000000000000080000000000000100000000000000000400000000000000000000000000000000000000000000000000000000000000000008301ffff028609184e72a000830f3a9f80845466342180a090649c06424d4ba8462bcb50b4dcd8507931366e8a5f8cd61019ae590872523bc0c0
f9020af90136a007bc19da9a5ecc987f579f40d1c450bd1d9938983929dce31d0a0734f76798a5a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347949d6327e4f16d48a3e4b658503d9e3256293fce75a013a5e615365c86438d98df5a2ca5bf1173ab4ea33be808fde7b94e47e9534549a00ddba1aad325f4f6d24e0b50ff6ceb3282650ccedc7afacbaa1256e18e014a55a072170d776433bd79dbbb1793f3cb1105ac369da0b142103639df7696e9718016b840000000000000000000000000000080000000000000100000000000000000400000000000000000000000000000000000000000000000000000000000000000008301ff80038609184e72a000830f36d08203e8845466342a80a086862224f20522063b12624e1c1158fc936bd549ca632e780d08471806bed945f8cef865808609184e72a0008203e894885f93eed577f2fc341ebb9a5c9b2ce4465d96c40c801ca01377aa9363574f78d328844287690b4ba7b96dbc9d2a12c67fc60c821093b3a3a06385f6507e8314e45c6b79536ffd164bc8f87d24c63a832c41ce444492101887f865018609184e72a0008203e894885f93eed577f2fc341ebb9a5c9b2ce4465d96c40c801ca062f64877aa71aa94bdddfa9c12be8aab35278f8856e1940aa2a55caf431152fea0101275c02e8b76c28f6cf90ed3a2dde0160eaba021a00cbfd02d1496b7d274fbc0
f90272f90136a0317604546eb502cf91b3d142301de66d46385fa3e89d6994bf8ed04e32a7ae55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347949d6327e4f16d48a3e4b658503d9e3256293fce75a08bbff862199ccf5411c9505598eeba3d76b51e4d391ac1189903b0fcbdd3733ba0ae62cdf41908bd8593c9065b34653bdbebeeb5bd372e4f82b8afb9178dd0c843a0ee823bbd7016023e00804ae726cfe8c611e7ceeeb64644a96aaa77e4c868f3c4b840000000000000000000000000000080000000000000100000000000000000400000000000000000000000000000000000000000000000000000000000000000008301ff01048609184e72a000830f33038205dc845466346080a0a5f179dd5b8af29bd95c139af1a57815548669b6cd470485bea03088612c4c1cf90135f865028609184e72a0008203e894885f93eed577f2fc341ebb9a5c9b2ce4465d96c40c801ba02891f3a500f4639906fdebb99cfad59c8f3fda9ed9d4ac13c40f01bedf38cfeea03ea2c3ce1b5346fe803c2e00309cc324979da38fac6893f182fc2a70d6d354d0f865038609184e72a0008203e894885f93eed577f2fc341ebb9a5c9b2ce4465d96c40c801ba0e0b83b97cad39259c8d9c73125036b794025bf129b9718f16e2c95892c84f3b3a02cf5bfd58c73043eb6b8d23d0a8d762e5a33e68d964a0b078efb36c7fbb78ebff865048609184e72a0008203e894885f93eed577f2fc341ebb9a5c9b2ce4465d96c40c801ca0c2586f90246d16d1d19c5b2ecc73c64f7d2028367122ec4c4d38e37850bd22aca045021f7342e69f07e4d6f28ad0075105596e6f4b38e3c1d3905d7d16162fc9f8c0

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long