Reduced genesis block load time.
This commit is contained in:
parent
502ec0b9b1
commit
cde1454b85
|
@ -231,13 +231,35 @@ public class EthereumRemoteService extends EthereumService {
|
||||||
if (ethereum != null) {
|
if (ethereum != null) {
|
||||||
System.out.println("Loading genesis");
|
System.out.println("Loading genesis");
|
||||||
broadcastEvent(EventFlag.EVENT_TRACE, new TraceEventData("Loading genesis block. This may take a few minutes..."));
|
broadcastEvent(EventFlag.EVENT_TRACE, new TraceEventData("Loading genesis block. This may take a few minutes..."));
|
||||||
|
/*
|
||||||
String genesisFile = CONFIG.genesisInfo();
|
String genesisFile = CONFIG.genesisInfo();
|
||||||
|
long startTime = System.nanoTime();
|
||||||
try {
|
try {
|
||||||
InputStream is = getApplication().getAssets().open("genesis/" + genesisFile);
|
InputStream genesis = getApplication().getAssets().open("genesis/" + genesisFile);
|
||||||
Genesis.androidGetInstance(is);
|
Genesis.androidGetInstance(genesis);
|
||||||
|
genesis.close();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println(e.getMessage());
|
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");
|
System.out.println("Genesis loaded");
|
||||||
if (privateKeys == null || privateKeys.size() == 0) {
|
if (privateKeys == null || privateKeys.size() == 0) {
|
||||||
privateKeys = new ArrayList<>();
|
privateKeys = new ArrayList<>();
|
||||||
|
|
|
@ -5,11 +5,12 @@ import org.ethereum.util.RLPList;
|
||||||
|
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import static org.ethereum.crypto.HashUtil.*;
|
import static org.ethereum.crypto.HashUtil.*;
|
||||||
|
|
||||||
public class AccountState {
|
public class AccountState implements Serializable {
|
||||||
|
|
||||||
private byte[] rlpEncoded;
|
private byte[] rlpEncoded;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,13 @@ import org.json.simple.parser.JSONParser;
|
||||||
import org.json.simple.parser.ParseException;
|
import org.json.simple.parser.ParseException;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
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.InputStream;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -35,7 +41,7 @@ import static org.ethereum.util.ByteUtil.wrap;
|
||||||
* <p>
|
* <p>
|
||||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf (Appendix I. Genesis Block)
|
* 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<>();
|
private Map<ByteArrayWrapper, AccountState> premine = new HashMap<>();
|
||||||
|
|
||||||
|
@ -45,6 +51,10 @@ public class Genesis extends Block {
|
||||||
|
|
||||||
private static Block instance;
|
private static Block instance;
|
||||||
|
|
||||||
|
public Genesis(byte[] rlpEncoded) {
|
||||||
|
super(rlpEncoded);
|
||||||
|
}
|
||||||
|
|
||||||
public Genesis(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] logsBloom,
|
public Genesis(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] logsBloom,
|
||||||
byte[] difficulty, long number, long gasLimit,
|
byte[] difficulty, long number, long gasLimit,
|
||||||
long gasUsed, long timestamp,
|
long gasUsed, long timestamp,
|
||||||
|
@ -68,6 +78,17 @@ public class Genesis extends Block {
|
||||||
return instance;
|
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() {
|
public Map<ByteArrayWrapper, AccountState> getPremine() {
|
||||||
return premine;
|
return premine;
|
||||||
}
|
}
|
||||||
|
@ -75,4 +96,17 @@ public class Genesis extends Block {
|
||||||
public void setPremine(Map<ByteArrayWrapper, AccountState> premine) {
|
public void setPremine(Map<ByteArrayWrapper, AccountState> premine) {
|
||||||
this.premine = 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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,15 +4,22 @@ import com.google.common.io.ByteStreams;
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
import org.codehaus.jackson.map.ObjectMapper;
|
||||||
import org.codehaus.jackson.type.JavaType;
|
import org.codehaus.jackson.type.JavaType;
|
||||||
import org.ethereum.core.AccountState;
|
import org.ethereum.core.AccountState;
|
||||||
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Genesis;
|
import org.ethereum.core.Genesis;
|
||||||
import org.ethereum.db.ByteArrayWrapper;
|
import org.ethereum.db.ByteArrayWrapper;
|
||||||
import org.ethereum.jsontestsuite.Utils;
|
import org.ethereum.jsontestsuite.Utils;
|
||||||
import org.ethereum.trie.SecureTrie;
|
import org.ethereum.trie.SecureTrie;
|
||||||
import org.ethereum.trie.Trie;
|
import org.ethereum.trie.Trie;
|
||||||
import org.ethereum.util.ByteUtil;
|
import org.ethereum.util.ByteUtil;
|
||||||
|
import org.ethereum.vm.program.Program;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
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.InputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -48,6 +55,97 @@ public class GenesisLoader {
|
||||||
byte[] rootHash = generateRootHash(premine);
|
byte[] rootHash = generateRootHash(premine);
|
||||||
genesis.setStateRoot(rootHash);
|
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;
|
return genesis;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
|
|
@ -167,6 +167,7 @@ public class WorldManager {
|
||||||
Set<ByteArrayWrapper> keys = genesis.getPremine().keySet();
|
Set<ByteArrayWrapper> keys = genesis.getPremine().keySet();
|
||||||
int size = keys.size();
|
int size = keys.size();
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
long startTime0 = System.nanoTime();
|
||||||
for (ByteArrayWrapper key : keys) {
|
for (ByteArrayWrapper key : keys) {
|
||||||
index++;
|
index++;
|
||||||
if (index % 500 == 0 || index == size) {
|
if (index % 500 == 0 || index == size) {
|
||||||
|
@ -175,6 +176,8 @@ public class WorldManager {
|
||||||
repository.createAccount(key.getData());
|
repository.createAccount(key.getData());
|
||||||
repository.addBalance(key.getData(), genesis.getPremine().get(key).getBalance());
|
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);
|
blockStore.saveBlock(Genesis.getInstance(), Genesis.getInstance().getCumulativeDifficulty(), true);
|
||||||
|
|
||||||
|
@ -183,7 +186,7 @@ public class WorldManager {
|
||||||
blockStore.flush();
|
blockStore.flush();
|
||||||
listener.onBlock(Genesis.getInstance(), new ArrayList<TransactionReceipt>());
|
listener.onBlock(Genesis.getInstance(), new ArrayList<TransactionReceipt>());
|
||||||
repository.dumpState(Genesis.getInstance(), 0, 0, null);
|
repository.dumpState(Genesis.getInstance(), 0, 0, null);
|
||||||
|
repository.flush();
|
||||||
|
|
||||||
logger.info("Genesis block imported");
|
logger.info("Genesis block imported");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -55,8 +55,6 @@ public class Channel {
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger("net");
|
private final static Logger logger = LoggerFactory.getLogger("net");
|
||||||
|
|
||||||
ChannelManager channelManager;
|
|
||||||
|
|
||||||
private MessageQueue msgQueue;
|
private MessageQueue msgQueue;
|
||||||
|
|
||||||
private P2pHandler p2pHandler;
|
private P2pHandler p2pHandler;
|
||||||
|
@ -81,10 +79,9 @@ public class Channel {
|
||||||
private boolean discoveryMode;
|
private boolean discoveryMode;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public Channel(ChannelManager channelManager, MessageQueue msgQueue, P2pHandler p2pHandler
|
public Channel(MessageQueue msgQueue, P2pHandler p2pHandler
|
||||||
, ShhHandler shhHandler, BzzHandler bzzHandler, MessageCodec messageCodec
|
, ShhHandler shhHandler, BzzHandler bzzHandler, MessageCodec messageCodec
|
||||||
, NodeManager nodeManager, EthHandlerFactory ethHandlerFactory) {
|
, NodeManager nodeManager, EthHandlerFactory ethHandlerFactory) {
|
||||||
this.channelManager = channelManager;
|
|
||||||
this.msgQueue = msgQueue;
|
this.msgQueue = msgQueue;
|
||||||
this.p2pHandler = p2pHandler;
|
this.p2pHandler = p2pHandler;
|
||||||
this.shhHandler = shhHandler;
|
this.shhHandler = shhHandler;
|
||||||
|
|
Loading…
Reference in New Issue