Reduced genesis block load time.

This commit is contained in:
Adrian Tiberius 2015-11-09 05:26:28 +02:00
parent 502ec0b9b1
commit cde1454b85
6 changed files with 164 additions and 9 deletions

View File

@ -231,13 +231,35 @@ public class EthereumRemoteService extends EthereumService {
if (ethereum != null) {
System.out.println("Loading genesis");
broadcastEvent(EventFlag.EVENT_TRACE, new TraceEventData("Loading genesis block. This may take a few minutes..."));
/*
String genesisFile = CONFIG.genesisInfo();
long startTime = System.nanoTime();
try {
InputStream is = getApplication().getAssets().open("genesis/" + genesisFile);
Genesis.androidGetInstance(is);
InputStream genesis = getApplication().getAssets().open("genesis/" + genesisFile);
Genesis.androidGetInstance(genesis);
genesis.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
long endTime = System.nanoTime();
System.out.println((endTime - startTime)/1000000);
Genesis.reset();
*/
long startTime1 = System.nanoTime();
try {
InputStream genesis = getApplication().getAssets().open("genesis/genesis.bin");
InputStream premine = getApplication().getAssets().open("genesis/premine.bin");
InputStream roothash = getApplication().getAssets().open("genesis/roothash.bin");
Genesis.binaryGetInstance(genesis, premine, roothash);
genesis.close();
premine.close();
roothash.close();
} catch (Exception e) {
System.out.println(e.getMessage());
}
long endTime1 = System.nanoTime();
System.out.println((endTime1 - startTime1)/1000000);
System.out.println("Genesis loaded");
if (privateKeys == null || privateKeys.size() == 0) {
privateKeys = new ArrayList<>();

View File

@ -5,11 +5,12 @@ import org.ethereum.util.RLPList;
import org.spongycastle.util.encoders.Hex;
import java.io.Serializable;
import java.math.BigInteger;
import static org.ethereum.crypto.HashUtil.*;
public class AccountState {
public class AccountState implements Serializable {
private byte[] rlpEncoded;

View File

@ -9,7 +9,13 @@ import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.spongycastle.util.encoders.Hex;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
@ -35,7 +41,7 @@ import static org.ethereum.util.ByteUtil.wrap;
* <p>
* See Yellow Paper: http://www.gavwood.com/Paper.pdf (Appendix I. Genesis Block)
*/
public class Genesis extends Block {
public class Genesis extends Block implements Serializable {
private Map<ByteArrayWrapper, AccountState> premine = new HashMap<>();
@ -45,6 +51,10 @@ public class Genesis extends Block {
private static Block instance;
public Genesis(byte[] rlpEncoded) {
super(rlpEncoded);
}
public Genesis(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] logsBloom,
byte[] difficulty, long number, long gasLimit,
long gasUsed, long timestamp,
@ -68,6 +78,17 @@ public class Genesis extends Block {
return instance;
}
public static void reset() {
instance = null;
}
public static Block binaryGetInstance(InputStream genesis, InputStream premine, InputStream roothash) {
if (instance == null) {
instance = GenesisLoader.loadBinaryGenesis(genesis, premine, roothash);
}
return instance;
}
public Map<ByteArrayWrapper, AccountState> getPremine() {
return premine;
}
@ -75,4 +96,17 @@ public class Genesis extends Block {
public void setPremine(Map<ByteArrayWrapper, AccountState> premine) {
this.premine = premine;
}
public static byte[] serialize(Object obj) throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(obj);
return b.toByteArray();
}
public static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ByteArrayInputStream b = new ByteArrayInputStream(bytes);
ObjectInputStream o = new ObjectInputStream(b);
return o.readObject();
}
}

View File

@ -4,15 +4,22 @@ import com.google.common.io.ByteStreams;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.JavaType;
import org.ethereum.core.AccountState;
import org.ethereum.core.Block;
import org.ethereum.core.Genesis;
import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.jsontestsuite.Utils;
import org.ethereum.trie.SecureTrie;
import org.ethereum.trie.Trie;
import org.ethereum.util.ByteUtil;
import org.ethereum.vm.program.Program;
import org.spongycastle.util.encoders.Hex;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
@ -48,6 +55,97 @@ public class GenesisLoader {
byte[] rootHash = generateRootHash(premine);
genesis.setStateRoot(rootHash);
return genesis;
} catch (Throwable e) {
System.err.print(e.getMessage());
System.err.println("Genesis block configuration is corrupted or not found ./resources/genesis/...");
System.exit(-1);
}
System.err.println("Genesis block configuration is corrupted or not found ./resources/genesis/...");
System.exit(-1);
return null;
}
public static void exportGenesis(Genesis genesis) {
try {
byte[] data = genesis.getEncoded();
FileOutputStream fos = new FileOutputStream("genesis.bin");
fos.write(data, 0, data.length);
fos.flush();
fos.close();
ByteArrayOutputStream b = new ByteArrayOutputStream();
ObjectOutputStream o = new ObjectOutputStream(b);
o.writeObject(genesis.getPremine());
byte[] data1 = b.toByteArray();
FileOutputStream fos1 = new FileOutputStream("premine.bin");
fos1.write(data1, 0, data1.length);
fos1.flush();
fos1.close();
FileOutputStream fos2 = new FileOutputStream("roothash.bin");
fos2.write(genesis.getStateRoot(), 0, genesis.getStateRoot().length);
fos2.flush();
fos2.close();
} catch (Exception e) {
}
}
public static Genesis loadBinaryGenesis(InputStream genesisStream, InputStream premineStream, InputStream roothashStream) {
try {
byte[] data = ByteStreams.toByteArray(genesisStream);
Genesis genesis = new Genesis(data);
data = ByteStreams.toByteArray(premineStream);
Map<ByteArrayWrapper, AccountState> premine = (Map<ByteArrayWrapper, AccountState>)Genesis.deserialize(data);
genesis.setPremine(premine);
data = ByteStreams.toByteArray(roothashStream);
genesis.setStateRoot(data);
return genesis;
} catch (Throwable e) {
System.err.print(e.getMessage());
System.err.println("Genesis block configuration is corrupted or not found ./resources/genesis/...");
System.exit(-1);
}
System.err.println("Genesis block configuration is corrupted or not found ./resources/genesis/...");
System.exit(-1);
return null;
}
public static Genesis loadBinaryGenesis() {
try {
File inputFile = new File("genesis.bin");
byte[] data = new byte[(int)inputFile.length()];
FileInputStream fis = new FileInputStream(inputFile);
fis.read(data, 0, data.length);
fis.close();
Genesis genesis = new Genesis(data);
inputFile = new File("premine.bin");
data = new byte[(int)inputFile.length()];
fis = new FileInputStream(inputFile);
fis.read(data, 0, data.length);
fis.close();
Map<ByteArrayWrapper, AccountState> premine = (Map<ByteArrayWrapper, AccountState>)Genesis.deserialize(data);
genesis.setPremine(premine);
inputFile = new File("roothash.bin");
data = new byte[(int)inputFile.length()];
fis = new FileInputStream(inputFile);
fis.read(data, 0, data.length);
fis.close();
genesis.setStateRoot(data);
return genesis;
} catch (Throwable e) {

View File

@ -167,6 +167,7 @@ public class WorldManager {
Set<ByteArrayWrapper> keys = genesis.getPremine().keySet();
int size = keys.size();
int index = 0;
long startTime0 = System.nanoTime();
for (ByteArrayWrapper key : keys) {
index++;
if (index % 500 == 0 || index == size) {
@ -175,6 +176,8 @@ public class WorldManager {
repository.createAccount(key.getData());
repository.addBalance(key.getData(), genesis.getPremine().get(key).getBalance());
}
long endTime0 = System.nanoTime();
System.out.println("Import accounts time: " + ((endTime0 - startTime0) / 1000000));
blockStore.saveBlock(Genesis.getInstance(), Genesis.getInstance().getCumulativeDifficulty(), true);
@ -183,7 +186,7 @@ public class WorldManager {
blockStore.flush();
listener.onBlock(Genesis.getInstance(), new ArrayList<TransactionReceipt>());
repository.dumpState(Genesis.getInstance(), 0, 0, null);
repository.flush();
logger.info("Genesis block imported");
} else {

View File

@ -55,8 +55,6 @@ public class Channel {
private final static Logger logger = LoggerFactory.getLogger("net");
ChannelManager channelManager;
private MessageQueue msgQueue;
private P2pHandler p2pHandler;
@ -81,10 +79,9 @@ public class Channel {
private boolean discoveryMode;
@Inject
public Channel(ChannelManager channelManager, MessageQueue msgQueue, P2pHandler p2pHandler
public Channel(MessageQueue msgQueue, P2pHandler p2pHandler
, ShhHandler shhHandler, BzzHandler bzzHandler, MessageCodec messageCodec
, NodeManager nodeManager, EthHandlerFactory ethHandlerFactory) {
this.channelManager = channelManager;
this.msgQueue = msgQueue;
this.p2pHandler = p2pHandler;
this.shhHandler = shhHandler;