mirror of
https://github.com/status-im/ethereumj-personal.git
synced 2025-02-26 18:50:28 +00:00
Apply basic formatting
- Do not align assignments on equals signs - Use spaces before opening curly braces - Add spaces between parameters as necessary - Insert newlines between method declarations - Other minor changes This formatting pass is not comprehensive. For the most part, it does not deal with Javadoc formatting, line wrapping, parameter alignment rules or a number of other items that can be addressed later.
This commit is contained in:
parent
e5fcf5b48e
commit
58874cfc7e
@ -1,4 +1,3 @@
|
||||
|
||||
<!--
|
||||
|
||||
Publish from local ${user.home}/.m2/repository
|
||||
@ -25,16 +24,15 @@
|
||||
-->
|
||||
|
||||
|
||||
|
||||
<project name="ethereumj-bintray" default="publish" basedir="." >
|
||||
<project name="ethereumj-bintray" default="publish" basedir=".">
|
||||
|
||||
<tstamp/>
|
||||
|
||||
<property name="artifact.groupId" value="org.ethereum"/>
|
||||
<property name="artifact.id" value="ethereumj"/>
|
||||
<property name="artifact.version" value="0.7.14"/>
|
||||
<property name="artifact.path" value="" />
|
||||
<property name="artifact.snapshot" value="snapshot" />
|
||||
<property name="artifact.path" value=""/>
|
||||
<property name="artifact.snapshot" value="snapshot"/>
|
||||
|
||||
<property name="repo.location" value="${user.home}/.m2/repository"/>
|
||||
<property name="artifact.group.path" value="${artifact.groupId}"/>
|
||||
@ -43,24 +41,24 @@
|
||||
|
||||
<property file="credentials.properties"/>
|
||||
|
||||
<property name="ant.contrib.lib" value="${user.home}/.ant/lib/ant-contrib-1.0b3.jar"/>
|
||||
<property name="ant.missinglink.lib" value="${user.home}/.ant/lib/ml-ant-http-1.1.3.jar"/>
|
||||
<property name="ant.contrib.lib" value="${user.home}/.ant/lib/ant-contrib-1.0b3.jar"/>
|
||||
<property name="ant.missinglink.lib" value="${user.home}/.ant/lib/ml-ant-http-1.1.3.jar"/>
|
||||
|
||||
<property name="bintray.subject" value="ethereum"/>
|
||||
<property name="bintray.repo" value="maven"/>
|
||||
<property name="bintray.package" value="${artifact.groupId}"/>
|
||||
|
||||
<condition property="bintray.version" value="${artifact.version}.${DSTAMP}.${TSTAMP}"
|
||||
else="${artifact.version}">
|
||||
else="${artifact.version}">
|
||||
|
||||
|
||||
<isset property="artifact.snapshot" />
|
||||
<isset property="artifact.snapshot"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<property name="bintray.publish" value="1"/>
|
||||
|
||||
<property name="bintray.file.path" value="${artifact.groupId}/${artifact.id}/${bintray.version}" />
|
||||
<property name="bintray.file.path" value="${artifact.groupId}/${artifact.id}/${bintray.version}"/>
|
||||
|
||||
<property name="encoded.bintray.file.path" value=""/>
|
||||
|
||||
@ -78,8 +76,6 @@
|
||||
</taskdef>
|
||||
|
||||
|
||||
|
||||
|
||||
<target name="definePath">
|
||||
<!--[groupId('.'->'/')]\[artifactId]\[version]-->
|
||||
<!--[artifactId]-[version][suffix]-->
|
||||
@ -93,11 +89,11 @@
|
||||
|
||||
<var name="artifact.full.path" unset="true"/>
|
||||
<property name="artifact.full.path"
|
||||
value="${repo.location}/${artifact.group.path}/${artifact.id}/${artifact.version}/" />
|
||||
value="${repo.location}/${artifact.group.path}/${artifact.id}/${artifact.version}/"/>
|
||||
|
||||
<var name="bintray.file.path" unset="true"/>
|
||||
<property name="bintray.file.path"
|
||||
value="${artifact.group.path}/${artifact.id}/${bintray.version}/${artifact.id}-${bintray.version}" />
|
||||
value="${artifact.group.path}/${artifact.id}/${bintray.version}/${artifact.id}-${bintray.version}"/>
|
||||
|
||||
<echo message="${bintray.file.path}"/>
|
||||
|
||||
@ -116,10 +112,9 @@
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
<target name="publish" depends="dependency, definePath">
|
||||
|
||||
<parallel>
|
||||
<parallel>
|
||||
<antcall target="upload">
|
||||
<param name="artifact.suffix" value=".pom"/>
|
||||
</antcall>
|
||||
@ -132,11 +127,11 @@
|
||||
<param name="artifact.suffix" value="-sources.jar"/>
|
||||
</antcall>
|
||||
|
||||
<antcall target="upload">
|
||||
<param name="artifact.suffix" value="-javadoc.jar"/>
|
||||
</antcall>
|
||||
<antcall target="upload">
|
||||
<param name="artifact.suffix" value="-javadoc.jar"/>
|
||||
</antcall>
|
||||
|
||||
</parallel>
|
||||
</parallel>
|
||||
|
||||
|
||||
</target>
|
||||
@ -169,6 +164,4 @@
|
||||
</target>
|
||||
|
||||
|
||||
|
||||
|
||||
</project>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.ethereum</groupId>
|
||||
<artifactId>ethereumj</artifactId>
|
||||
@ -8,14 +8,14 @@
|
||||
<name>EthereumJ</name>
|
||||
<url>http://www.ethereumj.org</url>
|
||||
|
||||
<!--
|
||||
* Install jar with sources to the local maven repository
|
||||
mvn install -Dmaven.test.skip=true
|
||||
<!--
|
||||
* Install jar with sources to the local maven repository
|
||||
mvn install -Dmaven.test.skip=true
|
||||
|
||||
* To generate source for ANTLR parser/lexer
|
||||
mvn antlr4:antlr4
|
||||
* To generate source for ANTLR parser/lexer
|
||||
mvn antlr4:antlr4
|
||||
|
||||
-->
|
||||
-->
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
@ -70,9 +70,9 @@
|
||||
</dependency>
|
||||
<!-- Added Cedarsoft for DeepEquals function -->
|
||||
<dependency>
|
||||
<groupId>com.cedarsoftware</groupId>
|
||||
<artifactId>java-util</artifactId>
|
||||
<version>1.8.0</version>
|
||||
<groupId>com.cedarsoftware</groupId>
|
||||
<artifactId>java-util</artifactId>
|
||||
<version>1.8.0</version>
|
||||
</dependency>
|
||||
<!-- For Serpent compile -->
|
||||
<dependency>
|
||||
@ -347,7 +347,7 @@
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!--
|
||||
<!--
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.3</version>
|
||||
@ -367,8 +367,7 @@
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
|
||||
-->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.antlr</groupId>
|
||||
@ -400,9 +399,8 @@
|
||||
</plugin>
|
||||
|
||||
|
||||
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
|
||||
<plugin>
|
||||
|
@ -14,7 +14,7 @@ import org.ethereum.facade.EthereumFactory;
|
||||
|
||||
public class Start {
|
||||
|
||||
public static void main(String args[]){
|
||||
public static void main(String args[]) {
|
||||
CLIInterface.call(args);
|
||||
Ethereum ethereum = EthereumFactory.createEthereum();
|
||||
|
||||
|
@ -19,35 +19,35 @@ public class CLIInterface {
|
||||
private static final Logger logger = LoggerFactory.getLogger("cli");
|
||||
|
||||
|
||||
public static void call(String[] args){
|
||||
public static void call(String[] args) {
|
||||
|
||||
try {
|
||||
for (int i = 0; i < args.length; ++i){
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
|
||||
// override the db directory
|
||||
if (args[i].equals("--help")){
|
||||
if (args[i].equals("--help")) {
|
||||
|
||||
printHelp();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// override the db directory
|
||||
if (args[i].equals("-db") && i + 1 < args.length){
|
||||
String db = args[i+1];
|
||||
if (args[i].equals("-db") && i + 1 < args.length) {
|
||||
String db = args[i + 1];
|
||||
logger.info("DB directory set to [{}]", db);
|
||||
CONFIG.setDataBaseDir(db);
|
||||
}
|
||||
|
||||
// override the listen port directory
|
||||
if (args[i].equals("-listen") && i + 1 < args.length){
|
||||
String port = args[i+1];
|
||||
if (args[i].equals("-listen") && i + 1 < args.length) {
|
||||
String port = args[i + 1];
|
||||
logger.info("Listen port set to [{}]", port);
|
||||
CONFIG.setListenPort(Integer.valueOf(port));
|
||||
}
|
||||
|
||||
// override the connect host:port directory
|
||||
if (args[i].equals("-connect") && i + 1 < args.length){
|
||||
String connectStr = args[i+1];
|
||||
if (args[i].equals("-connect") && i + 1 < args.length) {
|
||||
String connectStr = args[i + 1];
|
||||
logger.info("Connect host:port set to [{}]", connectStr);
|
||||
String[] params = connectStr.split(":");
|
||||
String host = params[0];
|
||||
@ -57,8 +57,8 @@ public class CLIInterface {
|
||||
}
|
||||
|
||||
// override the listen port directory
|
||||
if (args[i].equals("-reset") && i + 1 < args.length){
|
||||
Boolean resetStr = interpret( args[i+1] );
|
||||
if (args[i].equals("-reset") && i + 1 < args.length) {
|
||||
Boolean resetStr = interpret(args[i + 1]);
|
||||
logger.info("Resetting db set to [{}]", resetStr);
|
||||
CONFIG.setDatabaseReset(resetStr);
|
||||
}
|
||||
@ -70,15 +70,15 @@ public class CLIInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private static Boolean interpret(String arg){
|
||||
private static Boolean interpret(String arg) {
|
||||
|
||||
if (arg.equals("on") || arg.equals("true") || arg.equals("yes")) return true;
|
||||
if (arg.equals("on") || arg.equals("true") || arg.equals("yes")) return true;
|
||||
if (arg.equals("off") || arg.equals("false") || arg.equals("no")) return false;
|
||||
|
||||
throw new Error("Can't interpret the answer: " + arg);
|
||||
}
|
||||
|
||||
private static void printHelp(){
|
||||
private static void printHelp() {
|
||||
|
||||
System.out.println("--help -- this help message ");
|
||||
System.out.println("-reset <yes/no> -- reset yes/no the all database ");
|
||||
|
@ -14,41 +14,41 @@ import org.springframework.stereotype.Component;
|
||||
* Utility class to retrieve property values from the system.properties files
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 22/05/2014 19:22
|
||||
* Created on: 22/05/2014 19:22
|
||||
*/
|
||||
public class SystemProperties {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger("general");
|
||||
|
||||
private static int DEFAULT_TX_APPROVE_TIMEOUT = 10;
|
||||
private static String DEFAULT_DISCOVERY_PEER_LIST = "poc-7.ethdev.com:30303";
|
||||
private static String DEFAULT_ACTIVE_PEER_IP = "poc-7.ethdev.com";
|
||||
private static int DEFAULT_ACTIVE_PORT = 30303;
|
||||
private static String DEFAULT_SAMPLES_DIR = "samples";
|
||||
private static String DEFAULT_COINBASE_SECRET = "monkey";
|
||||
private static int DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT = 5;
|
||||
private static Boolean DEFAULT_DB_RESET = false;
|
||||
private static Boolean DEFAULT_DUMP_FULL = false;
|
||||
private static Boolean DEFAULT_RECORD_BLOCKS = false;
|
||||
private static String DEFAULT_DUMP_DIR = "dmp";
|
||||
private static String DEFAULT_DUMP_STYLE = "standard+";
|
||||
private static Integer DEFAULT_VMTRACE_BLOCK = 0;
|
||||
private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir");
|
||||
private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true;
|
||||
private static Boolean DEFAULT_PLAY_VM = true;
|
||||
private static Boolean DEFAULT_BLOCKCHAIN_ONLY = false;
|
||||
private static int DEFAULT_TRACE_STARTBLOCK = -1;
|
||||
private static int DEFAULT_MAX_HASHES_ASK = -1; // unlimited
|
||||
private static int DEFAULT_MAX_BLOCKS_ASK = 10;
|
||||
private static int DEFAULT_MAX_BLOCKS_QUEUED = 300;
|
||||
private static String DEFAULT_PROJECT_VERSION = "";
|
||||
private static String DEFAULT_HELLO_PHRASE = "Dev";
|
||||
private static Boolean DEFAULT_VM_TRACE = false;
|
||||
private static String DEFAULT_VM_TRACE_DIR = "dmp";
|
||||
private static int DEFAULT_PEER_LISTEN_PORT = 30303;
|
||||
private static int DEFAULT_TX_APPROVE_TIMEOUT = 10;
|
||||
private static String DEFAULT_DISCOVERY_PEER_LIST = "poc-7.ethdev.com:30303";
|
||||
private static String DEFAULT_ACTIVE_PEER_IP = "poc-7.ethdev.com";
|
||||
private static int DEFAULT_ACTIVE_PORT = 30303;
|
||||
private static String DEFAULT_SAMPLES_DIR = "samples";
|
||||
private static String DEFAULT_COINBASE_SECRET = "monkey";
|
||||
private static int DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT = 5;
|
||||
private static Boolean DEFAULT_DB_RESET = false;
|
||||
private static Boolean DEFAULT_DUMP_FULL = false;
|
||||
private static Boolean DEFAULT_RECORD_BLOCKS = false;
|
||||
private static String DEFAULT_DUMP_DIR = "dmp";
|
||||
private static String DEFAULT_DUMP_STYLE = "standard+";
|
||||
private static Integer DEFAULT_VMTRACE_BLOCK = 0;
|
||||
private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir");
|
||||
private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true;
|
||||
private static Boolean DEFAULT_PLAY_VM = true;
|
||||
private static Boolean DEFAULT_BLOCKCHAIN_ONLY = false;
|
||||
private static int DEFAULT_TRACE_STARTBLOCK = -1;
|
||||
private static int DEFAULT_MAX_HASHES_ASK = -1; // unlimited
|
||||
private static int DEFAULT_MAX_BLOCKS_ASK = 10;
|
||||
private static int DEFAULT_MAX_BLOCKS_QUEUED = 300;
|
||||
private static String DEFAULT_PROJECT_VERSION = "";
|
||||
private static String DEFAULT_HELLO_PHRASE = "Dev";
|
||||
private static Boolean DEFAULT_VM_TRACE = false;
|
||||
private static String DEFAULT_VM_TRACE_DIR = "dmp";
|
||||
private static int DEFAULT_PEER_LISTEN_PORT = 30303;
|
||||
|
||||
/* Testing */
|
||||
private static Boolean DEFAULT_VMTEST_LOAD_LOCAL = false;
|
||||
private static Boolean DEFAULT_VMTEST_LOAD_LOCAL = false;
|
||||
|
||||
private static List<String> DEFAULT_PROTOCOL_LIST = Arrays.asList("eth", "shh");
|
||||
|
||||
@ -122,7 +122,7 @@ public class SystemProperties {
|
||||
return Boolean.parseBoolean(prop.getProperty("database.reset"));
|
||||
}
|
||||
|
||||
public void setDatabaseReset(Boolean reset){
|
||||
public void setDatabaseReset(Boolean reset) {
|
||||
prop.setProperty("database.reset", reset.toString());
|
||||
}
|
||||
|
||||
@ -131,7 +131,7 @@ public class SystemProperties {
|
||||
return prop.getProperty("peer.active.ip");
|
||||
}
|
||||
|
||||
public void setActivePeerIP(String host){
|
||||
public void setActivePeerIP(String host) {
|
||||
prop.setProperty("peer.active.ip", host.toString());
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ public class SystemProperties {
|
||||
return Integer.parseInt(prop.getProperty("peer.active.port"));
|
||||
}
|
||||
|
||||
public void setActivePeerPort(Integer port){
|
||||
public void setActivePeerPort(Integer port) {
|
||||
prop.setProperty("peer.active.port", port.toString());
|
||||
}
|
||||
|
||||
@ -195,7 +195,7 @@ public class SystemProperties {
|
||||
return prop.getProperty("database.dir");
|
||||
}
|
||||
|
||||
public void setDataBaseDir(String dataBaseDir){
|
||||
public void setDataBaseDir(String dataBaseDir) {
|
||||
prop.setProperty("database.dir", dataBaseDir);
|
||||
}
|
||||
|
||||
@ -247,13 +247,13 @@ public class SystemProperties {
|
||||
return hash;
|
||||
}
|
||||
|
||||
public List<String> peerCapabilities(){
|
||||
public List<String> peerCapabilities() {
|
||||
if (prop.isEmpty()) return DEFAULT_PROTOCOL_LIST;
|
||||
String capabilitiesList = prop.getProperty("peer.capabilities");
|
||||
return Arrays.asList(capabilitiesList.split(","));
|
||||
}
|
||||
|
||||
public boolean vmTrace(){
|
||||
public boolean vmTrace() {
|
||||
if (prop.isEmpty()) return DEFAULT_VM_TRACE;
|
||||
return Boolean.parseBoolean(prop.getProperty("vm.structured.trace"));
|
||||
}
|
||||
@ -263,12 +263,12 @@ public class SystemProperties {
|
||||
return prop.getProperty("vm.structured.dir");
|
||||
}
|
||||
|
||||
public int listenPort(){
|
||||
public int listenPort() {
|
||||
if (prop.isEmpty()) return DEFAULT_PEER_LISTEN_PORT;
|
||||
return Integer.parseInt(prop.getProperty("peer.listen.port"));
|
||||
}
|
||||
|
||||
public void setListenPort(Integer port){
|
||||
public void setListenPort(Integer port) {
|
||||
prop.setProperty("peer.listen.port", port.toString());
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
|
||||
*/
|
||||
@Component
|
||||
@Scope("prototype")
|
||||
public class Account {
|
||||
public class Account {
|
||||
|
||||
private ECKey ecKey;
|
||||
private byte[] address;
|
||||
@ -30,7 +30,7 @@ public class Account {
|
||||
public Account() {
|
||||
}
|
||||
|
||||
public void init(){
|
||||
public void init() {
|
||||
this.ecKey = new ECKey(Utils.getRandom());
|
||||
address = this.ecKey.getAddress();
|
||||
}
|
||||
@ -40,14 +40,14 @@ public class Account {
|
||||
address = this.ecKey.getAddress();
|
||||
}
|
||||
|
||||
public BigInteger getNonce(){
|
||||
public BigInteger getNonce() {
|
||||
AccountState accountState =
|
||||
worldManager.getRepository().getAccountState(getAddress());
|
||||
|
||||
return accountState.getNonce();
|
||||
}
|
||||
|
||||
public BigInteger getBalance(){
|
||||
public BigInteger getBalance() {
|
||||
|
||||
AccountState accountState =
|
||||
worldManager.getRepository().getAccountState(this.getAddress());
|
||||
@ -57,15 +57,15 @@ public class Account {
|
||||
if (accountState != null)
|
||||
balance = accountState.getBalance();
|
||||
|
||||
synchronized (getPendingTransactins()){
|
||||
if (!getPendingTransactins().isEmpty()){
|
||||
synchronized (getPendingTransactins()) {
|
||||
if (!getPendingTransactins().isEmpty()) {
|
||||
|
||||
for (Transaction tx : getPendingTransactins()){
|
||||
if (Arrays.equals(getAddress(), tx.getSender())){
|
||||
for (Transaction tx : getPendingTransactins()) {
|
||||
if (Arrays.equals(getAddress(), tx.getSender())) {
|
||||
balance = balance.subtract(new BigInteger(1, tx.getValue()));
|
||||
}
|
||||
|
||||
if (Arrays.equals(getAddress(), tx.getReceiveAddress())){
|
||||
if (Arrays.equals(getAddress(), tx.getReceiveAddress())) {
|
||||
balance = balance.add(new BigInteger(1, tx.getValue()));
|
||||
}
|
||||
}
|
||||
@ -94,14 +94,14 @@ public class Account {
|
||||
return this.pendingTransactions;
|
||||
}
|
||||
|
||||
public void addPendingTransaction(Transaction transaction){
|
||||
synchronized (pendingTransactions){
|
||||
public void addPendingTransaction(Transaction transaction) {
|
||||
synchronized (pendingTransactions) {
|
||||
pendingTransactions.add(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearAllPendingTransactions(){
|
||||
synchronized (pendingTransactions){
|
||||
public void clearAllPendingTransactions() {
|
||||
synchronized (pendingTransactions) {
|
||||
pendingTransactions.clear();
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class AccountState {
|
||||
* retrieval */
|
||||
private byte[] codeHash = EMPTY_DATA_HASH;
|
||||
|
||||
private boolean dirty = false;
|
||||
private boolean dirty = false;
|
||||
private boolean deleted = false;
|
||||
|
||||
|
||||
@ -57,13 +57,13 @@ public class AccountState {
|
||||
public AccountState(byte[] rlpData) {
|
||||
this.rlpEncoded = rlpData;
|
||||
|
||||
RLPList items = (RLPList) RLP.decode2(rlpEncoded).get(0);
|
||||
RLPList items = (RLPList) RLP.decode2(rlpEncoded).get(0);
|
||||
this.nonce = items.get(0).getRLPData() == null ? BigInteger.ZERO
|
||||
: new BigInteger(1, items.get(0).getRLPData());
|
||||
this.balance = items.get(1).getRLPData() == null ? BigInteger.ZERO
|
||||
: new BigInteger(1, items.get(1).getRLPData());
|
||||
this.stateRoot = items.get(2).getRLPData();
|
||||
this.codeHash = items.get(3).getRLPData();
|
||||
this.stateRoot = items.get(2).getRLPData();
|
||||
this.codeHash = items.get(3).getRLPData();
|
||||
}
|
||||
|
||||
public BigInteger getNonce() {
|
||||
@ -117,11 +117,11 @@ public class AccountState {
|
||||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
if(rlpEncoded == null) {
|
||||
byte[] nonce = RLP.encodeBigInteger(this.nonce);
|
||||
byte[] balance = RLP.encodeBigInteger(this.balance);
|
||||
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
|
||||
byte[] codeHash = RLP.encodeElement(this.codeHash);
|
||||
if (rlpEncoded == null) {
|
||||
byte[] nonce = RLP.encodeBigInteger(this.nonce);
|
||||
byte[] balance = RLP.encodeBigInteger(this.balance);
|
||||
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
|
||||
byte[] codeHash = RLP.encodeElement(this.codeHash);
|
||||
this.rlpEncoded = RLP.encodeList(nonce, balance, stateRoot, codeHash);
|
||||
}
|
||||
return rlpEncoded;
|
||||
@ -143,7 +143,7 @@ public class AccountState {
|
||||
return deleted;
|
||||
}
|
||||
|
||||
public AccountState clone(){
|
||||
public AccountState clone() {
|
||||
AccountState accountState = new AccountState();
|
||||
|
||||
accountState.addToBalance(this.getBalance());
|
||||
@ -156,10 +156,10 @@ public class AccountState {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String ret = " Nonce: " + this.getNonce().toString() + "\n" +
|
||||
" Balance: " + getBalance() + "\n" +
|
||||
" State Root: " + Hex.toHexString(this.getStateRoot()) + "\n" +
|
||||
" Code Hash: " + Hex.toHexString(this.getCodeHash());
|
||||
String ret = " Nonce: " + this.getNonce().toString() + "\n" +
|
||||
" Balance: " + getBalance() + "\n" +
|
||||
" State Root: " + Hex.toHexString(this.getStateRoot()) + "\n" +
|
||||
" Code Hash: " + Hex.toHexString(this.getCodeHash());
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
||||
* (such blocks are known as uncles).
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author Roman Mandeleil,
|
||||
* Nick Savers
|
||||
* Created on: 20/05/2014 10:44
|
||||
@ -31,7 +32,7 @@ public class Block {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("block");
|
||||
|
||||
public static BigInteger BLOCK_REWARD = BigInteger.valueOf(1500000000000000000L);
|
||||
public static BigInteger BLOCK_REWARD = BigInteger.valueOf(1500000000000000000L);
|
||||
public static BigInteger UNCLE_REWARD = BLOCK_REWARD.multiply(
|
||||
BigInteger.valueOf(15)).divide(BigInteger.valueOf(16));
|
||||
public static BigInteger INCLUSION_REWARD = Block.BLOCK_REWARD
|
||||
@ -65,11 +66,11 @@ public class Block {
|
||||
long gasUsed, long timestamp, byte[] extraData, byte[] nonce,
|
||||
List<Transaction> transactionsList, List<BlockHeader> uncleList) {
|
||||
this.header = new BlockHeader(parentHash, unclesHash, coinbase, logsBloom,
|
||||
difficulty, number, gasLimit, gasUsed,
|
||||
difficulty, number, gasLimit, gasUsed,
|
||||
timestamp, extraData, nonce);
|
||||
|
||||
this.transactionsList = transactionsList;
|
||||
if (this.transactionsList == null){
|
||||
if (this.transactionsList == null) {
|
||||
this.transactionsList = new CopyOnWriteArrayList<Transaction>();
|
||||
}
|
||||
|
||||
@ -105,7 +106,7 @@ public class Block {
|
||||
this.parsed = true;
|
||||
}
|
||||
|
||||
public BlockHeader getHeader(){
|
||||
public BlockHeader getHeader() {
|
||||
if (!parsed) parseRLP();
|
||||
return this.header;
|
||||
}
|
||||
@ -162,7 +163,7 @@ public class Block {
|
||||
return this.header.getTxTrieRoot();
|
||||
}
|
||||
|
||||
public byte[] getLogBloom(){
|
||||
public byte[] getLogBloom() {
|
||||
if (!parsed) parseRLP();
|
||||
return this.header.getLogsBloom();
|
||||
}
|
||||
@ -243,7 +244,7 @@ public class Block {
|
||||
toStringBuff.append(header.toString());
|
||||
|
||||
toStringBuff.append("\nUncles [\n");
|
||||
for (BlockHeader uncle : getUncleList()){
|
||||
for (BlockHeader uncle : getUncleList()) {
|
||||
toStringBuff.append(uncle.toString());
|
||||
toStringBuff.append("\n");
|
||||
}
|
||||
@ -277,20 +278,21 @@ public class Block {
|
||||
for (int i = 0; i < txTransactions.size(); i++) {
|
||||
RLPElement transactionRaw = txTransactions.get(i);
|
||||
this.transactionsList.add(new Transaction(transactionRaw.getRLPData()));
|
||||
this.txsState.update(RLP.encodeInt(i) , transactionRaw.getRLPData());
|
||||
this.txsState.update(RLP.encodeInt(i), transactionRaw.getRLPData());
|
||||
}
|
||||
|
||||
String calculatedRoot = Hex.toHexString(txsState.getRootHash());
|
||||
if(!calculatedRoot.equals(Hex.toHexString(expectedRoot)))
|
||||
if (!calculatedRoot.equals(Hex.toHexString(expectedRoot)))
|
||||
logger.error("Added tx receipts don't match the given txsStateRoot");
|
||||
}
|
||||
|
||||
/**
|
||||
* check if param block is son of this block
|
||||
*
|
||||
* @param block - possible a son of this
|
||||
* @return - true if this block is parent of param block
|
||||
*/
|
||||
public boolean isParentOf(Block block){
|
||||
public boolean isParentOf(Block block) {
|
||||
return Arrays.areEqual(this.getHash(), block.getParentHash());
|
||||
}
|
||||
|
||||
@ -298,29 +300,29 @@ public class Block {
|
||||
return this.header.isGenesis();
|
||||
}
|
||||
|
||||
public boolean isEqual(Block block){
|
||||
public boolean isEqual(Block block) {
|
||||
return Arrays.areEqual(this.getHash(), block.getHash());
|
||||
}
|
||||
|
||||
private byte[] getUnclesEncoded(){
|
||||
private byte[] getUnclesEncoded() {
|
||||
|
||||
byte[][] unclesEncoded = new byte[uncleList.size()][];
|
||||
int i = 0;
|
||||
for( BlockHeader uncle : uncleList ){
|
||||
for (BlockHeader uncle : uncleList) {
|
||||
unclesEncoded[i] = uncle.getEncoded();
|
||||
++i;
|
||||
}
|
||||
return RLP.encodeList(unclesEncoded);
|
||||
}
|
||||
|
||||
public void addUncle(BlockHeader uncle){
|
||||
public void addUncle(BlockHeader uncle) {
|
||||
uncleList.add(uncle);
|
||||
this.getHeader().setUnclesHash( SHA3Helper.sha3( getUnclesEncoded() ));
|
||||
this.getHeader().setUnclesHash(SHA3Helper.sha3(getUnclesEncoded()));
|
||||
rlpEncoded = null;
|
||||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
if(rlpEncoded == null) {
|
||||
if (rlpEncoded == null) {
|
||||
byte[] header = this.header.getEncoded();
|
||||
byte[] transactions = RLP.encodeList();
|
||||
byte[] uncles = getUnclesEncoded();
|
||||
@ -335,7 +337,7 @@ public class Block {
|
||||
return header;
|
||||
}
|
||||
|
||||
public String getShortHash(){
|
||||
public String getShortHash() {
|
||||
if (!parsed) parseRLP();
|
||||
return Hex.toHexString(getHash()).substring(0, 6);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public class BlockHeader {
|
||||
|
||||
|
||||
/* The SHA3 256-bit hash of the parent block, in its entirety */
|
||||
private byte[] parentHash;
|
||||
private byte[] parentHash;
|
||||
/* The SHA3 256-bit hash of the uncles list portion of this block */
|
||||
private byte[] unclesHash;
|
||||
/* The 160-bit address to which all fees collected from the
|
||||
@ -63,40 +63,40 @@ public class BlockHeader {
|
||||
|
||||
public BlockHeader(RLPList rlpHeader) {
|
||||
|
||||
this.parentHash = rlpHeader.get(0).getRLPData();
|
||||
this.unclesHash = rlpHeader.get(1).getRLPData();
|
||||
this.coinbase = rlpHeader.get(2).getRLPData();
|
||||
this.stateRoot = rlpHeader.get(3).getRLPData();
|
||||
this.parentHash = rlpHeader.get(0).getRLPData();
|
||||
this.unclesHash = rlpHeader.get(1).getRLPData();
|
||||
this.coinbase = rlpHeader.get(2).getRLPData();
|
||||
this.stateRoot = rlpHeader.get(3).getRLPData();
|
||||
|
||||
this.txTrieRoot = rlpHeader.get(4).getRLPData();
|
||||
if(this.txTrieRoot == null)
|
||||
this.txTrieRoot = rlpHeader.get(4).getRLPData();
|
||||
if (this.txTrieRoot == null)
|
||||
this.txTrieRoot = EMPTY_TRIE_HASH;
|
||||
|
||||
this.recieptTrieRoot = rlpHeader.get(5).getRLPData();
|
||||
if(this.recieptTrieRoot == null)
|
||||
this.recieptTrieRoot = rlpHeader.get(5).getRLPData();
|
||||
if (this.recieptTrieRoot == null)
|
||||
this.recieptTrieRoot = EMPTY_TRIE_HASH;
|
||||
|
||||
this.logsBloom = rlpHeader.get(6).getRLPData();
|
||||
this.difficulty = rlpHeader.get(7).getRLPData();
|
||||
this.logsBloom = rlpHeader.get(6).getRLPData();
|
||||
this.difficulty = rlpHeader.get(7).getRLPData();
|
||||
|
||||
byte[] nrBytes = rlpHeader.get(8).getRLPData();
|
||||
byte[] glBytes = rlpHeader.get(9).getRLPData();
|
||||
byte[] guBytes = rlpHeader.get(10).getRLPData();
|
||||
byte[] tsBytes = rlpHeader.get(11).getRLPData();
|
||||
byte[] nrBytes = rlpHeader.get(8).getRLPData();
|
||||
byte[] glBytes = rlpHeader.get(9).getRLPData();
|
||||
byte[] guBytes = rlpHeader.get(10).getRLPData();
|
||||
byte[] tsBytes = rlpHeader.get(11).getRLPData();
|
||||
|
||||
this.number = nrBytes == null ? 0 : (new BigInteger(1, nrBytes)).longValue();
|
||||
this.number = nrBytes == null ? 0 : (new BigInteger(1, nrBytes)).longValue();
|
||||
|
||||
this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
|
||||
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
|
||||
this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue();
|
||||
this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
|
||||
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
|
||||
this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue();
|
||||
|
||||
this.extraData = rlpHeader.get(12).getRLPData();
|
||||
this.nonce = rlpHeader.get(13).getRLPData();
|
||||
this.extraData = rlpHeader.get(12).getRLPData();
|
||||
this.nonce = rlpHeader.get(13).getRLPData();
|
||||
|
||||
}
|
||||
|
||||
public BlockHeader(byte[] parentHash, byte[] unclesHash, byte[] coinbase,
|
||||
byte[] logsBloom, byte[] difficulty, long number,
|
||||
byte[] logsBloom, byte[] difficulty, long number,
|
||||
long gasLimit, long gasUsed, long timestamp,
|
||||
byte[] extraData, byte[] nonce) {
|
||||
this.parentHash = parentHash;
|
||||
@ -117,6 +117,7 @@ public class BlockHeader {
|
||||
/**
|
||||
* Calculate Difficulty
|
||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (24)
|
||||
*
|
||||
* @return byte array value of the difficulty
|
||||
*/
|
||||
public byte[] calcDifficulty() {
|
||||
@ -132,8 +133,6 @@ public class BlockHeader {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public boolean isGenesis() {
|
||||
return this.getNumber() == Genesis.NUMBER;
|
||||
}
|
||||
@ -141,79 +140,107 @@ public class BlockHeader {
|
||||
public byte[] getParentHash() {
|
||||
return parentHash;
|
||||
}
|
||||
|
||||
public void setParentHash(byte[] parentHash) {
|
||||
this.parentHash = parentHash;
|
||||
}
|
||||
|
||||
public byte[] getUnclesHash() {
|
||||
return unclesHash;
|
||||
}
|
||||
|
||||
public void setUnclesHash(byte[] unclesHash) {
|
||||
this.unclesHash = unclesHash;
|
||||
}
|
||||
|
||||
public byte[] getCoinbase() {
|
||||
return coinbase;
|
||||
}
|
||||
|
||||
public void setCoinbase(byte[] coinbase) {
|
||||
this.coinbase = coinbase;
|
||||
}
|
||||
|
||||
public byte[] getStateRoot() {
|
||||
return stateRoot;
|
||||
}
|
||||
|
||||
public void setStateRoot(byte[] stateRoot) {
|
||||
this.stateRoot = stateRoot;
|
||||
}
|
||||
|
||||
public byte[] getTxTrieRoot() {
|
||||
return txTrieRoot;
|
||||
}
|
||||
|
||||
public void setTxTrieRoot(byte[] txTrieRoot) {
|
||||
this.txTrieRoot = txTrieRoot;
|
||||
}
|
||||
|
||||
public byte[] getRecieptTrieRoot() {
|
||||
return recieptTrieRoot;
|
||||
}
|
||||
public byte[] getLogsBloom() {return logsBloom;}
|
||||
|
||||
public byte[] getLogsBloom() {
|
||||
return logsBloom;
|
||||
}
|
||||
|
||||
public void setRecieptTrieRoot(byte[] recieptTrieRoot) {
|
||||
this.recieptTrieRoot = recieptTrieRoot;
|
||||
}
|
||||
|
||||
public byte[] getDifficulty() {
|
||||
return difficulty;
|
||||
}
|
||||
|
||||
public void setDifficulty(byte[] difficulty) {
|
||||
this.difficulty = difficulty;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public long getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(long number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public long getGasLimit() {
|
||||
return gasLimit;
|
||||
}
|
||||
|
||||
public void setGasLimit(long gasLimit) {
|
||||
this.gasLimit = gasLimit;
|
||||
}
|
||||
|
||||
public long getGasUsed() {
|
||||
return gasUsed;
|
||||
}
|
||||
|
||||
public void setGasUsed(long gasUsed) {
|
||||
this.gasUsed = gasUsed;
|
||||
}
|
||||
|
||||
public byte[] getExtraData() {
|
||||
return extraData;
|
||||
}
|
||||
|
||||
public void setExtraData(byte[] extraData) {
|
||||
this.extraData = extraData;
|
||||
}
|
||||
|
||||
public byte[] getNonce() {
|
||||
return nonce;
|
||||
}
|
||||
|
||||
public void setNonce(byte[] nonce) {
|
||||
this.nonce = nonce;
|
||||
}
|
||||
@ -227,31 +254,31 @@ public class BlockHeader {
|
||||
}
|
||||
|
||||
public byte[] getEncoded(boolean withNonce) {
|
||||
byte[] parentHash = RLP.encodeElement(this.parentHash);
|
||||
byte[] parentHash = RLP.encodeElement(this.parentHash);
|
||||
|
||||
byte[] unclesHash = RLP.encodeElement(this.unclesHash);
|
||||
byte[] coinbase = RLP.encodeElement(this.coinbase);
|
||||
byte[] unclesHash = RLP.encodeElement(this.unclesHash);
|
||||
byte[] coinbase = RLP.encodeElement(this.coinbase);
|
||||
|
||||
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
|
||||
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
|
||||
|
||||
if (txTrieRoot == null) this.txTrieRoot = EMPTY_TRIE_HASH;
|
||||
byte[] txTrieRoot = RLP.encodeElement(this.txTrieRoot);
|
||||
byte[] txTrieRoot = RLP.encodeElement(this.txTrieRoot);
|
||||
|
||||
if (recieptTrieRoot == null) this.recieptTrieRoot = EMPTY_TRIE_HASH;
|
||||
byte[] recieptTrieRoot = RLP.encodeElement(this.recieptTrieRoot);
|
||||
byte[] recieptTrieRoot = RLP.encodeElement(this.recieptTrieRoot);
|
||||
|
||||
byte[] logsBloom = RLP.encodeElement(this.logsBloom);
|
||||
byte[] difficulty = RLP.encodeElement(this.difficulty);
|
||||
byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number));
|
||||
byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit));
|
||||
byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed));
|
||||
byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp));
|
||||
byte[] extraData = RLP.encodeElement(this.extraData);
|
||||
if(withNonce) {
|
||||
byte[] nonce = RLP.encodeElement(this.nonce);
|
||||
byte[] logsBloom = RLP.encodeElement(this.logsBloom);
|
||||
byte[] difficulty = RLP.encodeElement(this.difficulty);
|
||||
byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number));
|
||||
byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit));
|
||||
byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed));
|
||||
byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp));
|
||||
byte[] extraData = RLP.encodeElement(this.extraData);
|
||||
if (withNonce) {
|
||||
byte[] nonce = RLP.encodeElement(this.nonce);
|
||||
return RLP.encodeList(parentHash, unclesHash, coinbase,
|
||||
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
|
||||
gasLimit, gasUsed, timestamp, extraData, nonce);
|
||||
gasLimit, gasUsed, timestamp, extraData, nonce);
|
||||
} else {
|
||||
return RLP.encodeList(parentHash, unclesHash, coinbase,
|
||||
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
|
||||
@ -260,7 +287,6 @@ public class BlockHeader {
|
||||
}
|
||||
|
||||
|
||||
|
||||
private StringBuffer toStringBuff = new StringBuffer();
|
||||
|
||||
public String toString() {
|
||||
@ -269,16 +295,16 @@ public class BlockHeader {
|
||||
toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("\n");
|
||||
toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("\n");
|
||||
toStringBuff.append(" coinbase=" + toHexString(coinbase)).append("\n");
|
||||
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("\n");
|
||||
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("\n");
|
||||
toStringBuff.append(" reciptsTrieHash=" + toHexString(recieptTrieRoot)).append("\n");
|
||||
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("\n");
|
||||
toStringBuff.append(" number=" + number).append("\n");
|
||||
toStringBuff.append(" gasLimit=" + gasLimit).append("\n");
|
||||
toStringBuff.append(" gasUsed=" + gasUsed).append("\n");
|
||||
toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n");
|
||||
toStringBuff.append(" extraData=" + toHexString(extraData)).append("\n");
|
||||
toStringBuff.append(" nonce=" + toHexString(nonce)).append("\n");
|
||||
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("\n");
|
||||
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("\n");
|
||||
toStringBuff.append(" reciptsTrieHash=" + toHexString(recieptTrieRoot)).append("\n");
|
||||
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("\n");
|
||||
toStringBuff.append(" number=" + number).append("\n");
|
||||
toStringBuff.append(" gasLimit=" + gasLimit).append("\n");
|
||||
toStringBuff.append(" gasUsed=" + gasUsed).append("\n");
|
||||
toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n");
|
||||
toStringBuff.append(" extraData=" + toHexString(extraData)).append("\n");
|
||||
toStringBuff.append(" nonce=" + toHexString(nonce)).append("\n");
|
||||
return toStringBuff.toString();
|
||||
}
|
||||
|
||||
@ -286,15 +312,15 @@ public class BlockHeader {
|
||||
toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("");
|
||||
toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("");
|
||||
toStringBuff.append(" coinbase=" + toHexString(coinbase)).append("");
|
||||
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("");
|
||||
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("");
|
||||
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("");
|
||||
toStringBuff.append(" number=" + number).append("");
|
||||
toStringBuff.append(" gasLimit=" + gasLimit).append("");
|
||||
toStringBuff.append(" gasUsed=" + gasUsed).append("");
|
||||
toStringBuff.append(" timestamp=" + timestamp).append("");
|
||||
toStringBuff.append(" extraData=" + toHexString(extraData)).append("");
|
||||
toStringBuff.append(" nonce=" + toHexString(nonce)).append("");
|
||||
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("");
|
||||
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("");
|
||||
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("");
|
||||
toStringBuff.append(" number=" + number).append("");
|
||||
toStringBuff.append(" gasLimit=" + gasLimit).append("");
|
||||
toStringBuff.append(" gasUsed=" + gasUsed).append("");
|
||||
toStringBuff.append(" timestamp=" + timestamp).append("");
|
||||
toStringBuff.append(" extraData=" + toHexString(extraData)).append("");
|
||||
toStringBuff.append(" nonce=" + toHexString(nonce)).append("");
|
||||
return toStringBuff.toString();
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ import static org.ethereum.core.Denomination.SZABO;
|
||||
* <li>Check that the proof of work on the block is valid.</li>
|
||||
* <li>Let S[0] be the STATE_ROOT of the previous block.</li>
|
||||
* <li>Let TX be the block's transaction list, with n transactions.
|
||||
* For all in in 0...n-1, set S[i+1] = APPLY(S[i],TX[i]).
|
||||
* For all in in 0...n-1, set S[i+1] = APPLY(S[i],TX[i]).
|
||||
* If any applications returns an error, or if the total gas consumed in the block
|
||||
* up until this point exceeds the GASLIMIT, return an error.</li>
|
||||
* <li>Let S_FINAL be S[n], but adding the block reward paid to the miner.</li>
|
||||
@ -54,6 +54,7 @@ import static org.ethereum.core.Denomination.SZABO;
|
||||
* See <a href="https://github.com/ethereum/wiki/wiki/White-Paper#blockchain-and-mining">Ethereum Whitepaper</a>
|
||||
*
|
||||
* www.etherJ.com
|
||||
*
|
||||
* @author Roman Mandeleil,
|
||||
* Nick Savers
|
||||
* Created on: 20/05/2014 10:44
|
||||
@ -119,23 +120,23 @@ public class BlockchainImpl implements Blockchain {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionReceipt getTransactionReceiptByHash(byte[] hash){
|
||||
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
|
||||
|
||||
return blockStore.getTransactionReceiptByHash(hash);
|
||||
return blockStore.getTransactionReceiptByHash(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlockByHash(byte[] hash){
|
||||
public Block getBlockByHash(byte[] hash) {
|
||||
return blockStore.getBlockByHash(hash);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty){
|
||||
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
|
||||
return blockStore.getListOfHashesStartFrom(hash, qty);
|
||||
}
|
||||
|
||||
|
||||
public void tryToConnect(Block block){
|
||||
public void tryToConnect(Block block) {
|
||||
|
||||
recordBlock(block);
|
||||
|
||||
@ -144,7 +145,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
Hex.toHexString(block.getHash()).substring(0, 6),
|
||||
block.getNumber());
|
||||
|
||||
if (blockStore.getBlockByHash(block.getHash()) != null){
|
||||
if (blockStore.getBlockByHash(block.getHash()) != null) {
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Block already exist hash: {}, number: {}",
|
||||
@ -157,12 +158,12 @@ public class BlockchainImpl implements Blockchain {
|
||||
|
||||
// The simple case got the block
|
||||
// to connect to the main chain
|
||||
if (bestBlock.isParentOf(block)){
|
||||
if (bestBlock.isParentOf(block)) {
|
||||
add(block);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasParentOnTheChain(block) && block.getNumber() > bestBlock.getNumber()){
|
||||
if (!hasParentOnTheChain(block) && block.getNumber() > bestBlock.getNumber()) {
|
||||
|
||||
logger.info("*** Blockchain will rollback and resynchronise now ");
|
||||
|
||||
@ -198,7 +199,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
|
||||
// keep chain continuity
|
||||
if (!Arrays.equals(getBestBlock().getHash(),
|
||||
block.getParentHash())) return;
|
||||
block.getParentHash())) return;
|
||||
|
||||
if (block.getNumber() >= CONFIG.traceStartBlock() && CONFIG.traceStartBlock() != -1) {
|
||||
AdvancedDeviceUtils.adjustDetailedTracing(block.getNumber());
|
||||
@ -221,8 +222,8 @@ public class BlockchainImpl implements Blockchain {
|
||||
listener.onBlock(block);
|
||||
|
||||
if (blockQueue.size() == 0 &&
|
||||
!syncDoneCalled &&
|
||||
channelManager.isAllSync()){
|
||||
!syncDoneCalled &&
|
||||
channelManager.isAllSync()) {
|
||||
|
||||
logger.info("Sync done");
|
||||
syncDoneCalled = true;
|
||||
@ -231,7 +232,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
}
|
||||
|
||||
|
||||
public Block getParent(BlockHeader header){
|
||||
public Block getParent(BlockHeader header) {
|
||||
|
||||
return blockStore.getBlockByHash(header.getParentHash());
|
||||
}
|
||||
@ -239,6 +240,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
/**
|
||||
* Calculate GasLimit
|
||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (25)
|
||||
*
|
||||
* @return long value of the gasLimit
|
||||
*/
|
||||
public long calcGasLimit(BlockHeader header) {
|
||||
@ -272,12 +274,12 @@ public class BlockchainImpl implements Blockchain {
|
||||
* likely next period. Conversely, if the period is too large, the difficulty,
|
||||
* and expected time to the next block, is reduced.
|
||||
*/
|
||||
private boolean isValid(Block block){
|
||||
private boolean isValid(Block block) {
|
||||
|
||||
boolean isValid = true;
|
||||
if (isValid) return (isValid); // todo get back to the real header validation
|
||||
|
||||
if(!block.isGenesis()) {
|
||||
if (!block.isGenesis()) {
|
||||
isValid = isValid(block.getHeader());
|
||||
|
||||
for (BlockHeader uncle : block.getUncleList()) {
|
||||
@ -291,7 +293,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
isValid = generationGap > 0 && generationGap < 7;
|
||||
}
|
||||
}
|
||||
if(!isValid)
|
||||
if (!isValid)
|
||||
logger.warn("WARNING: Invalid - {}", this);
|
||||
return isValid;
|
||||
|
||||
@ -300,7 +302,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
private void processBlock(Block block) {
|
||||
|
||||
List<TransactionReceipt> receipts = new ArrayList<>();
|
||||
if(isValid(block)) {
|
||||
if (isValid(block)) {
|
||||
if (!block.isGenesis()) {
|
||||
if (!CONFIG.blockChainOnly()) {
|
||||
wallet.addTransactions(block.getTransactionsList());
|
||||
@ -341,9 +343,9 @@ public class BlockchainImpl implements Blockchain {
|
||||
stateLogger.info("[{}] ", receipt.toString());
|
||||
|
||||
if (stateLogger.isInfoEnabled())
|
||||
stateLogger.info("tx[{}].receipt: [{}] ",i, Hex.toHexString(receipt.getEncoded()));
|
||||
stateLogger.info("tx[{}].receipt: [{}] ", i, Hex.toHexString(receipt.getEncoded()));
|
||||
|
||||
if(block.getNumber() >= CONFIG.traceStartBlock())
|
||||
if (block.getNumber() >= CONFIG.traceStartBlock())
|
||||
repository.dumpState(block, totalGasUsed, i++, tx.getHash());
|
||||
|
||||
reciepts.add(receipt);
|
||||
@ -354,7 +356,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
|
||||
track.commit();
|
||||
|
||||
if(block.getNumber() >= CONFIG.traceStartBlock())
|
||||
if (block.getNumber() >= CONFIG.traceStartBlock())
|
||||
repository.dumpState(block, totalGasUsed, 0, null);
|
||||
|
||||
return reciepts;
|
||||
@ -372,7 +374,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
BigInteger totalBlockReward = Block.BLOCK_REWARD;
|
||||
|
||||
// Add extra rewards based on number of uncles
|
||||
if(block.getUncleList().size() > 0) {
|
||||
if (block.getUncleList().size() > 0) {
|
||||
for (BlockHeader uncle : block.getUncleList()) {
|
||||
track.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD);
|
||||
}
|
||||
@ -386,10 +388,10 @@ public class BlockchainImpl implements Blockchain {
|
||||
public void storeBlock(Block block, List<TransactionReceipt> receipts) {
|
||||
|
||||
/* Debug check to see if the state is still as expected */
|
||||
if(logger.isWarnEnabled()) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
String blockStateRootHash = Hex.toHexString(block.getStateRoot());
|
||||
String worldStateRootHash = Hex.toHexString(repository.getRoot());
|
||||
if(!blockStateRootHash.equals(worldStateRootHash)){
|
||||
if (!blockStateRootHash.equals(worldStateRootHash)) {
|
||||
|
||||
stateLogger.info("BLOCK: STATE CONFLICT! block: {} worldstate {} mismatch", block.getNumber(), worldStateRootHash);
|
||||
adminInfo.lostConsensus();
|
||||
@ -411,17 +413,17 @@ public class BlockchainImpl implements Blockchain {
|
||||
}
|
||||
|
||||
|
||||
public boolean hasParentOnTheChain(Block block){
|
||||
public boolean hasParentOnTheChain(Block block) {
|
||||
return getParent(block.getHeader()) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Chain> getAltChains(){
|
||||
public List<Chain> getAltChains() {
|
||||
return altChains;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Block> getGarbage(){
|
||||
public List<Block> getGarbage() {
|
||||
return garbage;
|
||||
}
|
||||
|
||||
@ -442,14 +444,14 @@ public class BlockchainImpl implements Blockchain {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(){
|
||||
public void reset() {
|
||||
blockStore.reset();
|
||||
altChains = new ArrayList<>();
|
||||
garbage = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(){
|
||||
public void close() {
|
||||
blockQueue.close();
|
||||
}
|
||||
|
||||
@ -468,12 +470,15 @@ public class BlockchainImpl implements Blockchain {
|
||||
this.totalDifficulty = totalDifficulty;
|
||||
}
|
||||
|
||||
private void recordBlock(Block block){
|
||||
private void recordBlock(Block block) {
|
||||
|
||||
if (!CONFIG.recordBlocks()) return;
|
||||
|
||||
if (bestBlock.isGenesis()){
|
||||
try {FileUtils.deleteDirectory(CONFIG.dumpDir());} catch (IOException e) {}
|
||||
if (bestBlock.isGenesis()) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(CONFIG.dumpDir());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
String dir = CONFIG.dumpDir() + "/";
|
||||
@ -490,7 +495,7 @@ public class BlockchainImpl implements Blockchain {
|
||||
fw = new FileWriter(dumpFile.getAbsoluteFile(), true);
|
||||
bw = new BufferedWriter(fw);
|
||||
|
||||
if (bestBlock.isGenesis()){
|
||||
if (bestBlock.isGenesis()) {
|
||||
bw.write(Hex.toHexString(bestBlock.getEncoded()));
|
||||
bw.write("\n");
|
||||
}
|
||||
@ -516,15 +521,15 @@ public class BlockchainImpl implements Blockchain {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public void setProgramInvokeFactory(ProgramInvokeFactory factory){
|
||||
public void setProgramInvokeFactory(ProgramInvokeFactory factory) {
|
||||
this.programInvokeFactory = factory;
|
||||
}
|
||||
|
||||
public void startTracking(){
|
||||
public void startTracking() {
|
||||
track = repository.startTracking();
|
||||
}
|
||||
|
||||
public void commitTracking(){
|
||||
public void commitTracking() {
|
||||
track.commit();
|
||||
}
|
||||
|
||||
|
@ -15,14 +15,14 @@ import java.util.Arrays;
|
||||
* http://www.herongyang.com/Java/Bit-String-Set-Bit-to-Byte-Array.html
|
||||
*/
|
||||
|
||||
public class Bloom {
|
||||
public class Bloom {
|
||||
|
||||
byte[] data = new byte[64];
|
||||
|
||||
public Bloom() {
|
||||
}
|
||||
|
||||
public Bloom(byte[] data){
|
||||
public Bloom(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@ -41,8 +41,8 @@ public class Bloom {
|
||||
return bloom;
|
||||
}
|
||||
|
||||
public void or(Bloom bloom){
|
||||
for (int i = 0; i < data.length; ++i){
|
||||
public void or(Bloom bloom) {
|
||||
for (int i = 0; i < data.length; ++i) {
|
||||
data[i] |= bloom.data[i];
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class Chain {
|
||||
private Map<ByteArrayWrapper, Block> index = new HashMap<>();
|
||||
|
||||
|
||||
public boolean tryToConnect(Block block){
|
||||
public boolean tryToConnect(Block block) {
|
||||
|
||||
if (chain.isEmpty()) {
|
||||
add(block);
|
||||
@ -35,14 +35,14 @@ public class Chain {
|
||||
}
|
||||
|
||||
Block lastBlock = chain.get(chain.size() - 1);
|
||||
if (lastBlock.isParentOf(block)){
|
||||
if (lastBlock.isParentOf(block)) {
|
||||
add(block);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void add(Block block){
|
||||
public void add(Block block) {
|
||||
logger.info("adding block to alt chain block.hash: [{}] ", block.getShortHash());
|
||||
totalDifficulty = totalDifficulty.add(block.getCumulativeDifficulty());
|
||||
logger.info("total difficulty on alt chain is: [{}] ", totalDifficulty);
|
||||
@ -50,15 +50,15 @@ public class Chain {
|
||||
index.put(new ByteArrayWrapper(block.getHash()), block);
|
||||
}
|
||||
|
||||
public Block get(int i){
|
||||
public Block get(int i) {
|
||||
return chain.get(i);
|
||||
}
|
||||
|
||||
public Block getLast(){
|
||||
public Block getLast() {
|
||||
return chain.get(chain.size() - 1);
|
||||
}
|
||||
|
||||
public BigInteger getTotalDifficulty(){
|
||||
public BigInteger getTotalDifficulty() {
|
||||
return totalDifficulty;
|
||||
}
|
||||
|
||||
@ -66,11 +66,11 @@ public class Chain {
|
||||
this.totalDifficulty = totalDifficulty;
|
||||
}
|
||||
|
||||
public boolean isParentOnTheChain(Block block){
|
||||
return (index.get(new ByteArrayWrapper( block.getParentHash() )) != null);
|
||||
public boolean isParentOnTheChain(Block block) {
|
||||
return (index.get(new ByteArrayWrapper(block.getParentHash())) != null);
|
||||
}
|
||||
|
||||
public long getSize(){
|
||||
public long getSize() {
|
||||
return chain.size();
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ public class Genesis extends Block {
|
||||
|
||||
public final static BigInteger PREMINE_AMOUNT = BigInteger.valueOf(2).pow(200);
|
||||
|
||||
private static String[] premine = new String[] {
|
||||
private static String[] premine = new String[]{
|
||||
"51ba59315b3a95761d0863b05ccc7a7f54703d99",
|
||||
"e6716f9544a56c530d868e4bfbacb172315bdead", // # (J)
|
||||
"b9c015918bdaba24b4ff057a92a3873d6eb201be", // # (V)
|
||||
@ -50,10 +50,10 @@ public class Genesis extends Block {
|
||||
public static byte[] COINBASE = zeroHash160;
|
||||
public static byte[] LOG_BLOOM = zeroHash512;
|
||||
public static byte[] DIFFICULTY = BigInteger.valueOf(2).pow(17).toByteArray();
|
||||
public static long NUMBER = 0;
|
||||
public static long GAS_LIMIT = 1000000;
|
||||
public static long GAS_USED = 0;
|
||||
public static long TIMESTAMP = 0;
|
||||
public static long NUMBER = 0;
|
||||
public static long GAS_LIMIT = 1000000;
|
||||
public static long GAS_USED = 0;
|
||||
public static long TIMESTAMP = 0;
|
||||
public static byte[] EXTRA_DATA = new byte[0];
|
||||
public static byte[] NONCE = sha3(new byte[]{42});
|
||||
|
||||
|
@ -10,6 +10,7 @@ import org.ethereum.util.RLPList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.BigIntegers;
|
||||
|
||||
import java.security.SignatureException;
|
||||
|
||||
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
@ -86,7 +87,7 @@ public class Transaction {
|
||||
this.value = value;
|
||||
this.data = data;
|
||||
|
||||
if(receiveAddress == null) {
|
||||
if (receiveAddress == null) {
|
||||
this.receiveAddress = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
}
|
||||
|
||||
@ -97,25 +98,25 @@ public class Transaction {
|
||||
public void rlpParse() {
|
||||
|
||||
RLPList decodedTxList = RLP.decode2(rlpEncoded);
|
||||
RLPList transaction = (RLPList) decodedTxList.get(0);
|
||||
RLPList transaction = (RLPList) decodedTxList.get(0);
|
||||
|
||||
this.nonce = transaction.get(0).getRLPData();
|
||||
this.gasPrice = transaction.get(1).getRLPData();
|
||||
this.gasLimit = transaction.get(2).getRLPData();
|
||||
this.nonce = transaction.get(0).getRLPData();
|
||||
this.gasPrice = transaction.get(1).getRLPData();
|
||||
this.gasLimit = transaction.get(2).getRLPData();
|
||||
this.receiveAddress = transaction.get(3).getRLPData();
|
||||
this.value = transaction.get(4).getRLPData();
|
||||
this.data = transaction.get(5).getRLPData();
|
||||
this.value = transaction.get(4).getRLPData();
|
||||
this.data = transaction.get(5).getRLPData();
|
||||
// only parse signature in case tx is signed
|
||||
if(transaction.get(6).getRLPData() != null) {
|
||||
byte v = transaction.get(6).getRLPData()[0];
|
||||
byte[] r = transaction.get(7).getRLPData();
|
||||
byte[] s = transaction.get(8).getRLPData();
|
||||
if (transaction.get(6).getRLPData() != null) {
|
||||
byte v = transaction.get(6).getRLPData()[0];
|
||||
byte[] r = transaction.get(7).getRLPData();
|
||||
byte[] s = transaction.get(8).getRLPData();
|
||||
this.signature = ECDSASignature.fromComponents(r, s, v);
|
||||
} else {
|
||||
logger.debug("RLP encoded tx is not signed!");
|
||||
}
|
||||
this.parsed = true;
|
||||
this.hash = getHash();
|
||||
this.hash = getHash();
|
||||
}
|
||||
|
||||
public boolean isParsed() {
|
||||
@ -158,7 +159,7 @@ public class Transaction {
|
||||
|
||||
public byte[] getGasPrice() {
|
||||
if (!parsed) rlpParse();
|
||||
return gasPrice== null ? ZERO_BYTE_ARRAY : gasPrice;
|
||||
return gasPrice == null ? ZERO_BYTE_ARRAY : gasPrice;
|
||||
}
|
||||
|
||||
public byte[] getGasLimit() {
|
||||
@ -166,7 +167,7 @@ public class Transaction {
|
||||
return gasLimit;
|
||||
}
|
||||
|
||||
public long nonZeroDataBytes(){
|
||||
public long nonZeroDataBytes() {
|
||||
if (data == null) return 0;
|
||||
int counter = 0;
|
||||
for (final byte aData : data) {
|
||||
@ -175,7 +176,7 @@ public class Transaction {
|
||||
return counter;
|
||||
}
|
||||
|
||||
public long zeroDataBytes(){
|
||||
public long zeroDataBytes() {
|
||||
if (data == null) return 0;
|
||||
int counter = 0;
|
||||
for (final byte aData : data) {
|
||||
@ -237,7 +238,7 @@ public class Transaction {
|
||||
@Override
|
||||
public String toString() {
|
||||
if (!parsed) rlpParse();
|
||||
return "TransactionData [" + "hash=" + ByteUtil.toHexString(hash) +
|
||||
return "TransactionData [" + "hash=" + ByteUtil.toHexString(hash) +
|
||||
" nonce=" + ByteUtil.toHexString(nonce) +
|
||||
", gasPrice=" + ByteUtil.toHexString(gasPrice) +
|
||||
", gas=" + ByteUtil.toHexString(gasLimit) +
|
||||
@ -251,8 +252,8 @@ public class Transaction {
|
||||
}
|
||||
|
||||
/**
|
||||
* For signatures you have to keep also
|
||||
* RLP of the transaction without any signature data
|
||||
* For signatures you have to keep also
|
||||
* RLP of the transaction without any signature data
|
||||
*/
|
||||
public byte[] getEncodedRaw() {
|
||||
|
||||
@ -261,16 +262,16 @@ public class Transaction {
|
||||
|
||||
// parse null as 0 for nonce
|
||||
byte[] nonce = null;
|
||||
if ( this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0){
|
||||
nonce = RLP.encodeElement(null);
|
||||
if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) {
|
||||
nonce = RLP.encodeElement(null);
|
||||
} else {
|
||||
nonce = RLP.encodeElement(this.nonce);
|
||||
nonce = RLP.encodeElement(this.nonce);
|
||||
}
|
||||
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
||||
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
||||
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
||||
byte[] value = RLP.encodeElement(this.value);
|
||||
byte[] data = RLP.encodeElement(this.data);
|
||||
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
||||
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
||||
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
||||
byte[] value = RLP.encodeElement(this.value);
|
||||
byte[] data = RLP.encodeElement(this.data);
|
||||
|
||||
rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress,
|
||||
value, data);
|
||||
@ -279,25 +280,25 @@ public class Transaction {
|
||||
|
||||
public byte[] getEncoded() {
|
||||
|
||||
if(rlpEncoded != null) return rlpEncoded;
|
||||
if (rlpEncoded != null) return rlpEncoded;
|
||||
|
||||
// parse null as 0 for nonce
|
||||
byte[] nonce = null;
|
||||
if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0){
|
||||
nonce = RLP.encodeElement(null);
|
||||
if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) {
|
||||
nonce = RLP.encodeElement(null);
|
||||
} else {
|
||||
nonce = RLP.encodeElement(this.nonce);
|
||||
nonce = RLP.encodeElement(this.nonce);
|
||||
}
|
||||
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
||||
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
||||
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
||||
byte[] value = RLP.encodeElement(this.value);
|
||||
byte[] data = RLP.encodeElement(this.data);
|
||||
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
|
||||
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
|
||||
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
|
||||
byte[] value = RLP.encodeElement(this.value);
|
||||
byte[] data = RLP.encodeElement(this.data);
|
||||
|
||||
byte[] v, r, s;
|
||||
|
||||
if(signature != null) {
|
||||
v = RLP.encodeByte( signature.v );
|
||||
if (signature != null) {
|
||||
v = RLP.encodeByte(signature.v);
|
||||
r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r));
|
||||
s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s));
|
||||
} else {
|
||||
@ -309,7 +310,7 @@ public class Transaction {
|
||||
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit,
|
||||
receiveAddress, value, data, v, r, s);
|
||||
|
||||
this.hash = this.getHash();
|
||||
this.hash = this.getHash();
|
||||
|
||||
return rlpEncoded;
|
||||
}
|
||||
@ -331,7 +332,7 @@ public class Transaction {
|
||||
public boolean equals(Object obj) {
|
||||
|
||||
if (!(obj instanceof Transaction)) return false;
|
||||
Transaction tx = (Transaction)obj;
|
||||
Transaction tx = (Transaction) obj;
|
||||
|
||||
return tx.hashCode() == this.hashCode();
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ public class TransactionExecutor {
|
||||
ProgramInvokeFactory programInvokeFactory, Block currentBlock) {
|
||||
|
||||
this.tx = tx;
|
||||
this.coinbase = coinbase;
|
||||
this.coinbase = coinbase;
|
||||
this.track = track;
|
||||
this.programInvokeFactory = programInvokeFactory;
|
||||
this.currentBlock = currentBlock;
|
||||
@ -53,7 +53,7 @@ public class TransactionExecutor {
|
||||
// https://github.com/ethereum/cpp-ethereum/blob/develop/libethereum/Executive.cpp#L55
|
||||
|
||||
|
||||
public void execute(){
|
||||
public void execute() {
|
||||
|
||||
|
||||
logger.info("applyTransaction: [{}]", Hex.toHexString(tx.getHash()));
|
||||
@ -166,8 +166,8 @@ public class TransactionExecutor {
|
||||
try {
|
||||
|
||||
// CREATE NEW CONTRACT ADDRESS AND ADD TX VALUE
|
||||
if(isContractCreation) {
|
||||
if(stateLogger.isDebugEnabled())
|
||||
if (isContractCreation) {
|
||||
if (stateLogger.isDebugEnabled())
|
||||
stateLogger.debug("new contract created address={}",
|
||||
Hex.toHexString(receiverAddress));
|
||||
}
|
||||
@ -199,9 +199,9 @@ public class TransactionExecutor {
|
||||
trackTx.commit();
|
||||
} else {
|
||||
// REFUND GASDEBIT EXCEPT FOR FEE (500 + 5*TX_NO_ZERO_DATA)
|
||||
long dataCost = tx.getData() == null ? 0:
|
||||
long dataCost = tx.getData() == null ? 0 :
|
||||
tx.nonZeroDataBytes() * GasCost.TX_NO_ZERO_DATA +
|
||||
tx.zeroDataBytes() * GasCost.TX_ZERO_DATA;
|
||||
tx.zeroDataBytes() * GasCost.TX_ZERO_DATA;
|
||||
gasUsed = GasCost.TRANSACTION + dataCost;
|
||||
|
||||
BigInteger refund = gasDebit.subtract(BigInteger.valueOf(gasUsed).multiply(gasPrice));
|
||||
@ -253,7 +253,7 @@ public class TransactionExecutor {
|
||||
repository.addBalance(coinbase, refund.negate());
|
||||
}
|
||||
|
||||
if (result.getFutureRefund() > 0){
|
||||
if (result.getFutureRefund() > 0) {
|
||||
|
||||
long futureRefund = Math.min(result.getFutureRefund(), result.getGasUsed() / 2);
|
||||
BigInteger futureRefundBI = BigInteger.valueOf(futureRefund);
|
||||
@ -284,11 +284,12 @@ public class TransactionExecutor {
|
||||
Hex.toHexString(contractAddress),
|
||||
Hex.toHexString(bodyCode));
|
||||
|
||||
BigInteger storageCost = gasPrice.multiply( BigInteger.valueOf( bodyCode.length * GasCost.CREATE_DATA_BYTE) );
|
||||
BigInteger storageCost = gasPrice.multiply(BigInteger.valueOf(bodyCode.length * GasCost
|
||||
.CREATE_DATA_BYTE));
|
||||
BigInteger balance = repository.getBalance(senderAddress);
|
||||
|
||||
// check if can be charged for the contract data save
|
||||
if (storageCost.compareTo(balance) > 1){
|
||||
if (storageCost.compareTo(balance) > 1) {
|
||||
bodyCode = EMPTY_BYTE_ARRAY;
|
||||
} else {
|
||||
repository.addBalance(coinbase, storageCost);
|
||||
@ -301,7 +302,7 @@ public class TransactionExecutor {
|
||||
|
||||
// delete the marked to die accounts
|
||||
if (result.getDeleteAccounts() == null) return;
|
||||
for (DataWord address : result.getDeleteAccounts()){
|
||||
for (DataWord address : result.getDeleteAccounts()) {
|
||||
repository.delete(address.getNoLeadZeroesData());
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,6 @@ import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
* comprising the transaction, together with the post-transaction state,
|
||||
* and the cumulative gas used in the block containing the transaction receipt
|
||||
* as of immediately after the transaction has happened,
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class TransactionReceipt {
|
||||
|
||||
@ -26,7 +24,7 @@ public class TransactionReceipt {
|
||||
|
||||
private byte[] postTxState = EMPTY_BYTE_ARRAY;
|
||||
private byte[] cumulativeGas = EMPTY_BYTE_ARRAY;
|
||||
private Bloom bloomFilter = new Bloom();
|
||||
private Bloom bloomFilter = new Bloom();
|
||||
private List<LogInfo> logInfoList = new ArrayList<LogInfo>();
|
||||
|
||||
/* Tx Receipt in encoded form */
|
||||
@ -40,10 +38,10 @@ public class TransactionReceipt {
|
||||
RLPList params = RLP.decode2(rlp);
|
||||
RLPList receipt = (RLPList) params.get(0);
|
||||
|
||||
RLPItem postTxStateRLP = (RLPItem) receipt.get(0);
|
||||
RLPItem postTxStateRLP = (RLPItem) receipt.get(0);
|
||||
RLPItem cumulativeGasRLP = (RLPItem) receipt.get(1);
|
||||
RLPItem bloomRLP = (RLPItem) receipt.get(2);
|
||||
RLPList logs = (RLPList) receipt.get(3);
|
||||
RLPItem bloomRLP = (RLPItem) receipt.get(2);
|
||||
RLPList logs = (RLPList) receipt.get(3);
|
||||
|
||||
postTxState = postTxStateRLP.getRLPData();
|
||||
cumulativeGas = cumulativeGasRLP.getRLPData();
|
||||
@ -92,11 +90,11 @@ public class TransactionReceipt {
|
||||
/* [postTxState, cumulativeGas, bloomFilter, logInfoList] */
|
||||
public byte[] getEncoded() {
|
||||
|
||||
if(rlpEncoded != null) return rlpEncoded;
|
||||
if (rlpEncoded != null) return rlpEncoded;
|
||||
|
||||
byte[] postTxStateRLP = RLP.encodeElement(this.postTxState);
|
||||
byte[] postTxStateRLP = RLP.encodeElement(this.postTxState);
|
||||
byte[] cumulativeGasRLP = RLP.encodeElement(this.cumulativeGas);
|
||||
byte[] bloomRLP = RLP.encodeElement(this.bloomFilter.data);
|
||||
byte[] bloomRLP = RLP.encodeElement(this.bloomFilter.data);
|
||||
|
||||
byte[] logInfoListRLP = null;
|
||||
if (logInfoList != null) {
|
||||
@ -104,11 +102,11 @@ public class TransactionReceipt {
|
||||
|
||||
int i = 0;
|
||||
for (LogInfo logInfo : logInfoList) {
|
||||
logInfoListE[i] = logInfo.getEncoded() ;
|
||||
logInfoListE[i] = logInfo.getEncoded();
|
||||
++i;
|
||||
}
|
||||
logInfoListRLP = RLP.encodeList(logInfoListE);
|
||||
} else{
|
||||
} else {
|
||||
logInfoListRLP = RLP.encodeList();
|
||||
}
|
||||
|
||||
@ -122,7 +120,7 @@ public class TransactionReceipt {
|
||||
}
|
||||
|
||||
public void setCumulativeGas(long cumulativeGas) {
|
||||
this.cumulativeGas = BigIntegers.asUnsignedByteArray( BigInteger.valueOf( cumulativeGas ) );
|
||||
this.cumulativeGas = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(cumulativeGas));
|
||||
}
|
||||
|
||||
public void setCumulativeGas(byte[] cumulativeGas) {
|
||||
@ -135,16 +133,16 @@ public class TransactionReceipt {
|
||||
this.rlpEncoded = null;
|
||||
this.logInfoList = logInfoList;
|
||||
|
||||
for (LogInfo loginfo : logInfoList){
|
||||
for (LogInfo loginfo : logInfoList) {
|
||||
bloomFilter.or(loginfo.getBloom());
|
||||
}
|
||||
}
|
||||
|
||||
public void setTransaction(Transaction transaction){
|
||||
public void setTransaction(Transaction transaction) {
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
public Transaction getTransaction(){
|
||||
public Transaction getTransaction() {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
@ -110,7 +110,7 @@ public class Wallet {
|
||||
* @param transaction
|
||||
* @return
|
||||
*/
|
||||
public WalletTransaction addByWalletTransaction(Transaction transaction){
|
||||
public WalletTransaction addByWalletTransaction(Transaction transaction) {
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
WalletTransaction walletTransaction = new WalletTransaction(transaction);
|
||||
this.walletTransactions.put(hash, walletTransaction);
|
||||
@ -127,9 +127,9 @@ public class Wallet {
|
||||
*/
|
||||
public WalletTransaction addTransaction(Transaction transaction) {
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction placed hash: {}", hash );
|
||||
logger.info("pending transaction placed hash: {}", hash);
|
||||
|
||||
WalletTransaction walletTransaction = this.walletTransactions.get(hash);
|
||||
WalletTransaction walletTransaction = this.walletTransactions.get(hash);
|
||||
if (walletTransaction != null)
|
||||
walletTransaction.incApproved();
|
||||
else {
|
||||
@ -158,7 +158,7 @@ public class Wallet {
|
||||
|
||||
public void removeTransaction(Transaction transaction) {
|
||||
String hash = Hex.toHexString(transaction.getHash());
|
||||
logger.info("pending transaction removed with hash: {} ", hash);
|
||||
logger.info("pending transaction removed with hash: {} ", hash);
|
||||
walletTransactions.remove(hash);
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ public class Wallet {
|
||||
transactionMap.put(new ByteArrayWrapper(transaction.getHash()), transaction);
|
||||
|
||||
byte[] senderAddress = transaction.getSender();
|
||||
Account sender = rows.get(Hex.toHexString(senderAddress));
|
||||
Account sender = rows.get(Hex.toHexString(senderAddress));
|
||||
if (sender != null) {
|
||||
sender.addPendingTransaction(transaction);
|
||||
|
||||
@ -178,8 +178,8 @@ public class Wallet {
|
||||
}
|
||||
|
||||
byte[] receiveAddress = transaction.getReceiveAddress();
|
||||
if(receiveAddress != null) {
|
||||
Account receiver = rows.get(Hex.toHexString(receiveAddress));
|
||||
if (receiveAddress != null) {
|
||||
Account receiver = rows.get(Hex.toHexString(receiveAddress));
|
||||
if (receiver != null) {
|
||||
receiver.addPendingTransaction(transaction);
|
||||
|
||||
@ -195,7 +195,7 @@ public class Wallet {
|
||||
|
||||
public void processBlock(Block block) {
|
||||
|
||||
for (Account account : getAccountCollection()){
|
||||
for (Account account : getAccountCollection()) {
|
||||
account.clearAllPendingTransactions();
|
||||
}
|
||||
|
||||
@ -237,11 +237,11 @@ public class Wallet {
|
||||
|
||||
NodeList rowNodes = walletNode.getChildNodes();
|
||||
|
||||
for (int i = 0; i < rowNodes.getLength(); ++i ) {
|
||||
for (int i = 0; i < rowNodes.getLength(); ++i) {
|
||||
|
||||
Node rowNode = rowNodes.item(i);
|
||||
Node addrNode = rowNode.getChildNodes().item(0);
|
||||
Node privNode = rowNode.getChildNodes().item(1);
|
||||
Node rowNode = rowNodes.item(i);
|
||||
Node addrNode = rowNode.getChildNodes().item(0);
|
||||
Node privNode = rowNode.getChildNodes().item(1);
|
||||
Node valueNode = rowNode.getChildNodes().item(2);
|
||||
|
||||
// TODO: complete load func
|
||||
@ -287,11 +287,11 @@ public class Wallet {
|
||||
doc.appendChild(walletElement);
|
||||
|
||||
Attr high = doc.createAttribute("high");
|
||||
high.setValue(Long.toString( this.high ));
|
||||
high.setValue(Long.toString(this.high));
|
||||
walletElement.setAttributeNode(high);
|
||||
|
||||
int i = 0;
|
||||
for (Account account : getAccountCollection()) {
|
||||
for (Account account : getAccountCollection()) {
|
||||
|
||||
Element raw = doc.createElement("raw");
|
||||
Attr id = doc.createAttribute("id");
|
||||
@ -308,7 +308,7 @@ public class Wallet {
|
||||
Element privKey = doc.createElement("privkey");
|
||||
privKey.setTextContent(Hex.toHexString(account.getEcKey().getPrivKeyBytes()));
|
||||
|
||||
Element value = doc.createElement("value");
|
||||
Element value = doc.createElement("value");
|
||||
value.setTextContent(account.getBalance().toString());
|
||||
|
||||
raw.appendChild(addressE);
|
||||
@ -334,7 +334,7 @@ public class Wallet {
|
||||
listener.valueChanged();
|
||||
}
|
||||
|
||||
public interface WalletListener{
|
||||
public interface WalletListener {
|
||||
public void valueChanged();
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@ package org.ethereum.crypto;
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import static org.ethereum.util.ByteUtil.bigIntegerToBytes;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -66,12 +67,15 @@ import org.spongycastle.util.encoders.Hex;
|
||||
* can usually ignore the compressed/uncompressed distinction.</p>
|
||||
*
|
||||
* This code is borrowed from the bitcoinj project and altered to fit Ethereum.<br>
|
||||
* See <a href="https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/com/google/bitcoin/core/ECKey.java">bitcoinj on GitHub</a>
|
||||
* See <a href="https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/com/google/bitcoin/core/ECKey
|
||||
* .java">bitcoinj on GitHub</a>
|
||||
*/
|
||||
public class ECKey implements Serializable {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ECKey.class);
|
||||
|
||||
/** The parameters of the secp256k1 curve that Ethereum uses. */
|
||||
/**
|
||||
* The parameters of the secp256k1 curve that Ethereum uses.
|
||||
*/
|
||||
public static final ECDomainParameters CURVE;
|
||||
|
||||
/**
|
||||
@ -125,7 +129,7 @@ public class ECKey implements Serializable {
|
||||
|
||||
public ECKey(@Nullable BigInteger priv, ECPoint pub) {
|
||||
this.priv = priv;
|
||||
if(pub == null)
|
||||
if (pub == null)
|
||||
throw new IllegalArgumentException("Public key may not be null");
|
||||
this.pub = pub;
|
||||
}
|
||||
@ -234,7 +238,9 @@ public class ECKey implements Serializable {
|
||||
return point.getEncoded(compressed);
|
||||
}
|
||||
|
||||
/** Gets the hash160 form of the public key (as seen in addresses). */
|
||||
/**
|
||||
* Gets the hash160 form of the public key (as seen in addresses).
|
||||
*/
|
||||
public byte[] getAddress() {
|
||||
if (pubKeyHash == null) {
|
||||
byte[] pubBytes = this.pub.getEncoded(false);
|
||||
@ -251,7 +257,9 @@ public class ECKey implements Serializable {
|
||||
return pub.getEncoded();
|
||||
}
|
||||
|
||||
/** Gets the public key in the form of an elliptic curve point object from Bouncy Castle. */
|
||||
/**
|
||||
* Gets the public key in the form of an elliptic curve point object from Bouncy Castle.
|
||||
*/
|
||||
public ECPoint getPubKeyPoint() {
|
||||
return pub;
|
||||
}
|
||||
@ -300,7 +308,9 @@ public class ECKey implements Serializable {
|
||||
* components can be useful for doing further EC maths on them.
|
||||
*/
|
||||
public static class ECDSASignature {
|
||||
/** The two components of the signature. */
|
||||
/**
|
||||
* The two components of the signature.
|
||||
*/
|
||||
public final BigInteger r, s;
|
||||
public byte v;
|
||||
|
||||
@ -460,9 +470,9 @@ public class ECKey implements Serializable {
|
||||
* <p>When using native ECDSA verification, data must be 32 bytes, and no element may be
|
||||
* larger than 520 bytes.</p>
|
||||
*
|
||||
* @param data Hash of the data to verify.
|
||||
* @param data Hash of the data to verify.
|
||||
* @param signature signature.
|
||||
* @param pub The public key bytes to use.
|
||||
* @param pub The public key bytes to use.
|
||||
*/
|
||||
public static boolean verify(byte[] data, ECDSASignature signature, byte[] pub) {
|
||||
ECDSASigner signer = new ECDSASigner();
|
||||
@ -481,9 +491,9 @@ public class ECKey implements Serializable {
|
||||
/**
|
||||
* Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key.
|
||||
*
|
||||
* @param data Hash of the data to verify.
|
||||
* @param data Hash of the data to verify.
|
||||
* @param signature signature.
|
||||
* @param pub The public key bytes to use.
|
||||
* @param pub The public key bytes to use.
|
||||
*/
|
||||
public static boolean verify(byte[] data, byte[] signature, byte[] pub) {
|
||||
return verify(data, signature, pub);
|
||||
@ -492,7 +502,7 @@ public class ECKey implements Serializable {
|
||||
/**
|
||||
* Verifies the given ASN.1 encoded ECDSA signature against a hash using the public key.
|
||||
*
|
||||
* @param data Hash of the data to verify.
|
||||
* @param data Hash of the data to verify.
|
||||
* @param signature signature.
|
||||
*/
|
||||
public boolean verify(byte[] data, byte[] signature) {
|
||||
@ -601,11 +611,13 @@ public class ECKey implements Serializable {
|
||||
return ECKey.fromPublicOnly(q.getEncoded(compressed));
|
||||
}
|
||||
|
||||
/** Decompress a compressed public key (x co-ord and low-bit of y-coord). */
|
||||
/**
|
||||
* Decompress a compressed public key (x co-ord and low-bit of y-coord).
|
||||
*/
|
||||
private static ECPoint decompressKey(BigInteger xBN, boolean yBit) {
|
||||
X9IntegerConverter x9 = new X9IntegerConverter();
|
||||
byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve()));
|
||||
compEnc[0] = (byte)(yBit ? 0x03 : 0x02);
|
||||
compEnc[0] = (byte) (yBit ? 0x03 : 0x02);
|
||||
return CURVE.getCurve().decodePoint(compEnc);
|
||||
}
|
||||
|
||||
@ -643,6 +655,6 @@ public class ECKey implements Serializable {
|
||||
}
|
||||
|
||||
private static void check(boolean test, String message) {
|
||||
if(!test) throw new IllegalArgumentException(message);
|
||||
if (!test) throw new IllegalArgumentException(message);
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class HashUtil {
|
||||
public static byte[] sha3(byte[] input) {
|
||||
ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input);
|
||||
byte[] result = sha3Cache.get(inputByteArray);
|
||||
if(result != null)
|
||||
if (result != null)
|
||||
return result;
|
||||
result = SHA3Helper.sha3(input);
|
||||
sha3Cache.put(inputByteArray, result);
|
||||
@ -71,7 +71,7 @@ public class HashUtil {
|
||||
/**
|
||||
* The way to calculate new address inside ethereum
|
||||
*
|
||||
* @param addr - creating addres
|
||||
* @param addr - creating addres
|
||||
* @param nonce - nonce of creating address
|
||||
* @return new address
|
||||
*/
|
||||
|
@ -20,7 +20,7 @@ import java.util.List;
|
||||
* Created on: 12/11/2014 17:16
|
||||
*/
|
||||
@Repository
|
||||
@Transactional(propagation= Propagation.SUPPORTS)
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public class BlockStore {
|
||||
|
||||
@Autowired
|
||||
@ -35,10 +35,10 @@ public class BlockStore {
|
||||
|
||||
List result = sessionFactory.getCurrentSession().
|
||||
createQuery("from BlockVO where number = :number").
|
||||
setParameter("number", blockNumber).list();
|
||||
setParameter("number", blockNumber).list();
|
||||
|
||||
if (result.size() == 0) return null;
|
||||
BlockVO vo = (BlockVO)result.get(0);
|
||||
BlockVO vo = (BlockVO) result.get(0);
|
||||
|
||||
return new Block(vo.rlp);
|
||||
}
|
||||
@ -51,7 +51,7 @@ public class BlockStore {
|
||||
setParameter("hash", hash).list();
|
||||
|
||||
if (result.size() == 0) return null;
|
||||
BlockVO vo = (BlockVO)result.get(0);
|
||||
BlockVO vo = (BlockVO) result.get(0);
|
||||
|
||||
return new Block(vo.rlp);
|
||||
}
|
||||
@ -72,7 +72,7 @@ public class BlockStore {
|
||||
setParameter("limit", block.getNumber() - qty).
|
||||
setMaxResults(qty).list();
|
||||
|
||||
for (byte[] h : result){
|
||||
for (byte[] h : result) {
|
||||
hashes.add(h);
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ public class BlockStore {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteBlocksSince(long number){
|
||||
public void deleteBlocksSince(long number) {
|
||||
|
||||
sessionFactory.getCurrentSession().
|
||||
createQuery("delete from BlockVO where number > :number").
|
||||
@ -92,10 +92,10 @@ public class BlockStore {
|
||||
@Transactional
|
||||
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
|
||||
|
||||
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(),
|
||||
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(),
|
||||
block.getEncoded(), block.getCumulativeDifficulty());
|
||||
|
||||
for (TransactionReceipt receipt : receipts){
|
||||
for (TransactionReceipt receipt : receipts) {
|
||||
|
||||
byte[] hash = receipt.getTransaction().getHash();
|
||||
byte[] rlp = receipt.getEncoded();
|
||||
@ -108,9 +108,9 @@ public class BlockStore {
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public BigInteger getTotalDifficultySince(long number){
|
||||
public BigInteger getTotalDifficultySince(long number) {
|
||||
|
||||
BigInteger result = (BigInteger)sessionFactory.getCurrentSession().
|
||||
BigInteger result = (BigInteger) sessionFactory.getCurrentSession().
|
||||
createQuery("select sum(cummulativeDifficulty) from BlockVO where number > :number").
|
||||
setParameter("number", number).
|
||||
uniqueResult();
|
||||
@ -120,9 +120,9 @@ public class BlockStore {
|
||||
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public BigInteger getTotalDifficulty(){
|
||||
public BigInteger getTotalDifficulty() {
|
||||
|
||||
BigInteger result = (BigInteger)sessionFactory.getCurrentSession().
|
||||
BigInteger result = (BigInteger) sessionFactory.getCurrentSession().
|
||||
createQuery("select sum(cummulativeDifficulty) from BlockVO").uniqueResult();
|
||||
|
||||
return result;
|
||||
@ -130,15 +130,15 @@ public class BlockStore {
|
||||
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public Block getBestBlock(){
|
||||
public Block getBestBlock() {
|
||||
|
||||
Long bestNumber = (Long)
|
||||
sessionFactory.getCurrentSession().createQuery("select max(number) from BlockVO").uniqueResult();
|
||||
List result = sessionFactory.getCurrentSession().
|
||||
createQuery("from BlockVO where number = :number").setParameter("number", bestNumber) .list();
|
||||
createQuery("from BlockVO where number = :number").setParameter("number", bestNumber).list();
|
||||
|
||||
if (result.isEmpty()) return null;
|
||||
BlockVO vo = (BlockVO)result.get(0);
|
||||
BlockVO vo = (BlockVO) result.get(0);
|
||||
|
||||
return new Block(vo.rlp);
|
||||
}
|
||||
@ -151,7 +151,7 @@ public class BlockStore {
|
||||
createQuery("from BlockVO").list();
|
||||
|
||||
ArrayList<Block> blocks = new ArrayList<>();
|
||||
for (BlockVO blockVO : (List<BlockVO>)result){
|
||||
for (BlockVO blockVO : (List<BlockVO>) result) {
|
||||
blocks.add(new Block(blockVO.getRlp()));
|
||||
}
|
||||
|
||||
@ -161,7 +161,7 @@ public class BlockStore {
|
||||
@Transactional
|
||||
public void reset() {
|
||||
sessionFactory.getCurrentSession().
|
||||
createQuery("delete from BlockVO").executeUpdate();
|
||||
createQuery("delete from BlockVO").executeUpdate();
|
||||
}
|
||||
|
||||
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
|
||||
@ -171,7 +171,7 @@ public class BlockStore {
|
||||
setParameter("hash", hash).list();
|
||||
|
||||
if (result.size() == 0) return null;
|
||||
TransactionReceiptVO vo = (TransactionReceiptVO)result.get(0);
|
||||
TransactionReceiptVO vo = (TransactionReceiptVO) result.get(0);
|
||||
|
||||
return new TransactionReceipt(vo.rlp);
|
||||
|
||||
|
@ -19,7 +19,7 @@ public class BlockVO {
|
||||
@Id
|
||||
byte[] hash;
|
||||
|
||||
Long number;
|
||||
Long number;
|
||||
|
||||
@Lob
|
||||
byte[] rlp;
|
||||
@ -31,8 +31,8 @@ public class BlockVO {
|
||||
|
||||
public BlockVO(Long number, byte[] hash, byte[] rlp, BigInteger cummulativeDifficulty) {
|
||||
this.number = number;
|
||||
this.hash = hash;
|
||||
this.rlp = rlp;
|
||||
this.hash = hash;
|
||||
this.rlp = rlp;
|
||||
this.cummulativeDifficulty = cummulativeDifficulty;
|
||||
}
|
||||
|
||||
|
@ -20,12 +20,12 @@ public class ContractDetails {
|
||||
|
||||
private byte[] rlpEncoded;
|
||||
|
||||
private List<DataWord> storageKeys = new ArrayList<>();
|
||||
private List<DataWord> storageKeys = new ArrayList<>();
|
||||
private List<DataWord> storageValues = new ArrayList<>();
|
||||
|
||||
private byte[] code = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
private boolean dirty = false;
|
||||
private boolean dirty = false;
|
||||
private boolean deleted = false;
|
||||
|
||||
private Trie storageTrie = new TrieImpl(null);
|
||||
@ -75,8 +75,7 @@ public class ContractDetails {
|
||||
if (foundIndex != -1) {
|
||||
DataWord value = storageValues.get(foundIndex);
|
||||
return value.clone();
|
||||
}
|
||||
else
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -94,7 +93,7 @@ public class ContractDetails {
|
||||
|
||||
storageTrie = new TrieImpl(null);
|
||||
// calc the trie for root hash
|
||||
for (int i = 0; i < storageKeys.size(); ++i){
|
||||
for (int i = 0; i < storageKeys.size(); ++i) {
|
||||
storageTrie.update(storageKeys.get(i).getData(), RLP
|
||||
.encodeElement(storageValues.get(i).getNoLeadZeroesData()));
|
||||
}
|
||||
@ -197,7 +196,7 @@ public class ContractDetails {
|
||||
keys.addAll(storageKeys);
|
||||
|
||||
List<DataWord> values = new ArrayList<>();
|
||||
for (DataWord key : keys){
|
||||
for (DataWord key : keys) {
|
||||
|
||||
DataWord value = storage.get(key);
|
||||
values.add(value);
|
||||
@ -208,18 +207,17 @@ public class ContractDetails {
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ContractDetails clone(){
|
||||
public ContractDetails clone() {
|
||||
|
||||
ContractDetails contractDetails = new ContractDetails();
|
||||
|
||||
contractDetails.setCode(this.getCode());
|
||||
contractDetails.setStorage(new ArrayList<DataWord>(this.storageKeys) ,
|
||||
new ArrayList<DataWord>(this.storageValues));
|
||||
contractDetails.setStorage(new ArrayList<DataWord>(this.storageKeys),
|
||||
new ArrayList<DataWord>(this.storageValues));
|
||||
return contractDetails;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
|
||||
String ret = " Code: " + Hex.toHexString(code) + "\n";
|
||||
ret += " Storage: " + getStorage().toString();
|
||||
|
@ -18,12 +18,12 @@ import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* Generic interface for Ethereum database
|
||||
* Generic interface for Ethereum database
|
||||
*
|
||||
* LevelDB key/value pair DB implementation will be used.
|
||||
* Choice must be made between:
|
||||
* Pure Java: https://github.com/dain/leveldb
|
||||
* JNI binding: https://github.com/fusesource/leveldbjni
|
||||
* LevelDB key/value pair DB implementation will be used.
|
||||
* Choice must be made between:
|
||||
* Pure Java: https://github.com/dain/leveldb
|
||||
* JNI binding: https://github.com/fusesource/leveldbjni
|
||||
*/
|
||||
public class DatabaseImpl implements Database {
|
||||
|
||||
@ -40,10 +40,10 @@ public class DatabaseImpl implements Database {
|
||||
try {
|
||||
logger.debug("Opening database");
|
||||
File dbLocation = new File(System.getProperty("user.dir") + "/" +
|
||||
SystemProperties.CONFIG.databaseDir() + "/");
|
||||
SystemProperties.CONFIG.databaseDir() + "/");
|
||||
File fileLocation = new File(dbLocation, name);
|
||||
|
||||
if(SystemProperties.CONFIG.databaseReset()) {
|
||||
if (SystemProperties.CONFIG.databaseReset()) {
|
||||
destroyDB(fileLocation);
|
||||
}
|
||||
|
||||
@ -53,13 +53,13 @@ public class DatabaseImpl implements Database {
|
||||
// String stats = DATABASE.getProperty("leveldb.stats");
|
||||
// logger.debug(stats);
|
||||
|
||||
if (logger.isTraceEnabled()){
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
||||
logger.trace("Dump for: {}", fileLocation.toString());
|
||||
DBIterator iter = db.iterator();
|
||||
DBIterator iter = db.iterator();
|
||||
|
||||
while(iter.hasNext()){
|
||||
byte[] key = iter.peekNext().getKey();
|
||||
while (iter.hasNext()) {
|
||||
byte[] key = iter.peekNext().getKey();
|
||||
byte[] value = iter.peekNext().getValue();
|
||||
|
||||
logger.trace("key={}, value={}", Hex.toHexString(key), Hex.toHexString(value));
|
||||
@ -90,7 +90,7 @@ public class DatabaseImpl implements Database {
|
||||
@Override
|
||||
public void put(byte[] key, byte[] value) {
|
||||
|
||||
if(logger.isDebugEnabled())
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("put: key: [{}], value: [{}]",
|
||||
Hex.toHexString(key),
|
||||
Hex.toHexString(value));
|
||||
@ -99,7 +99,7 @@ public class DatabaseImpl implements Database {
|
||||
|
||||
@Override
|
||||
public void delete(byte[] key) {
|
||||
if(logger.isDebugEnabled())
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("delete: key: [{}]");
|
||||
|
||||
db.delete(key);
|
||||
|
@ -41,7 +41,7 @@ public class RepositoryDummy implements Repository {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("repository");
|
||||
private Map<ByteArrayWrapper, AccountState> worldState = new HashMap<>();
|
||||
private Map<ByteArrayWrapper, ContractDetails> detailsDB = new HashMap<>() ;
|
||||
private Map<ByteArrayWrapper, ContractDetails> detailsDB = new HashMap<>();
|
||||
|
||||
|
||||
@Override
|
||||
@ -53,12 +53,12 @@ public class RepositoryDummy implements Repository {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClosed() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@ -71,21 +71,21 @@ public class RepositoryDummy implements Repository {
|
||||
AccountState accountState = stateCache.get(hash);
|
||||
ContractDetails contractDetails = detailsCache.get(hash);
|
||||
|
||||
if (accountState.isDeleted()){
|
||||
worldState.remove( hash ) ;
|
||||
detailsDB.remove( hash );
|
||||
if (accountState.isDeleted()) {
|
||||
worldState.remove(hash);
|
||||
detailsDB.remove(hash);
|
||||
|
||||
logger.debug("delete: [{}]",
|
||||
Hex.toHexString(hash.getData()));
|
||||
|
||||
} else{
|
||||
} else {
|
||||
|
||||
if (accountState.isDirty() || contractDetails.isDirty()){
|
||||
detailsDB.put( hash, contractDetails);
|
||||
if (accountState.isDirty() || contractDetails.isDirty()) {
|
||||
detailsDB.put(hash, contractDetails);
|
||||
accountState.setStateRoot(contractDetails.getStorageHash());
|
||||
accountState.setCodeHash(sha3(contractDetails.getCode()));
|
||||
worldState.put( hash, accountState);
|
||||
if (logger.isDebugEnabled()){
|
||||
worldState.put(hash, accountState);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("update: [{}],nonce: [{}] balance: [{}] \n [{}]",
|
||||
Hex.toHexString(hash.getData()),
|
||||
accountState.getNonce(),
|
||||
@ -106,23 +106,23 @@ public class RepositoryDummy implements Repository {
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void syncToRoot(byte[] root) {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -140,7 +140,7 @@ public class RepositoryDummy implements Repository {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<ByteArrayWrapper> getFullAddressSet(){
|
||||
public Set<ByteArrayWrapper> getFullAddressSet() {
|
||||
return worldState.keySet();
|
||||
}
|
||||
|
||||
@ -170,7 +170,7 @@ public class RepositoryDummy implements Repository {
|
||||
|
||||
@Override
|
||||
public DataWord getStorageValue(byte[] addr, DataWord key) {
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null)
|
||||
return null;
|
||||
@ -180,11 +180,11 @@ public class RepositoryDummy implements Repository {
|
||||
|
||||
@Override
|
||||
public void addStorageRow(byte[] addr, DataWord key, DataWord value) {
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null){
|
||||
if (details == null) {
|
||||
createAccount(addr);
|
||||
details = getContractDetails(addr);
|
||||
details = getContractDetails(addr);
|
||||
}
|
||||
|
||||
details.put(key, value);
|
||||
@ -193,7 +193,7 @@ public class RepositoryDummy implements Repository {
|
||||
|
||||
@Override
|
||||
public byte[] getCode(byte[] addr) {
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null)
|
||||
return null;
|
||||
@ -204,15 +204,15 @@ public class RepositoryDummy implements Repository {
|
||||
|
||||
@Override
|
||||
public void saveCode(byte[] addr, byte[] code) {
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null){
|
||||
if (details == null) {
|
||||
createAccount(addr);
|
||||
details = getContractDetails(addr);
|
||||
details = getContractDetails(addr);
|
||||
}
|
||||
|
||||
details.setCode(code);
|
||||
detailsDB.put(wrap( addr ), details);
|
||||
detailsDB.put(wrap(addr), details);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -295,8 +295,8 @@ public class RepositoryDummy implements Repository {
|
||||
@Override
|
||||
public void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts, HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) {
|
||||
|
||||
AccountState account = getAccountState(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
AccountState account = getAccountState(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (account == null)
|
||||
account = new AccountState();
|
||||
|
@ -43,37 +43,37 @@ public class RepositoryImpl implements Repository {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("repository");
|
||||
|
||||
private Trie worldState;
|
||||
private Trie worldState;
|
||||
|
||||
private DatabaseImpl detailsDB = null;
|
||||
private DatabaseImpl stateDB = null;
|
||||
private DatabaseImpl detailsDB = null;
|
||||
private DatabaseImpl stateDB = null;
|
||||
|
||||
public RepositoryImpl() {
|
||||
this(DETAILS_DB, STATE_DB);
|
||||
}
|
||||
|
||||
public RepositoryImpl(String detailsDbName, String stateDbName) {
|
||||
detailsDB = new DatabaseImpl(detailsDbName);
|
||||
stateDB = new DatabaseImpl(stateDbName);
|
||||
worldState = new TrieImpl(stateDB.getDb());
|
||||
detailsDB = new DatabaseImpl(detailsDbName);
|
||||
stateDB = new DatabaseImpl(stateDbName);
|
||||
worldState = new TrieImpl(stateDB.getDb());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
close();
|
||||
detailsDB = new DatabaseImpl(DETAILS_DB);
|
||||
stateDB = new DatabaseImpl(STATE_DB);
|
||||
worldState = new TrieImpl(stateDB.getDb());
|
||||
detailsDB = new DatabaseImpl(DETAILS_DB);
|
||||
stateDB = new DatabaseImpl(STATE_DB);
|
||||
worldState = new TrieImpl(stateDB.getDb());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (this.detailsDB != null){
|
||||
if (this.detailsDB != null) {
|
||||
detailsDB.close();
|
||||
detailsDB = null;
|
||||
}
|
||||
if (this.stateDB != null){
|
||||
if (this.stateDB != null) {
|
||||
stateDB.close();
|
||||
stateDB = null;
|
||||
}
|
||||
@ -93,21 +93,21 @@ public class RepositoryImpl implements Repository {
|
||||
AccountState accountState = stateCache.get(hash);
|
||||
ContractDetails contractDetails = detailsCache.get(hash);
|
||||
|
||||
if (accountState.isDeleted()){
|
||||
if (accountState.isDeleted()) {
|
||||
worldState.delete(hash.getData());
|
||||
detailsDB.delete(hash.getData());
|
||||
|
||||
logger.debug("delete: [{}]",
|
||||
Hex.toHexString(hash.getData()));
|
||||
|
||||
} else{
|
||||
} else {
|
||||
|
||||
if (accountState.isDirty() || contractDetails.isDirty()){
|
||||
if (accountState.isDirty() || 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()){
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("update: [{}],nonce: [{}] balance: [{}] \n [{}]",
|
||||
Hex.toHexString(hash.getData()),
|
||||
accountState.getNonce(),
|
||||
@ -126,7 +126,7 @@ public class RepositoryImpl implements Repository {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush(){
|
||||
public void flush() {
|
||||
logger.info("flush to disk");
|
||||
worldState.sync();
|
||||
}
|
||||
@ -134,12 +134,12 @@ public class RepositoryImpl implements Repository {
|
||||
|
||||
@Override
|
||||
public void rollback() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void commit() {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -164,7 +164,9 @@ public class RepositoryImpl implements Repository {
|
||||
if (block.getNumber() == 0 && txNumber == 0)
|
||||
if (CONFIG.dumpCleanOnRestart()) {
|
||||
try {
|
||||
FileUtils.deleteDirectory(CONFIG.dumpDir());} catch (IOException e) {}
|
||||
FileUtils.deleteDirectory(CONFIG.dumpDir());
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
|
||||
String dir = CONFIG.dumpDir() + "/";
|
||||
@ -212,7 +214,7 @@ public class RepositoryImpl implements Repository {
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpTrie(Block block){
|
||||
public void dumpTrie(Block block) {
|
||||
|
||||
if (!(CONFIG.dumpFull() || CONFIG.dumpBlock() == block.getNumber()))
|
||||
return;
|
||||
@ -239,9 +241,11 @@ public class RepositoryImpl implements Repository {
|
||||
logger.error(e.getMessage(), e);
|
||||
} finally {
|
||||
try {
|
||||
if (bw != null)bw.close();
|
||||
if (fw != null)fw.close();
|
||||
} catch (IOException e) {e.printStackTrace();}
|
||||
if (bw != null) bw.close();
|
||||
if (fw != null) fw.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,7 +283,7 @@ public class RepositoryImpl implements Repository {
|
||||
@Override
|
||||
public DataWord getStorageValue(byte[] addr, DataWord key) {
|
||||
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null)
|
||||
return null;
|
||||
@ -290,11 +294,11 @@ public class RepositoryImpl implements Repository {
|
||||
@Override
|
||||
public void addStorageRow(byte[] addr, DataWord key, DataWord value) {
|
||||
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null){
|
||||
if (details == null) {
|
||||
createAccount(addr);
|
||||
details = getContractDetails(addr);
|
||||
details = getContractDetails(addr);
|
||||
}
|
||||
|
||||
details.put(key, value);
|
||||
@ -304,7 +308,7 @@ public class RepositoryImpl implements Repository {
|
||||
@Override
|
||||
public byte[] getCode(byte[] addr) {
|
||||
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null)
|
||||
return null;
|
||||
@ -314,11 +318,11 @@ public class RepositoryImpl implements Repository {
|
||||
|
||||
@Override
|
||||
public void saveCode(byte[] addr, byte[] code) {
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (details == null){
|
||||
if (details == null) {
|
||||
createAccount(addr);
|
||||
details = getContractDetails(addr);
|
||||
details = getContractDetails(addr);
|
||||
}
|
||||
|
||||
details.setCode(code);
|
||||
@ -365,8 +369,6 @@ public class RepositoryImpl implements Repository {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void delete(byte[] addr) {
|
||||
worldState.delete(addr);
|
||||
@ -419,8 +421,8 @@ public class RepositoryImpl implements Repository {
|
||||
HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
|
||||
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) {
|
||||
|
||||
AccountState account = getAccountState(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
AccountState account = getAccountState(addr);
|
||||
ContractDetails details = getContractDetails(addr);
|
||||
|
||||
if (account == null)
|
||||
account = new AccountState();
|
||||
|
@ -27,12 +27,12 @@ public class RepositoryTrack implements Repository {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("repository");
|
||||
|
||||
HashMap<ByteArrayWrapper, AccountState> cacheAccounts = new HashMap<>();
|
||||
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails = new HashMap<>();
|
||||
HashMap<ByteArrayWrapper, AccountState> cacheAccounts = new HashMap<>();
|
||||
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails = new HashMap<>();
|
||||
|
||||
Repository repository;
|
||||
|
||||
public RepositoryTrack(){
|
||||
public RepositoryTrack() {
|
||||
this.repository = new RepositoryDummy();
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ public class RepositoryTrack implements Repository {
|
||||
@Override
|
||||
public AccountState createAccount(byte[] addr) {
|
||||
|
||||
logger.trace("createAccount: [{}]", Hex.toHexString(addr)) ;
|
||||
logger.trace("createAccount: [{}]", Hex.toHexString(addr));
|
||||
|
||||
AccountState accountState = new AccountState();
|
||||
cacheAccounts.put(wrap(addr), accountState);
|
||||
@ -59,7 +59,7 @@ public class RepositoryTrack implements Repository {
|
||||
|
||||
AccountState accountState = cacheAccounts.get(wrap(addr));
|
||||
|
||||
if (accountState == null){
|
||||
if (accountState == null) {
|
||||
repository.loadAccount(addr, cacheAccounts, cacheDetails);
|
||||
accountState = cacheAccounts.get(wrap(addr));
|
||||
}
|
||||
@ -83,7 +83,7 @@ public class RepositoryTrack implements Repository {
|
||||
|
||||
ContractDetails contractDetails = cacheDetails.get(wrap(addr));
|
||||
|
||||
if (contractDetails == null){
|
||||
if (contractDetails == null) {
|
||||
repository.loadAccount(addr, cacheAccounts, cacheDetails);
|
||||
contractDetails = cacheDetails.get(wrap(addr));
|
||||
}
|
||||
@ -93,12 +93,12 @@ public class RepositoryTrack implements Repository {
|
||||
|
||||
@Override
|
||||
public void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
|
||||
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails){
|
||||
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) {
|
||||
|
||||
AccountState accountState = this.cacheAccounts.get(wrap(addr));
|
||||
AccountState accountState = this.cacheAccounts.get(wrap(addr));
|
||||
ContractDetails contractDetails = this.cacheDetails.get(wrap(addr));
|
||||
|
||||
if (accountState == null){
|
||||
if (accountState == null) {
|
||||
repository.loadAccount(addr, cacheAccounts, cacheDetails);
|
||||
} else {
|
||||
cacheAccounts.put(wrap(addr), accountState.clone());
|
||||
@ -110,7 +110,7 @@ public class RepositoryTrack implements Repository {
|
||||
@Override
|
||||
public void delete(byte[] addr) {
|
||||
|
||||
logger.trace("delete account: [{}]", Hex.toHexString(addr)) ;
|
||||
logger.trace("delete account: [{}]", Hex.toHexString(addr));
|
||||
getAccountState(addr).setDeleted(true);
|
||||
getContractDetails(addr).setDeleted(true);
|
||||
}
|
||||
@ -165,7 +165,7 @@ public class RepositoryTrack implements Repository {
|
||||
public BigInteger addBalance(byte[] addr, BigInteger value) {
|
||||
|
||||
AccountState accountState = getAccountState(addr);
|
||||
if (accountState == null){
|
||||
if (accountState == null) {
|
||||
accountState = createAccount(addr);
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ public class RepositoryTrack implements Repository {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Set<ByteArrayWrapper> getFullAddressSet(){
|
||||
public Set<ByteArrayWrapper> getFullAddressSet() {
|
||||
return cacheAccounts.keySet();
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ public class RepositoryTrack implements Repository {
|
||||
|
||||
|
||||
@Override
|
||||
public void flush(){
|
||||
public void flush() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@ -256,14 +256,14 @@ public class RepositoryTrack implements Repository {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBatch(HashMap<ByteArrayWrapper, AccountState> accountStates,
|
||||
HashMap<ByteArrayWrapper, ContractDetails> contractDetailes){
|
||||
public void updateBatch(HashMap<ByteArrayWrapper, AccountState> accountStates,
|
||||
HashMap<ByteArrayWrapper, ContractDetails> contractDetailes) {
|
||||
|
||||
for (ByteArrayWrapper hash : accountStates.keySet()){
|
||||
for (ByteArrayWrapper hash : accountStates.keySet()) {
|
||||
cacheAccounts.put(hash, accountStates.get(hash));
|
||||
}
|
||||
|
||||
for (ByteArrayWrapper hash : contractDetailes.keySet()){
|
||||
for (ByteArrayWrapper hash : contractDetailes.keySet()) {
|
||||
cacheDetails.put(hash, contractDetailes.get(hash));
|
||||
}
|
||||
}
|
||||
|
@ -30,10 +30,10 @@ public class TrackDatabase implements Database {
|
||||
}
|
||||
|
||||
public void commitTrack() {
|
||||
for(ByteArrayWrapper key : changes.keySet()) {
|
||||
for (ByteArrayWrapper key : changes.keySet()) {
|
||||
db.put(key.getData(), changes.get(key));
|
||||
}
|
||||
for(ByteArrayWrapper key : deletes) {
|
||||
for (ByteArrayWrapper key : deletes) {
|
||||
db.delete(key.getData());
|
||||
}
|
||||
changes = null;
|
||||
@ -57,7 +57,7 @@ public class TrackDatabase implements Database {
|
||||
}
|
||||
|
||||
public byte[] get(byte[] key) {
|
||||
if(trackingChanges) {
|
||||
if (trackingChanges) {
|
||||
ByteArrayWrapper wKey = new ByteArrayWrapper(key);
|
||||
if (deletes.contains(wKey)) return null;
|
||||
if (changes.get(wKey) != null) return changes.get(wKey);
|
||||
@ -65,7 +65,9 @@ public class TrackDatabase implements Database {
|
||||
return db.get(key);
|
||||
}
|
||||
|
||||
/** Delete object (key) from db **/
|
||||
/**
|
||||
* Delete object (key) from db *
|
||||
*/
|
||||
public void delete(byte[] key) {
|
||||
if (trackingChanges) {
|
||||
ByteArrayWrapper wKey = new ByteArrayWrapper(key);
|
||||
@ -76,7 +78,7 @@ public class TrackDatabase implements Database {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(){
|
||||
public void close() {
|
||||
db.close();
|
||||
}
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ public class TransactionReceiptVO {
|
||||
}
|
||||
|
||||
public TransactionReceiptVO(byte[] hash, byte[] rlp) {
|
||||
this.hash = hash;
|
||||
this.rlp = rlp;
|
||||
this.hash = hash;
|
||||
this.rlp = rlp;
|
||||
}
|
||||
|
||||
public byte[] getHash() {
|
||||
|
@ -11,30 +11,47 @@ import org.ethereum.db.ByteArrayWrapper;
|
||||
import org.ethereum.net.BlockQueue;
|
||||
import org.ethereum.core.Genesis;
|
||||
|
||||
public interface Blockchain {
|
||||
public interface Blockchain {
|
||||
|
||||
public static final byte[] GENESIS_HASH = Genesis.getInstance().getHash();
|
||||
|
||||
public long getSize();
|
||||
|
||||
public void add(Block block);
|
||||
|
||||
public void tryToConnect(Block block);
|
||||
|
||||
public void storeBlock(Block block, List<TransactionReceipt> receipts);
|
||||
|
||||
public Block getBlockByNumber(long blockNr);
|
||||
|
||||
public void setBestBlock(Block block);
|
||||
|
||||
public Block getBestBlock();
|
||||
|
||||
public BlockQueue getQueue();
|
||||
|
||||
public boolean hasParentOnTheChain(Block block);
|
||||
|
||||
public void reset();
|
||||
|
||||
public void close();
|
||||
|
||||
public void updateTotalDifficulty(Block block);
|
||||
|
||||
public BigInteger getTotalDifficulty();
|
||||
|
||||
public void setTotalDifficulty(BigInteger totalDifficulty);
|
||||
|
||||
public byte[] getBestBlockHash();
|
||||
|
||||
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty);
|
||||
|
||||
TransactionReceipt getTransactionReceiptByHash(byte[] hash);
|
||||
|
||||
public Block getBlockByHash(byte[] hash);
|
||||
|
||||
public List<Chain> getAltChains();
|
||||
|
||||
public List<Block> getGarbage();
|
||||
}
|
||||
|
@ -24,10 +24,11 @@ public interface Ethereum {
|
||||
|
||||
/**
|
||||
* Find a peer but not this one
|
||||
*
|
||||
* @param excludePeer - peer to exclude
|
||||
* @return online peer if available otherwise null
|
||||
*/
|
||||
public PeerInfo findOnlinePeer(PeerInfo excludePeer) ;
|
||||
public PeerInfo findOnlinePeer(PeerInfo excludePeer);
|
||||
|
||||
/**
|
||||
* Find an online peer but not from excluded list
|
||||
@ -35,7 +36,7 @@ public interface Ethereum {
|
||||
* @param excludePeerSet - peers to exclude
|
||||
* @return online peer if available otherwise null
|
||||
*/
|
||||
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeerSet) ;
|
||||
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeerSet);
|
||||
|
||||
/**
|
||||
* @return online peer if available
|
||||
@ -64,9 +65,11 @@ public interface Ethereum {
|
||||
public Set<PeerInfo> getPeers();
|
||||
|
||||
public void startPeerDiscovery();
|
||||
|
||||
public void stopPeerDiscovery();
|
||||
|
||||
public void connect(InetAddress addr, int port);
|
||||
|
||||
public void connect(String ip, int port);
|
||||
|
||||
public Blockchain getBlockchain();
|
||||
|
@ -61,7 +61,7 @@ public class EthereumFactory {
|
||||
|
||||
|
||||
@Bean
|
||||
public DataSourceTransactionManager transactionManager(){
|
||||
public DataSourceTransactionManager transactionManager() {
|
||||
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
|
||||
dataSourceTransactionManager.setDataSource(dataSource());
|
||||
|
||||
@ -69,18 +69,18 @@ public class EthereumFactory {
|
||||
}
|
||||
|
||||
@Bean(name = "dataSource")
|
||||
public DriverManagerDataSource dataSource(){
|
||||
public DriverManagerDataSource dataSource() {
|
||||
|
||||
logger.info("Connecting to the block store");
|
||||
|
||||
System.setProperty("hsqldb.reconfig_logging", "false");
|
||||
|
||||
String url =
|
||||
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
|
||||
"create=%s;hsqldb.default_table_type=cached",
|
||||
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
|
||||
"create=%s;hsqldb.default_table_type=cached",
|
||||
|
||||
SystemProperties.CONFIG.databaseDir(),
|
||||
SystemProperties.CONFIG.databaseReset());
|
||||
SystemProperties.CONFIG.databaseDir(),
|
||||
SystemProperties.CONFIG.databaseReset());
|
||||
|
||||
DriverManagerDataSource ds = new DriverManagerDataSource();
|
||||
ds.setDriverClassName("org.hsqldb.jdbcDriver");
|
||||
@ -99,12 +99,12 @@ public class EthereumFactory {
|
||||
private static EthereumFactory factory;
|
||||
|
||||
|
||||
public static Ethereum createEthereum(){
|
||||
public static Ethereum createEthereum() {
|
||||
|
||||
logger.info("capability eth version: [{}]", EthHandler.VERSION);
|
||||
logger.info("capability shh version: [{}]", ShhHandler.VERSION);
|
||||
|
||||
if (context == null){
|
||||
if (context == null) {
|
||||
context = new AnnotationConfigApplicationContext(EthereumFactory.class);
|
||||
factory = context.getBean(EthereumFactory.class);
|
||||
}
|
||||
|
@ -60,19 +60,22 @@ public class EthereumImpl implements Ethereum {
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init(){
|
||||
public void init() {
|
||||
worldManager.loadBlockchain();
|
||||
if (CONFIG.listenPort() > 0){
|
||||
if (CONFIG.listenPort() > 0) {
|
||||
Executors.newSingleThreadExecutor().submit(
|
||||
new Runnable() { public void run() {
|
||||
peerServer.start(CONFIG.listenPort());
|
||||
}}
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
peerServer.start(CONFIG.listenPort());
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a peer but not this one
|
||||
*
|
||||
* @param peer - peer to exclude
|
||||
* @return online peer
|
||||
*/
|
||||
@ -90,7 +93,7 @@ public class EthereumImpl implements Ethereum {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeers) {
|
||||
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeers) {
|
||||
logger.info("Looking for online peers...");
|
||||
|
||||
final EthereumListener listener = worldManager.getListener();
|
||||
@ -132,7 +135,7 @@ public class EthereumImpl implements Ethereum {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPeerDiscovery(){
|
||||
public void startPeerDiscovery() {
|
||||
worldManager.startPeerDiscovery();
|
||||
}
|
||||
|
||||
@ -179,10 +182,10 @@ public class EthereumImpl implements Ethereum {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PeerClient getDefaultPeer(){
|
||||
public PeerClient getDefaultPeer() {
|
||||
|
||||
PeerClient peer = worldManager.getActivePeer();
|
||||
if (peer == null){
|
||||
if (peer == null) {
|
||||
|
||||
peer = new PeerClient();
|
||||
worldManager.setActivePeer(peer);
|
||||
@ -200,12 +203,12 @@ public class EthereumImpl implements Ethereum {
|
||||
BigInteger gasPrice,
|
||||
BigInteger gas,
|
||||
byte[] recieveAddress,
|
||||
BigInteger value, byte[] data ){
|
||||
BigInteger value, byte[] data) {
|
||||
|
||||
byte[] nonceBytes = ByteUtil.bigIntegerToBytes(nonce);
|
||||
byte[] gasPriceBytes = ByteUtil.bigIntegerToBytes(gasPrice);
|
||||
byte[] gasBytes = ByteUtil.bigIntegerToBytes(gas);
|
||||
byte[] valueBytes = ByteUtil.bigIntegerToBytes(value);
|
||||
byte[] nonceBytes = ByteUtil.bigIntegerToBytes(nonce);
|
||||
byte[] gasPriceBytes = ByteUtil.bigIntegerToBytes(gasPrice);
|
||||
byte[] gasBytes = ByteUtil.bigIntegerToBytes(gas);
|
||||
byte[] valueBytes = ByteUtil.bigIntegerToBytes(value);
|
||||
|
||||
Transaction tx = new Transaction(nonceBytes, gasPriceBytes, gasBytes,
|
||||
recieveAddress, valueBytes, data);
|
||||
@ -215,7 +218,7 @@ public class EthereumImpl implements Ethereum {
|
||||
|
||||
|
||||
@Override
|
||||
public Future<Transaction> submitTransaction(Transaction transaction){
|
||||
public Future<Transaction> submitTransaction(Transaction transaction) {
|
||||
|
||||
TransactionTask transactionTask = new TransactionTask(transaction, worldManager);
|
||||
Future<Transaction> future = TransactionExecutor.instance.submitTransaction(transactionTask);
|
||||
@ -225,13 +228,13 @@ public class EthereumImpl implements Ethereum {
|
||||
|
||||
|
||||
@Override
|
||||
public Wallet getWallet(){
|
||||
public Wallet getWallet() {
|
||||
return worldManager.getWallet();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Repository getRepository(){
|
||||
public Repository getRepository() {
|
||||
return worldManager.getRepository();
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ public interface Repository {
|
||||
* @param gasUsed the amount of gas used in the block until that point
|
||||
* @param txNumber is the number of the transaction for which the dump has to be made
|
||||
* @param txHash is the hash of the given transaction.
|
||||
* If null, the block state post coinbase reward is dumped.
|
||||
* If null, the block state post coinbase reward is dumped.
|
||||
*/
|
||||
public void dumpState(Block block, long gasUsed, int txNumber, byte[] txHash);
|
||||
|
||||
@ -172,12 +172,14 @@ public interface Repository {
|
||||
/**
|
||||
* Return to one of the previous snapshots
|
||||
* by moving the root.
|
||||
*
|
||||
* @param root - new root
|
||||
*/
|
||||
public void syncToRoot(byte[] root);
|
||||
|
||||
/**
|
||||
* Check to see if the current repository has an open connection to the database
|
||||
*
|
||||
* @return <tt>true</tt> if connection to database is open
|
||||
*/
|
||||
public boolean isClosed();
|
||||
@ -198,7 +200,7 @@ public interface Repository {
|
||||
|
||||
public byte[] getRoot();
|
||||
|
||||
void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
|
||||
void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
|
||||
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails);
|
||||
|
||||
}
|
||||
|
@ -15,36 +15,34 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
* customize ethereum state dumps.
|
||||
*
|
||||
* @author Alon Muroch
|
||||
*
|
||||
*/
|
||||
public class EtherObjectMapper extends ObjectMapper {
|
||||
|
||||
@Override
|
||||
public String writeValueAsString(Object value)
|
||||
throws JsonProcessingException {
|
||||
// alas, we have to pull the recycler directly here...
|
||||
SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
|
||||
try {
|
||||
JsonGenerator ge = _jsonFactory.createGenerator(sw);
|
||||
// set ethereum custom pretty printer
|
||||
EtherPrettyPrinter pp = new EtherPrettyPrinter();
|
||||
ge.setPrettyPrinter(pp);
|
||||
// alas, we have to pull the recycler directly here...
|
||||
SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
|
||||
try {
|
||||
JsonGenerator ge = _jsonFactory.createGenerator(sw);
|
||||
// set ethereum custom pretty printer
|
||||
EtherPrettyPrinter pp = new EtherPrettyPrinter();
|
||||
ge.setPrettyPrinter(pp);
|
||||
|
||||
_configAndWriteValue(ge, value);
|
||||
} catch (JsonProcessingException e) { // to support [JACKSON-758]
|
||||
throw e;
|
||||
} catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
|
||||
throw JsonMappingException.fromUnexpectedIOE(e);
|
||||
}
|
||||
return sw.getAndClear();
|
||||
_configAndWriteValue(ge, value);
|
||||
} catch (JsonProcessingException e) { // to support [JACKSON-758]
|
||||
throw e;
|
||||
} catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
|
||||
throw JsonMappingException.fromUnexpectedIOE(e);
|
||||
}
|
||||
return sw.getAndClear();
|
||||
}
|
||||
|
||||
/**
|
||||
* An extended {@link com.fasterxml.jackson.core.util.DefaultPrettyPrinter} class to customize
|
||||
* an ethereum {@link com.fasterxml.jackson.core.PrettyPrinter Pretty Printer} Generator
|
||||
*
|
||||
* @author Alon Muroch
|
||||
*
|
||||
*/
|
||||
public class EtherPrettyPrinter extends DefaultPrettyPrinter {
|
||||
|
||||
@ -55,11 +53,11 @@ public class EtherObjectMapper extends ObjectMapper {
|
||||
@Override
|
||||
public void writeObjectFieldValueSeparator(JsonGenerator jg)
|
||||
throws IOException, JsonGenerationException {
|
||||
/**
|
||||
* Custom object separator (Default is " : ") to make it easier to compare state dumps with other
|
||||
* ethereum client implementations
|
||||
*/
|
||||
jg.writeRaw(": ");
|
||||
}
|
||||
/**
|
||||
* Custom object separator (Default is " : ") to make it easier to compare state dumps with other
|
||||
* ethereum client implementations
|
||||
*/
|
||||
jg.writeRaw(": ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import java.util.*;
|
||||
|
||||
/**
|
||||
* JSON Helper class to format data into ObjectNodes
|
||||
* to match PyEthereum blockstate output
|
||||
* to match PyEthereum blockstate output
|
||||
*
|
||||
* Dump format:
|
||||
* {
|
||||
@ -80,8 +80,8 @@ public class JSONHelper {
|
||||
ObjectNode statesNode = blockNode.objectNode();
|
||||
for (ByteArrayWrapper key : keys) {
|
||||
byte[] keyBytes = key.getData();
|
||||
AccountState accountState = repository.getAccountState(keyBytes);
|
||||
ContractDetails details = repository.getContractDetails(keyBytes);
|
||||
AccountState accountState = repository.getAccountState(keyBytes);
|
||||
ContractDetails details = repository.getContractDetails(keyBytes);
|
||||
JSONHelper.dumpState(statesNode, Hex.toHexString(keyBytes), accountState, details);
|
||||
}
|
||||
blockNode.put("state", statesNode);
|
||||
|
@ -31,29 +31,29 @@ public class AccountState {
|
||||
public AccountState(byte[] address, JSONObject accountState) {
|
||||
|
||||
this.address = address;
|
||||
String balance = accountState.get("balance").toString();
|
||||
String code = (String)accountState.get("code");
|
||||
String nonce = accountState.get("nonce").toString();
|
||||
String balance = accountState.get("balance").toString();
|
||||
String code = (String) accountState.get("code");
|
||||
String nonce = accountState.get("nonce").toString();
|
||||
|
||||
JSONObject store = (JSONObject)accountState.get("storage");
|
||||
JSONObject store = (JSONObject) accountState.get("storage");
|
||||
|
||||
this.balance = new BigInteger(balance).toByteArray();
|
||||
|
||||
if (code != null && code.length() > 2)
|
||||
this.code = Hex.decode(code.substring(2));
|
||||
this.code = Hex.decode(code.substring(2));
|
||||
else
|
||||
this.code = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
this.nonce = new BigInteger(nonce).toByteArray();
|
||||
this.nonce = new BigInteger(nonce).toByteArray();
|
||||
|
||||
int size = store.keySet().size();
|
||||
Object[] keys = store.keySet().toArray();
|
||||
for (int i = 0; i < size; ++i) {
|
||||
|
||||
String keyS = keys[i].toString();
|
||||
String valS = store.get(keys[i]).toString();
|
||||
String valS = store.get(keys[i]).toString();
|
||||
|
||||
byte[] key = Utils.parseData(keyS);
|
||||
byte[] key = Utils.parseData(keyS);
|
||||
byte[] value = Utils.parseData(valS);
|
||||
storage.put(new DataWord(key), new DataWord(value));
|
||||
}
|
||||
@ -89,12 +89,12 @@ public class AccountState {
|
||||
return storage;
|
||||
}
|
||||
|
||||
public List<String> compareToReal(org.ethereum.core.AccountState state, ContractDetails details){
|
||||
public List<String> compareToReal(org.ethereum.core.AccountState state, ContractDetails details) {
|
||||
|
||||
List<String> results = new ArrayList<>();
|
||||
|
||||
BigInteger expectedBalance = new BigInteger(1, this.getBalance());
|
||||
if (!state.getBalance().equals(expectedBalance)){
|
||||
if (!state.getBalance().equals(expectedBalance)) {
|
||||
String formatedString = String.format("Account: %s: has unexpected balance, expected balance: %s found balance: %s",
|
||||
Hex.toHexString(this.address), expectedBalance.toString(), state.getBalance().toString());
|
||||
results.add(formatedString);
|
||||
@ -105,13 +105,13 @@ public class AccountState {
|
||||
state.getNonce();
|
||||
this.getNonce();
|
||||
String formatedString = String.format("Account: %s: has unexpected nonce, expected nonce: %s found nonce: %s",
|
||||
Hex.toHexString(this.address), expectedNonce.toString(), state.getNonce().toString() );
|
||||
Hex.toHexString(this.address), expectedNonce.toString(), state.getNonce().toString());
|
||||
results.add(formatedString);
|
||||
}
|
||||
|
||||
if (!Arrays.equals(details.getCode(),this.getCode())) {
|
||||
String formatedString = String.format("Account: %s: has unexpected nonce, expected nonce: %s found nonce: %s",
|
||||
Hex.toHexString(this.address), Hex.toHexString( this.getCode() ), Hex.toHexString(details.getCode()));
|
||||
Hex.toHexString(this.address), Hex.toHexString(this.getCode()), Hex.toHexString(details.getCode()));
|
||||
results.add(formatedString);
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ public class AccountState {
|
||||
Set<DataWord> expectedKeys = this.getStorage().keySet();
|
||||
Set<DataWord> checked = new HashSet<>();
|
||||
|
||||
for (DataWord key : keys){
|
||||
for (DataWord key : keys) {
|
||||
|
||||
DataWord value = details.getStorage().get(key);
|
||||
DataWord expectedValue = this.getStorage().get(key);
|
||||
@ -137,7 +137,7 @@ public class AccountState {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!expectedValue.equals(value)){
|
||||
if (!expectedValue.equals(value)) {
|
||||
|
||||
String formatedString = String.format("Account: %s: has unexpected value, for key: %s , expectedValue: %s real value: %s",
|
||||
Hex.toHexString(this.address), key.toString(),
|
||||
@ -149,8 +149,8 @@ public class AccountState {
|
||||
checked.add(key);
|
||||
}
|
||||
|
||||
for (DataWord key : expectedKeys){
|
||||
if (!checked.contains(key)){
|
||||
for (DataWord key : expectedKeys) {
|
||||
if (!checked.contains(key)) {
|
||||
String formatedString = String.format("Account: %s: doesn't exist expected storage key: %s",
|
||||
Hex.toHexString(this.address), key.toString());
|
||||
results.add(formatedString);
|
||||
|
@ -30,19 +30,19 @@ public class CallCreate {
|
||||
|
||||
public CallCreate(JSONObject callCreateJSON) {
|
||||
|
||||
String data = callCreateJSON.get("data").toString();
|
||||
String data = callCreateJSON.get("data").toString();
|
||||
String destination = callCreateJSON.get("destination").toString();
|
||||
String gasLimit = callCreateJSON.get("gasLimit").toString();
|
||||
String value = callCreateJSON.get("value").toString();
|
||||
String gasLimit = callCreateJSON.get("gasLimit").toString();
|
||||
String value = callCreateJSON.get("value").toString();
|
||||
|
||||
if (data != null && data.length() > 2)
|
||||
this.data = Hex.decode(data.substring(2));
|
||||
this.data = Hex.decode(data.substring(2));
|
||||
else
|
||||
this.data = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
this.destination = Hex.decode(destination);
|
||||
this.gasLimit = ByteUtil.bigIntegerToBytes(new BigInteger(gasLimit));
|
||||
this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));
|
||||
this.gasLimit = ByteUtil.bigIntegerToBytes(new BigInteger(gasLimit));
|
||||
this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
@ -64,10 +64,10 @@ public class CallCreate {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CallCreate{" +
|
||||
"data=" + Hex.toHexString(data) +
|
||||
"data=" + Hex.toHexString(data) +
|
||||
", destination=" + Hex.toHexString(destination) +
|
||||
", gasLimit=" + Hex.toHexString(gasLimit) +
|
||||
", value=" + Hex.toHexString(value) +
|
||||
", gasLimit=" + Hex.toHexString(gasLimit) +
|
||||
", value=" + Hex.toHexString(value) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
@ -33,19 +33,19 @@ public class Env {
|
||||
*/
|
||||
public Env(JSONObject env) {
|
||||
|
||||
String coinbase = env.get("currentCoinbase").toString();
|
||||
String coinbase = env.get("currentCoinbase").toString();
|
||||
String difficulty = env.get("currentDifficulty").toString();
|
||||
String timestamp = env.get("currentTimestamp").toString();
|
||||
String number = env.get("currentNumber").toString();
|
||||
String gasLimit = env.get("currentGasLimit").toString();
|
||||
String prevHash = env.get("previousHash").toString();
|
||||
String timestamp = env.get("currentTimestamp").toString();
|
||||
String number = env.get("currentNumber").toString();
|
||||
String gasLimit = env.get("currentGasLimit").toString();
|
||||
String prevHash = env.get("previousHash").toString();
|
||||
|
||||
this.currentCoinbase = Hex.decode(coinbase);
|
||||
this.currentCoinbase = Hex.decode(coinbase);
|
||||
this.currentDifficlty = new BigInteger(difficulty).toByteArray();
|
||||
this.currentGasLimit = new BigInteger(gasLimit).toByteArray();
|
||||
this.currentNumber = new BigInteger(number).toByteArray();
|
||||
this.currentGasLimit = new BigInteger(gasLimit).toByteArray();
|
||||
this.currentNumber = new BigInteger(number).toByteArray();
|
||||
this.currentTimestamp = new BigInteger(timestamp).toByteArray();
|
||||
this.previousHash = Hex.decode(prevHash);
|
||||
this.previousHash = Hex.decode(prevHash);
|
||||
|
||||
}
|
||||
|
||||
|
@ -42,36 +42,36 @@ public class Exec {
|
||||
*/
|
||||
public Exec(JSONObject exec) {
|
||||
|
||||
String address = exec.get("address").toString();
|
||||
String caller = exec.get("caller").toString();
|
||||
String address = exec.get("address").toString();
|
||||
String caller = exec.get("caller").toString();
|
||||
|
||||
String code = exec.get("code").toString();
|
||||
String data = exec.get("data").toString();
|
||||
String code = exec.get("code").toString();
|
||||
String data = exec.get("data").toString();
|
||||
|
||||
String gas = exec.get("gas").toString();
|
||||
String gas = exec.get("gas").toString();
|
||||
String gasPrice = exec.get("gasPrice").toString();
|
||||
String origin = exec.get("origin").toString();
|
||||
String origin = exec.get("origin").toString();
|
||||
|
||||
String value = exec.get("value").toString();
|
||||
String value = exec.get("value").toString();
|
||||
|
||||
this.address = Hex.decode(address);
|
||||
this.caller = Hex.decode(caller);
|
||||
this.caller = Hex.decode(caller);
|
||||
|
||||
if (code != null && code.length() > 2)
|
||||
this.code = Hex.decode(code.substring(2));
|
||||
this.code = Hex.decode(code.substring(2));
|
||||
else
|
||||
this.code = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
if (data != null && data.length() > 2)
|
||||
this.data = Hex.decode(data.substring(2));
|
||||
this.data = Hex.decode(data.substring(2));
|
||||
else
|
||||
this.data = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gas));
|
||||
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gas));
|
||||
this.gasPrice = ByteUtil.bigIntegerToBytes(new BigInteger(gasPrice));
|
||||
|
||||
this.origin = Hex.decode(origin);
|
||||
this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));
|
||||
this.origin = Hex.decode(origin);
|
||||
this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));
|
||||
}
|
||||
|
||||
|
||||
@ -86,6 +86,7 @@ public class Exec {
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public byte[] getCode() {
|
||||
return code;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ public class Helper {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger("misc");
|
||||
|
||||
public static byte[] parseDataArray(JSONArray valArray){
|
||||
public static byte[] parseDataArray(JSONArray valArray) {
|
||||
|
||||
// value can be:
|
||||
// 1. 324234 number
|
||||
@ -29,34 +29,45 @@ public class Helper {
|
||||
// 3. "239472398472" - big number
|
||||
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
for (int i = 0; i < valArray.size(); ++i){
|
||||
for (int i = 0; i < valArray.size(); ++i) {
|
||||
|
||||
Object val = valArray.get(i);
|
||||
if (val instanceof String){
|
||||
if (val instanceof String) {
|
||||
|
||||
// Hex num
|
||||
boolean hexVal = Pattern.matches("0[xX][0-9a-fA-F]+", val.toString());
|
||||
if (hexVal){
|
||||
if (hexVal) {
|
||||
String number = ((String) val).substring(2);
|
||||
if (number.length() % 2 == 1) number = "0" + number;
|
||||
byte[] data = Hex.decode(number);
|
||||
try {bos.write(data);} catch (IOException e) { logger.error("should not happen", e);}
|
||||
} else{
|
||||
try {
|
||||
bos.write(data);
|
||||
} catch (IOException e) {
|
||||
logger.error("should not happen", e);
|
||||
}
|
||||
} else {
|
||||
|
||||
// BigInt num
|
||||
boolean isNumeric = Pattern.matches("[0-9a-fA-F]+", val.toString());
|
||||
if (!isNumeric) throw new Error("Wrong test case JSON format");
|
||||
else{
|
||||
else {
|
||||
BigInteger value = new BigInteger(val.toString());
|
||||
try {bos.write(value.toByteArray());} catch (IOException e)
|
||||
{ logger.error("should not happen", e);}
|
||||
try {
|
||||
bos.write(value.toByteArray());
|
||||
} catch (IOException e) {
|
||||
logger.error("should not happen", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (val instanceof Long) {
|
||||
|
||||
// Simple long
|
||||
byte[] data = ByteUtil.bigIntegerToBytes(BigInteger.valueOf((Long)val));
|
||||
try {bos.write(data);} catch (IOException e) {logger.error("should not happen", e);}
|
||||
byte[] data = ByteUtil.bigIntegerToBytes(BigInteger.valueOf((Long) val));
|
||||
try {
|
||||
bos.write(data);
|
||||
} catch (IOException e) {
|
||||
logger.error("should not happen", e);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Wrong test case JSON format");
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class JSONReader {
|
||||
|
||||
public static String loadJSON(String filename) {
|
||||
String json = "";
|
||||
if(!SystemProperties.CONFIG.vmTestLoadLocal())
|
||||
if (!SystemProperties.CONFIG.vmTestLoadLocal())
|
||||
json = getFromUrl("https://raw.githubusercontent.com/ethereum/tests/develop/" + filename);
|
||||
return json == "" ? json = getFromLocal(filename) : json;
|
||||
}
|
||||
@ -24,8 +24,9 @@ public class JSONReader {
|
||||
public static String getFromLocal(String filename) {
|
||||
System.out.println("Loading local file: " + filename);
|
||||
try {
|
||||
if(System.getProperty("ETHEREUM_TEST_PATH") == null) {
|
||||
System.out.println("ETHEREUM_TEST_PATH is not passed as a VM argument, please make sure you pass it with the correct path");
|
||||
if (System.getProperty("ETHEREUM_TEST_PATH") == null) {
|
||||
System.out.println("ETHEREUM_TEST_PATH is not passed as a VM argument, please make sure you pass it " +
|
||||
"with the correct path");
|
||||
return "";
|
||||
}
|
||||
System.out.println("From: " + System.getProperty("ETHEREUM_TEST_PATH"));
|
||||
|
@ -18,17 +18,17 @@ public class Logs {
|
||||
|
||||
public Logs(JSONArray jLogs) {
|
||||
|
||||
for (int i = 0; i < jLogs.size(); ++i){
|
||||
for (int i = 0; i < jLogs.size(); ++i) {
|
||||
|
||||
JSONObject jLog = (JSONObject)jLogs.get(i);
|
||||
byte[] address = Hex.decode((String)jLog.get("address"));
|
||||
byte[] data = Hex.decode(((String)jLog.get("data")).substring(2));
|
||||
JSONObject jLog = (JSONObject) jLogs.get(i);
|
||||
byte[] address = Hex.decode((String) jLog.get("address"));
|
||||
byte[] data = Hex.decode(((String) jLog.get("data")).substring(2));
|
||||
|
||||
List<DataWord> topics = new ArrayList<>();
|
||||
|
||||
JSONArray jTopics = (JSONArray)jLog.get("topics");
|
||||
for(Object t: jTopics.toArray()) {
|
||||
byte[] topic = Hex.decode(((String)t));
|
||||
JSONArray jTopics = (JSONArray) jLog.get("topics");
|
||||
for (Object t : jTopics.toArray()) {
|
||||
byte[] topic = Hex.decode(((String) t));
|
||||
topics.add(new DataWord(topic));
|
||||
}
|
||||
|
||||
@ -38,24 +38,24 @@ public class Logs {
|
||||
}
|
||||
|
||||
|
||||
public Iterator<LogInfo> getIterator(){
|
||||
public Iterator<LogInfo> getIterator() {
|
||||
return logs.iterator();
|
||||
}
|
||||
|
||||
|
||||
public List<String> compareToReal(List<LogInfo> logs){
|
||||
public List<String> compareToReal(List<LogInfo> logs) {
|
||||
|
||||
List<String> results = new ArrayList<>();
|
||||
|
||||
int i = 0;
|
||||
for (LogInfo postLog : this.logs){
|
||||
for (LogInfo postLog : this.logs) {
|
||||
|
||||
LogInfo realLog = logs.get(i);
|
||||
|
||||
String postAddress = Hex.toHexString(postLog.getAddress());
|
||||
String realAddress = Hex.toHexString(realLog.getAddress());
|
||||
|
||||
if (!postAddress.equals(realAddress)){
|
||||
if (!postAddress.equals(realAddress)) {
|
||||
|
||||
String formatedString = String.format("Log: %s: has unexpected address, expected address: %s found address: %s",
|
||||
i, postAddress, realAddress);
|
||||
@ -65,7 +65,7 @@ public class Logs {
|
||||
String postData = Hex.toHexString(postLog.getData());
|
||||
String realData = Hex.toHexString(realLog.getData());
|
||||
|
||||
if (!postData.equals(realData)){
|
||||
if (!postData.equals(realData)) {
|
||||
|
||||
String formatedString = String.format("Log: %s: has unexpected data, expected data: %s found data: %s",
|
||||
i, postData, realData);
|
||||
@ -86,11 +86,11 @@ public class Logs {
|
||||
List<DataWord> realTopics = realLog.getTopics();
|
||||
|
||||
int j = 0;
|
||||
for (DataWord postTopic : postTopics){
|
||||
for (DataWord postTopic : postTopics) {
|
||||
|
||||
DataWord realTopic = realTopics.get(j);
|
||||
|
||||
if (!postTopic.equals(realTopic)){
|
||||
if (!postTopic.equals(realTopic)) {
|
||||
|
||||
String formatedString = String.format("Log: %s: has unexpected topic: %s, expected topic: %s found topic: %s",
|
||||
i, j, postTopic, realTopic);
|
||||
|
@ -21,8 +21,8 @@ public class StateTestCase {
|
||||
|
||||
private String name = "";
|
||||
|
||||
private Env env;
|
||||
private Logs logs;
|
||||
private Env env;
|
||||
private Logs logs;
|
||||
private byte[] out;
|
||||
|
||||
// "pre": { ... },
|
||||
@ -39,44 +39,44 @@ public class StateTestCase {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public StateTestCase(JSONObject testCaseJSONObj) throws ParseException{
|
||||
public StateTestCase(JSONObject testCaseJSONObj) throws ParseException {
|
||||
|
||||
try {
|
||||
|
||||
JSONObject envJSON = (JSONObject)testCaseJSONObj.get("env");
|
||||
JSONArray logsJSON = (JSONArray)testCaseJSONObj.get("logs");
|
||||
String outStr = testCaseJSONObj.get("out").toString();
|
||||
JSONObject txJSON = (JSONObject)testCaseJSONObj.get("transaction");
|
||||
JSONObject envJSON = (JSONObject) testCaseJSONObj.get("env");
|
||||
JSONArray logsJSON = (JSONArray) testCaseJSONObj.get("logs");
|
||||
String outStr = testCaseJSONObj.get("out").toString();
|
||||
JSONObject txJSON = (JSONObject) testCaseJSONObj.get("transaction");
|
||||
|
||||
JSONObject preJSON = (JSONObject)testCaseJSONObj.get("pre");
|
||||
JSONObject postJSON = (JSONObject)testCaseJSONObj.get("post");
|
||||
JSONObject preJSON = (JSONObject) testCaseJSONObj.get("pre");
|
||||
JSONObject postJSON = (JSONObject) testCaseJSONObj.get("post");
|
||||
|
||||
this.env = new Env(envJSON);
|
||||
this.env = new Env(envJSON);
|
||||
this.logs = new Logs(logsJSON);
|
||||
this.out = Utils.parseData(outStr);
|
||||
this.transaction = new Transaction(txJSON);
|
||||
this.out = Utils.parseData(outStr);
|
||||
this.transaction = new Transaction(txJSON);
|
||||
|
||||
for (Object key : preJSON.keySet()){
|
||||
for (Object key : preJSON.keySet()) {
|
||||
|
||||
byte[] keyBytes = Hex.decode(key.toString());
|
||||
AccountState accountState =
|
||||
new AccountState(keyBytes, (JSONObject) preJSON.get(key));
|
||||
new AccountState(keyBytes, (JSONObject) preJSON.get(key));
|
||||
|
||||
pre.put(new ByteArrayWrapper(keyBytes), accountState);
|
||||
}
|
||||
|
||||
for (Object key : postJSON.keySet()){
|
||||
for (Object key : postJSON.keySet()) {
|
||||
|
||||
byte[] keyBytes = Hex.decode(key.toString());
|
||||
AccountState accountState =
|
||||
new AccountState(keyBytes, (JSONObject) postJSON.get(key));
|
||||
new AccountState(keyBytes, (JSONObject) postJSON.get(key));
|
||||
|
||||
post.put(new ByteArrayWrapper(keyBytes), accountState);
|
||||
}
|
||||
|
||||
|
||||
} catch (Throwable e) {
|
||||
throw new ParseException(0, e);
|
||||
throw new ParseException(0, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ public class StateTestSuite {
|
||||
|
||||
public StateTestSuite(JSONObject testCaseJSONObj) throws ParseException {
|
||||
|
||||
for (Object key: testCaseJSONObj.keySet()){
|
||||
for (Object key : testCaseJSONObj.keySet()) {
|
||||
|
||||
Object testCaseJSON = testCaseJSONObj.get(key);
|
||||
|
||||
@ -31,19 +31,17 @@ public class StateTestSuite {
|
||||
}
|
||||
}
|
||||
|
||||
public StateTestCase getTestCase(String name){
|
||||
public StateTestCase getTestCase(String name) {
|
||||
|
||||
StateTestCase testCase = testCases.get(name);
|
||||
if (testCase == null) throw new NullPointerException("Test cases doesn't exist: " + name);
|
||||
|
||||
return testCase;
|
||||
return testCase;
|
||||
}
|
||||
|
||||
public Collection<StateTestCase> getAllTests(){
|
||||
public Collection<StateTestCase> getAllTests() {
|
||||
return testCases.values();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -45,73 +45,74 @@ public class TestCase {
|
||||
// "callcreates": { ... }
|
||||
private List<CallCreate> callCreateList = new ArrayList<>();
|
||||
|
||||
public TestCase(String name, JSONObject testCaseJSONObj) throws ParseException{
|
||||
public TestCase(String name, JSONObject testCaseJSONObj) throws ParseException {
|
||||
|
||||
this(testCaseJSONObj);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TestCase(JSONObject testCaseJSONObj) throws ParseException{
|
||||
public TestCase(JSONObject testCaseJSONObj) throws ParseException {
|
||||
|
||||
try {
|
||||
|
||||
JSONObject envJSON = (JSONObject)testCaseJSONObj.get("env");
|
||||
JSONObject execJSON = (JSONObject)testCaseJSONObj.get("exec");
|
||||
JSONObject preJSON = (JSONObject)testCaseJSONObj.get("pre");
|
||||
JSONObject envJSON = (JSONObject) testCaseJSONObj.get("env");
|
||||
JSONObject execJSON = (JSONObject) testCaseJSONObj.get("exec");
|
||||
JSONObject preJSON = (JSONObject) testCaseJSONObj.get("pre");
|
||||
JSONObject postJSON = new JSONObject();
|
||||
if(testCaseJSONObj.containsKey("post")) // in cases where there is no post dictionary (when testing for exceptions for example)
|
||||
postJSON = (JSONObject)testCaseJSONObj.get("post");
|
||||
JSONArray callCreates = new JSONArray();
|
||||
if(testCaseJSONObj.containsKey("callcreates"))
|
||||
callCreates = (JSONArray)testCaseJSONObj.get("callcreates");
|
||||
if (testCaseJSONObj.containsKey("post")) // in cases where there is no post dictionary (when testing for
|
||||
// exceptions for example)
|
||||
postJSON = (JSONObject) testCaseJSONObj.get("post");
|
||||
JSONArray callCreates = new JSONArray();
|
||||
if (testCaseJSONObj.containsKey("callcreates"))
|
||||
callCreates = (JSONArray) testCaseJSONObj.get("callcreates");
|
||||
|
||||
JSONArray logsJSON = new JSONArray();
|
||||
if(testCaseJSONObj.containsKey("logs"))
|
||||
logsJSON = (JSONArray)testCaseJSONObj.get("logs");
|
||||
if (testCaseJSONObj.containsKey("logs"))
|
||||
logsJSON = (JSONArray) testCaseJSONObj.get("logs");
|
||||
logs = new Logs(logsJSON);
|
||||
|
||||
String gasString = "0";
|
||||
if(testCaseJSONObj.containsKey("gas"))
|
||||
String gasString = "0";
|
||||
if (testCaseJSONObj.containsKey("gas"))
|
||||
gasString = testCaseJSONObj.get("gas").toString();
|
||||
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString));
|
||||
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString));
|
||||
|
||||
String outString = null;
|
||||
if(testCaseJSONObj.containsKey("out"))
|
||||
if (testCaseJSONObj.containsKey("out"))
|
||||
outString = testCaseJSONObj.get("out").toString();
|
||||
if (outString != null && outString.length() > 2)
|
||||
this.out = Hex.decode(outString.substring(2));
|
||||
this.out = Hex.decode(outString.substring(2));
|
||||
else
|
||||
this.out = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
for (Object key : preJSON.keySet()){
|
||||
for (Object key : preJSON.keySet()) {
|
||||
|
||||
byte[] keyBytes = Hex.decode(key.toString());
|
||||
AccountState accountState =
|
||||
new AccountState(keyBytes, (JSONObject) preJSON.get(key));
|
||||
new AccountState(keyBytes, (JSONObject) preJSON.get(key));
|
||||
|
||||
pre.put(new ByteArrayWrapper(keyBytes), accountState);
|
||||
}
|
||||
|
||||
for (Object key : postJSON.keySet()){
|
||||
for (Object key : postJSON.keySet()) {
|
||||
|
||||
byte[] keyBytes = Hex.decode(key.toString());
|
||||
AccountState accountState =
|
||||
new AccountState(keyBytes, (JSONObject) postJSON.get(key));
|
||||
new AccountState(keyBytes, (JSONObject) postJSON.get(key));
|
||||
|
||||
post.put(new ByteArrayWrapper(keyBytes), accountState);
|
||||
}
|
||||
|
||||
for (int i = 0; i < callCreates.size(); ++i){
|
||||
for (int i = 0; i < callCreates.size(); ++i) {
|
||||
|
||||
CallCreate cc = new CallCreate((JSONObject)callCreates.get(i));
|
||||
CallCreate cc = new CallCreate((JSONObject) callCreates.get(i));
|
||||
this.callCreateList.add(cc);
|
||||
}
|
||||
|
||||
this.env = new Env(envJSON);
|
||||
this.env = new Env(envJSON);
|
||||
this.exec = new Exec(execJSON);
|
||||
|
||||
} catch (Throwable e) {
|
||||
throw new ParseException(0, e);
|
||||
throw new ParseException(0, e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +148,7 @@ public class TestCase {
|
||||
return callCreateList;
|
||||
}
|
||||
|
||||
public String getName(){
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,11 @@ import java.math.BigInteger;
|
||||
* Created on: 19/12/2014 12:22
|
||||
*/
|
||||
|
||||
public class TestProgramInvokeFactory implements ProgramInvokeFactory{
|
||||
public class TestProgramInvokeFactory implements ProgramInvokeFactory {
|
||||
|
||||
Env env;
|
||||
|
||||
TestProgramInvokeFactory(Env env){
|
||||
TestProgramInvokeFactory(Env env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
@ -36,15 +36,15 @@ public class TestProgramInvokeFactory implements ProgramInvokeFactory{
|
||||
}
|
||||
|
||||
|
||||
private ProgramInvoke generalInvoke(Transaction tx, Repository repository){
|
||||
private ProgramInvoke generalInvoke(Transaction tx, Repository repository) {
|
||||
|
||||
/*** ADDRESS op ***/
|
||||
// YP: Get address of currently executing account.
|
||||
byte[] address = tx.isContractCreation() ? tx.getContractAddress(): tx.getReceiveAddress();
|
||||
byte[] address = tx.isContractCreation() ? tx.getContractAddress() : tx.getReceiveAddress();
|
||||
|
||||
/*** ORIGIN op ***/
|
||||
// YP: This is the sender of original transaction; it is never a contract.
|
||||
byte[] origin = tx.getSender();
|
||||
byte[] origin = tx.getSender();
|
||||
|
||||
/*** CALLER op ***/
|
||||
// YP: This is the address of the account that is directly responsible for this execution.
|
||||
@ -80,10 +80,10 @@ public class TestProgramInvokeFactory implements ProgramInvokeFactory{
|
||||
long number = ByteUtil.byteArrayToLong(env.getCurrentNumber());
|
||||
|
||||
/*** DIFFICULTY op ***/
|
||||
byte[] difficulty = env.getCurrentDifficlty();
|
||||
byte[] difficulty = env.getCurrentDifficlty();
|
||||
|
||||
/*** GASLIMIT op ***/
|
||||
long gaslimit = ByteUtil.byteArrayToLong( env.getCurrentGasLimit() );
|
||||
long gaslimit = ByteUtil.byteArrayToLong(env.getCurrentGasLimit());
|
||||
|
||||
return new ProgramInvokeImpl(address, origin, caller, balance,
|
||||
gasPrice, gas, callValue, data, lastHash, coinbase,
|
||||
|
@ -53,7 +53,7 @@ public class TestRunner {
|
||||
|
||||
List<String> results = null;
|
||||
logger.info("\n***");
|
||||
logger.info(" Running test case: [" + testCase.getName() + "]") ;
|
||||
logger.info(" Running test case: [" + testCase.getName() + "]");
|
||||
logger.info("***\n");
|
||||
results = new ArrayList<>();
|
||||
|
||||
@ -62,7 +62,7 @@ public class TestRunner {
|
||||
|
||||
logger.info("loaded repository");
|
||||
|
||||
org.ethereum.core.Transaction tx = createTransaction(testCase.getTransaction());
|
||||
org.ethereum.core.Transaction tx = createTransaction(testCase.getTransaction());
|
||||
logger.info("transaction: {}", tx.toString());
|
||||
|
||||
byte[] secretKey = testCase.getTransaction().secretKey;
|
||||
@ -91,9 +91,9 @@ public class TestRunner {
|
||||
List<String> logResults = testCase.getLogs().compareToReal(logs);
|
||||
results.addAll(logResults);
|
||||
|
||||
Set<ByteArrayWrapper> fullAddressSet = repository.getFullAddressSet();
|
||||
Set<ByteArrayWrapper> fullAddressSet = repository.getFullAddressSet();
|
||||
int repoSize = 0;
|
||||
for (ByteArrayWrapper addrWrapped : fullAddressSet){
|
||||
for (ByteArrayWrapper addrWrapped : fullAddressSet) {
|
||||
|
||||
byte[] addr = addrWrapped.getData();
|
||||
|
||||
@ -101,11 +101,11 @@ public class TestRunner {
|
||||
ContractDetails contractDetails = repository.getContractDetails(addr);
|
||||
|
||||
logger.info("{} \n{} \n{}", Hex.toHexString(addr),
|
||||
accountState.toString(), contractDetails.toString() );
|
||||
accountState.toString(), contractDetails.toString());
|
||||
logger.info("");
|
||||
|
||||
AccountState expectedAccountState = testCase.getPost().get(wrap(addr));
|
||||
if (expectedAccountState == null){
|
||||
if (expectedAccountState == null) {
|
||||
String formatedString = String.format("Unexpected account state: address: %s", Hex.toHexString(addr));
|
||||
results.add(formatedString);
|
||||
continue;
|
||||
@ -119,7 +119,7 @@ public class TestRunner {
|
||||
|
||||
int postRepoSize = testCase.getPost().size();
|
||||
|
||||
if (postRepoSize > repoSize){
|
||||
if (postRepoSize > repoSize) {
|
||||
results.add("ERROR: Post repository contains more accounts than executed repository ");
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ public class TestRunner {
|
||||
public List<String> runTestCase(TestCase testCase) {
|
||||
|
||||
logger.info("\n***");
|
||||
logger.info(" Running test case: [" + testCase.getName() + "]") ;
|
||||
logger.info(" Running test case: [" + testCase.getName() + "]");
|
||||
logger.info("***\n");
|
||||
List<String> results = new ArrayList<>();
|
||||
|
||||
@ -141,29 +141,29 @@ public class TestRunner {
|
||||
|
||||
|
||||
/* 2. Create ProgramInvoke - Env/Exec */
|
||||
Env env = testCase.getEnv();
|
||||
Env env = testCase.getEnv();
|
||||
Exec exec = testCase.getExec();
|
||||
Logs logs = testCase.getLogs();
|
||||
|
||||
byte[] address = exec.getAddress();
|
||||
byte[] origin = exec.getOrigin();
|
||||
byte[] caller = exec.getCaller();
|
||||
byte[] balance = ByteUtil.bigIntegerToBytes(repository.getBalance(exec.getAddress()));
|
||||
byte[] gasPrice = exec.getGasPrice();
|
||||
byte[] gas = exec.getGas();
|
||||
byte[] callValue = exec.getValue();
|
||||
byte[] msgData = exec.getData();
|
||||
byte[] lastHash = env.getPreviousHash();
|
||||
byte[] coinbase = env.getCurrentCoinbase();
|
||||
long timestamp = new BigInteger(env.getCurrentTimestamp()).longValue();
|
||||
long number = new BigInteger(env.getCurrentNumber()).longValue();
|
||||
byte[] difficulty = env.getCurrentDifficlty();
|
||||
long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue();
|
||||
byte[] address = exec.getAddress();
|
||||
byte[] origin = exec.getOrigin();
|
||||
byte[] caller = exec.getCaller();
|
||||
byte[] balance = ByteUtil.bigIntegerToBytes(repository.getBalance(exec.getAddress()));
|
||||
byte[] gasPrice = exec.getGasPrice();
|
||||
byte[] gas = exec.getGas();
|
||||
byte[] callValue = exec.getValue();
|
||||
byte[] msgData = exec.getData();
|
||||
byte[] lastHash = env.getPreviousHash();
|
||||
byte[] coinbase = env.getCurrentCoinbase();
|
||||
long timestamp = new BigInteger(env.getCurrentTimestamp()).longValue();
|
||||
long number = new BigInteger(env.getCurrentNumber()).longValue();
|
||||
byte[] difficulty = env.getCurrentDifficlty();
|
||||
long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue();
|
||||
|
||||
// Origin and caller need to exist in order to be able to execute
|
||||
if(repository.getAccountState(origin) == null)
|
||||
if (repository.getAccountState(origin) == null)
|
||||
repository.createAccount(origin);
|
||||
if(repository.getAccountState(caller) == null)
|
||||
if (repository.getAccountState(caller) == null)
|
||||
repository.createAccount(caller);
|
||||
|
||||
ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance,
|
||||
@ -177,27 +177,24 @@ public class TestRunner {
|
||||
boolean vmDidThrowAnEception = false;
|
||||
RuntimeException e = null;
|
||||
try {
|
||||
while(!program.isStopped())
|
||||
while (!program.isStopped())
|
||||
vm.step(program);
|
||||
}
|
||||
catch (RuntimeException ex) {
|
||||
} catch (RuntimeException ex) {
|
||||
vmDidThrowAnEception = true;
|
||||
e = ex;
|
||||
}
|
||||
program.saveProgramTraceToFile(testCase.getName());
|
||||
|
||||
if(testCase.getPost().size() == 0) {
|
||||
if(vmDidThrowAnEception != true) {
|
||||
if (testCase.getPost().size() == 0) {
|
||||
if (vmDidThrowAnEception != true) {
|
||||
String output =
|
||||
String.format("VM was expected to throw an exception");
|
||||
logger.info(output);
|
||||
results.add(output);
|
||||
}
|
||||
else
|
||||
} else
|
||||
logger.info("VM did throw an exception: " + e.toString());
|
||||
}
|
||||
else {
|
||||
if(vmDidThrowAnEception) {
|
||||
} else {
|
||||
if (vmDidThrowAnEception) {
|
||||
String output =
|
||||
String.format("VM threw an unexpected exception: " + e.toString());
|
||||
logger.info(output);
|
||||
@ -213,9 +210,9 @@ public class TestRunner {
|
||||
|
||||
AccountState accountState = testCase.getPost().get(key);
|
||||
|
||||
long expectedNonce = accountState.getNonceLong();
|
||||
BigInteger expectedBalance = accountState.getBigIntegerBalance();
|
||||
byte[] expectedCode = accountState.getCode();
|
||||
long expectedNonce = accountState.getNonceLong();
|
||||
BigInteger expectedBalance = accountState.getBigIntegerBalance();
|
||||
byte[] expectedCode = accountState.getCode();
|
||||
|
||||
boolean accountExist = (null != repository.getAccountState(key.getData()));
|
||||
if (!accountExist) {
|
||||
@ -283,17 +280,17 @@ public class TestRunner {
|
||||
continue;
|
||||
}
|
||||
|
||||
Map<DataWord, DataWord> testStorage = contractDetails.getStorage();
|
||||
Map<DataWord, DataWord> testStorage = contractDetails.getStorage();
|
||||
DataWord actualValue = testStorage.get(new DataWord(storageKey.getData()));
|
||||
|
||||
if (actualValue == null ||
|
||||
!Arrays.equals(expectedStValue, actualValue.getNoLeadZeroesData())) {
|
||||
!Arrays.equals(expectedStValue, actualValue.getNoLeadZeroesData())) {
|
||||
|
||||
String output =
|
||||
String.format("Storage value different: key [ %s ], expectedValue: [ %s ], actualValue: [ %s ]",
|
||||
Hex.toHexString(storageKey.getData()),
|
||||
Hex.toHexString(expectedStValue),
|
||||
actualValue == null ? "" : Hex.toHexString(actualValue.getNoLeadZeroesData()));
|
||||
actualValue == null ? "" : Hex.toHexString(actualValue.getNoLeadZeroesData()));
|
||||
logger.info(output);
|
||||
results.add(output);
|
||||
}
|
||||
@ -304,36 +301,35 @@ public class TestRunner {
|
||||
|
||||
Iterator<LogInfo> postLogs = logs.getIterator();
|
||||
int i = 0;
|
||||
while(postLogs.hasNext()) {
|
||||
while (postLogs.hasNext()) {
|
||||
|
||||
LogInfo expectedLogInfo = postLogs.next();
|
||||
|
||||
LogInfo foundLogInfo = null;
|
||||
if (logResult.size() > i)
|
||||
foundLogInfo = logResult.get(i);
|
||||
foundLogInfo = logResult.get(i);
|
||||
|
||||
if(foundLogInfo == null) {
|
||||
if (foundLogInfo == null) {
|
||||
String output =
|
||||
String.format("Expected log [ %s ]", expectedLogInfo.toString());
|
||||
logger.info(output);
|
||||
results.add(output);
|
||||
}
|
||||
else {
|
||||
if(!Arrays.equals(expectedLogInfo.getAddress(), foundLogInfo.getAddress())) {
|
||||
} else {
|
||||
if (!Arrays.equals(expectedLogInfo.getAddress(), foundLogInfo.getAddress())) {
|
||||
String output =
|
||||
String.format("Expected address [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getAddress()), Hex.toHexString(foundLogInfo.getAddress()));
|
||||
logger.info(output);
|
||||
results.add(output);
|
||||
}
|
||||
|
||||
if(!Arrays.equals(expectedLogInfo.getData(), foundLogInfo.getData())) {
|
||||
if (!Arrays.equals(expectedLogInfo.getData(), foundLogInfo.getData())) {
|
||||
String output =
|
||||
String.format("Expected data [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getData()), Hex.toHexString(foundLogInfo.getData()));
|
||||
logger.info(output);
|
||||
results.add(output);
|
||||
}
|
||||
|
||||
if(!expectedLogInfo.getBloom().equals(foundLogInfo.getBloom())) {
|
||||
if (!expectedLogInfo.getBloom().equals(foundLogInfo.getBloom())) {
|
||||
String output =
|
||||
String.format("Expected bloom [ %s ], found [ %s ]",
|
||||
Hex.toHexString(expectedLogInfo.getBloom().getData()),
|
||||
@ -342,18 +338,18 @@ public class TestRunner {
|
||||
results.add(output);
|
||||
}
|
||||
|
||||
if(expectedLogInfo.getTopics().size() != foundLogInfo.getTopics().size()) {
|
||||
if (expectedLogInfo.getTopics().size() != foundLogInfo.getTopics().size()) {
|
||||
String output =
|
||||
String.format("Expected number of topics [ %d ], found [ %d ]", expectedLogInfo.getTopics().size(), foundLogInfo.getTopics().size());
|
||||
String.format("Expected number of topics [ %d ], found [ %d ]",
|
||||
expectedLogInfo.getTopics().size(), foundLogInfo.getTopics().size());
|
||||
logger.info(output);
|
||||
results.add(output);
|
||||
}
|
||||
else {
|
||||
int j=0;
|
||||
for(DataWord topic: expectedLogInfo.getTopics()) {
|
||||
} else {
|
||||
int j = 0;
|
||||
for (DataWord topic : expectedLogInfo.getTopics()) {
|
||||
byte[] foundTopic = foundLogInfo.getTopics().get(j).getData();
|
||||
|
||||
if(!Arrays.equals(topic.getData(), foundTopic)) {
|
||||
if (!Arrays.equals(topic.getData(), foundTopic)) {
|
||||
String output =
|
||||
String.format("Expected topic [ %s ], found [ %s ]", Hex.toHexString(topic.getData()), Hex.toHexString(foundTopic));
|
||||
logger.info(output);
|
||||
@ -373,7 +369,7 @@ public class TestRunner {
|
||||
// TODO: -> basically the deleted by suicide should be deleted
|
||||
// TODO: -> and no unexpected created
|
||||
|
||||
List<org.ethereum.vm.CallCreate> resultCallCreates =
|
||||
List<org.ethereum.vm.CallCreate> resultCallCreates =
|
||||
program.getResult().getCallCreateList();
|
||||
|
||||
// assert call creates
|
||||
@ -492,14 +488,14 @@ public class TestRunner {
|
||||
}
|
||||
}
|
||||
|
||||
public org.ethereum.core.Transaction createTransaction(Transaction tx){
|
||||
public org.ethereum.core.Transaction createTransaction(Transaction tx) {
|
||||
|
||||
byte[] nonceBytes = ByteUtil.longToBytes(tx.nonce);
|
||||
byte[] gasPriceBytes = ByteUtil.longToBytes(tx.gasPrice);
|
||||
byte[] gasBytes = ByteUtil.longToBytes(tx.gasLimit);
|
||||
byte[] valueBytes = ByteUtil.longToBytes(tx.value);
|
||||
byte[] toAddr = tx.getTo();
|
||||
byte[] data = tx.getData();
|
||||
byte[] nonceBytes = ByteUtil.longToBytes(tx.nonce);
|
||||
byte[] gasPriceBytes = ByteUtil.longToBytes(tx.gasPrice);
|
||||
byte[] gasBytes = ByteUtil.longToBytes(tx.gasLimit);
|
||||
byte[] valueBytes = ByteUtil.longToBytes(tx.value);
|
||||
byte[] toAddr = tx.getTo();
|
||||
byte[] data = tx.getData();
|
||||
|
||||
org.ethereum.core.Transaction transaction = new org.ethereum.core.Transaction(
|
||||
nonceBytes, gasPriceBytes, gasBytes,
|
||||
@ -508,7 +504,7 @@ public class TestRunner {
|
||||
return transaction;
|
||||
}
|
||||
|
||||
public RepositoryDummy loadRepository(Map<ByteArrayWrapper, AccountState> pre){
|
||||
public RepositoryDummy loadRepository(Map<ByteArrayWrapper, AccountState> pre) {
|
||||
|
||||
|
||||
RepositoryDummy track = new RepositoryDummy();
|
||||
@ -524,7 +520,7 @@ public class TestRunner {
|
||||
|
||||
track.saveCode(addr, accountState.getCode());
|
||||
|
||||
for (DataWord storageKey : accountState.getStorage().keySet()){
|
||||
for (DataWord storageKey : accountState.getStorage().keySet()) {
|
||||
track.addStorageRow(addr, storageKey, accountState.getStorage().get(storageKey));
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public class TestSuite {
|
||||
|
||||
public TestSuite(JSONObject testCaseJSONObj) throws ParseException {
|
||||
|
||||
for (Object key: testCaseJSONObj.keySet()){
|
||||
for (Object key : testCaseJSONObj.keySet()) {
|
||||
|
||||
Object testCaseJSON = testCaseJSONObj.get(key);
|
||||
TestCase testCase = new TestCase(key.toString(), (JSONObject) testCaseJSON);
|
||||
@ -26,7 +26,7 @@ public class TestSuite {
|
||||
}
|
||||
}
|
||||
|
||||
public Iterator<TestCase> iterator(){
|
||||
public Iterator<TestCase> iterator() {
|
||||
return testList.iterator();
|
||||
}
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ import static org.ethereum.util.ByteUtil.toHexString;
|
||||
public class Transaction {
|
||||
|
||||
byte[] data;
|
||||
long gasLimit;
|
||||
long gasPrice;
|
||||
long nonce;
|
||||
long gasLimit;
|
||||
long gasPrice;
|
||||
long nonce;
|
||||
byte[] secretKey;
|
||||
byte[] to;
|
||||
long value;
|
||||
long value;
|
||||
|
||||
/* e.g.
|
||||
"transaction" : {
|
||||
@ -40,22 +40,22 @@ public class Transaction {
|
||||
|
||||
public Transaction(JSONObject callCreateJSON) {
|
||||
|
||||
String dataStr = callCreateJSON.get("data").toString();
|
||||
String gasLimitStr = callCreateJSON.get("gasLimit").toString();
|
||||
String gasPriceStr = callCreateJSON.get("gasPrice").toString();
|
||||
String nonceStr = callCreateJSON.get("nonce").toString();
|
||||
String secretKeyStr = callCreateJSON.get("secretKey").toString();
|
||||
String toStr = callCreateJSON.get("to").toString();
|
||||
String valueStr = callCreateJSON.get("value").toString();
|
||||
String dataStr = callCreateJSON.get("data").toString();
|
||||
String gasLimitStr = callCreateJSON.get("gasLimit").toString();
|
||||
String gasPriceStr = callCreateJSON.get("gasPrice").toString();
|
||||
String nonceStr = callCreateJSON.get("nonce").toString();
|
||||
String secretKeyStr = callCreateJSON.get("secretKey").toString();
|
||||
String toStr = callCreateJSON.get("to").toString();
|
||||
String valueStr = callCreateJSON.get("value").toString();
|
||||
|
||||
|
||||
this.data = Utils.parseData(dataStr);
|
||||
this.gasLimit = Utils.parseLong(gasLimitStr);
|
||||
this.gasPrice = Utils.parseLong(gasPriceStr);
|
||||
this.nonce = Utils.parseLong(nonceStr);
|
||||
this.data = Utils.parseData(dataStr);
|
||||
this.gasLimit = Utils.parseLong(gasLimitStr);
|
||||
this.gasPrice = Utils.parseLong(gasPriceStr);
|
||||
this.nonce = Utils.parseLong(nonceStr);
|
||||
this.secretKey = Utils.parseData(secretKeyStr);
|
||||
this.to = Utils.parseData(toStr);
|
||||
this.value = Utils.parseLong(valueStr);
|
||||
this.to = Utils.parseData(toStr);
|
||||
this.value = Utils.parseLong(valueStr);
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
|
@ -14,14 +14,14 @@ import org.spongycastle.util.encoders.Hex;
|
||||
public class Utils {
|
||||
|
||||
|
||||
public static byte[] parseData(String data){
|
||||
public static byte[] parseData(String data) {
|
||||
if (data == null) return ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
if (data.startsWith("0x")) data = data.substring(2);
|
||||
return Hex.decode(data);
|
||||
}
|
||||
|
||||
public static long parseLong(String data){
|
||||
return data.equals("") ? 0 : Long.parseLong(data);
|
||||
public static long parseLong(String data) {
|
||||
return data.equals("") ? 0 : Long.parseLong(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -16,11 +16,18 @@ import java.util.Set;
|
||||
public interface EthereumListener {
|
||||
|
||||
public void trace(String output);
|
||||
|
||||
public void onBlock(Block block);
|
||||
|
||||
public void onRecvMessage(Message message);
|
||||
|
||||
public void onSendMessage(Message message);
|
||||
|
||||
public void onPeerDisconnect(String host, long port);
|
||||
|
||||
public void onPendingTransactionsReceived(Set<Transaction> transactions);
|
||||
|
||||
public void onSyncDone();
|
||||
|
||||
public void onNoConnections();
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class EthereumListenerAdapter implements EthereumListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNoConnections(){
|
||||
public void onNoConnections() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ import java.util.Set;
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 12/11/2014 08:34
|
||||
*/
|
||||
@Component(value="EthereumListener")
|
||||
public class EthereumListenerWrapper implements EthereumListener{
|
||||
@Component(value = "EthereumListener")
|
||||
public class EthereumListenerWrapper implements EthereumListener {
|
||||
|
||||
EthereumListener listener;
|
||||
|
||||
@ -64,12 +64,12 @@ public class EthereumListenerWrapper implements EthereumListener{
|
||||
|
||||
|
||||
@Override
|
||||
public void onNoConnections(){
|
||||
public void onNoConnections() {
|
||||
if (listener != null)
|
||||
listener.onNoConnections();
|
||||
}
|
||||
|
||||
public void addListener(EthereumListener listener){
|
||||
public void addListener(EthereumListener listener) {
|
||||
if (listener != null)
|
||||
this.listener = listener;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class AdminInfo {
|
||||
return consensus;
|
||||
}
|
||||
|
||||
public void lostConsensus(){
|
||||
public void lostConsensus() {
|
||||
consensus = false;
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ public class WorldManager {
|
||||
|
||||
public void addListener(EthereumListener listener) {
|
||||
logger.info("Ethereum listener added");
|
||||
((EthereumListenerWrapper)this.listener).addListener(listener);
|
||||
((EthereumListenerWrapper) this.listener).addListener(listener);
|
||||
}
|
||||
|
||||
public void startPeerDiscovery() {
|
||||
@ -88,7 +88,7 @@ public class WorldManager {
|
||||
peerDiscovery.stop();
|
||||
}
|
||||
|
||||
public void addPendingTransactions(Set<Transaction> transactions){
|
||||
public void addPendingTransactions(Set<Transaction> transactions) {
|
||||
logger.info("Pending transaction list added: size: [{}]", transactions.size());
|
||||
|
||||
if (listener != null)
|
||||
@ -96,15 +96,15 @@ public class WorldManager {
|
||||
pendingTransactions.addAll(transactions);
|
||||
}
|
||||
|
||||
public void clearPendingTransactions(List<Transaction> recivedTransactions){
|
||||
public void clearPendingTransactions(List<Transaction> recivedTransactions) {
|
||||
|
||||
for (Transaction tx : recivedTransactions){
|
||||
for (Transaction tx : recivedTransactions) {
|
||||
logger.info("Clear transaction, hash: [{}]", Hex.toHexString(tx.getHash()));
|
||||
pendingTransactions.remove(tx);
|
||||
}
|
||||
}
|
||||
|
||||
public ChannelManager getChannelManager(){
|
||||
public ChannelManager getChannelManager() {
|
||||
return channelManager;
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ public class WorldManager {
|
||||
return listener;
|
||||
}
|
||||
|
||||
public void setWallet(Wallet wallet) {
|
||||
public void setWallet(Wallet wallet) {
|
||||
this.wallet = wallet;
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ public class WorldManager {
|
||||
return pendingTransactions;
|
||||
}
|
||||
|
||||
public boolean isBlockchainLoading(){
|
||||
public boolean isBlockchainLoading() {
|
||||
return blockchain.getQueue().size() > 2;
|
||||
}
|
||||
|
||||
@ -180,14 +180,14 @@ public class WorldManager {
|
||||
}
|
||||
|
||||
|
||||
if (CONFIG.rootHashStart() != null){
|
||||
if (CONFIG.rootHashStart() != null) {
|
||||
|
||||
// update world state by dummy hash
|
||||
byte[] rootHash = Hex.decode(CONFIG.rootHashStart());
|
||||
logger.info("Loading root hash from property file: [{}]", CONFIG.rootHashStart());
|
||||
this.repository.syncToRoot(rootHash);
|
||||
|
||||
} else{
|
||||
} else {
|
||||
|
||||
// Update world state to latest loaded block from db
|
||||
this.repository.syncToRoot(blockchain.getBestBlock().getStateRoot());
|
||||
@ -202,7 +202,7 @@ public class WorldManager {
|
||||
*/
|
||||
}
|
||||
|
||||
public void reset(){
|
||||
public void reset() {
|
||||
logger.info("Resetting blockchain ");
|
||||
repository.reset();
|
||||
blockchain.reset();
|
||||
|
@ -77,9 +77,9 @@ public class Miner {
|
||||
byte[] testNonce = new byte[32];
|
||||
byte[] concat;
|
||||
|
||||
while(ByteUtil.increment(testNonce) && !stop) {
|
||||
while (ByteUtil.increment(testNonce) && !stop) {
|
||||
|
||||
if (testNonce[31] == 0 && testNonce[30] == 0){
|
||||
if (testNonce[31] == 0 && testNonce[30] == 0) {
|
||||
System.out.println("mining: " + new BigInteger(1, testNonce));
|
||||
}
|
||||
|
||||
@ -87,7 +87,7 @@ public class Miner {
|
||||
sleep();
|
||||
concat = Arrays.concatenate(hash, testNonce);
|
||||
byte[] result = SHA3Helper.sha3(concat);
|
||||
if(FastByteComparisons.compareTo(result, 0, 32, target, 0, 32) < 0) {
|
||||
if (FastByteComparisons.compareTo(result, 0, 32, target, 0, 32) < 0) {
|
||||
newBlock.setNonce(testNonce);
|
||||
return true;
|
||||
}
|
||||
@ -95,11 +95,11 @@ public class Miner {
|
||||
return false; // couldn't find a valid nonce
|
||||
}
|
||||
|
||||
public void stop(){
|
||||
public void stop() {
|
||||
stop = true;
|
||||
}
|
||||
|
||||
private void sleep(){
|
||||
private void sleep() {
|
||||
try {
|
||||
// Thread.sleep(1);
|
||||
Thread.sleep(10);
|
||||
|
@ -27,17 +27,25 @@ public class BlockQueue {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("blockqueue");
|
||||
|
||||
/** The list of hashes of the heaviest chain on the network,
|
||||
* for which this client doesn't have the blocks yet */
|
||||
/**
|
||||
* The list of hashes of the heaviest chain on the network,
|
||||
* for which this client doesn't have the blocks yet
|
||||
*/
|
||||
private Deque<byte[]> blockHashQueue = new ArrayDeque<>();
|
||||
|
||||
/** Queue with blocks to be validated and added to the blockchain */
|
||||
/**
|
||||
* Queue with blocks to be validated and added to the blockchain
|
||||
*/
|
||||
private Queue<Block> blockReceivedQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
/** Highest known total difficulty, representing the heaviest chain on the network */
|
||||
/**
|
||||
* Highest known total difficulty, representing the heaviest chain on the network
|
||||
*/
|
||||
private BigInteger highestTotalDifficulty;
|
||||
|
||||
/** Last block in the queue to be processed */
|
||||
/**
|
||||
* Last block in the queue to be processed
|
||||
*/
|
||||
private Block lastBlock;
|
||||
|
||||
private Timer timer = new Timer("BlockQueueTimer");
|
||||
@ -61,7 +69,7 @@ public class BlockQueue {
|
||||
return;
|
||||
|
||||
logger.info("BlockQueue size: {}", blockReceivedQueue.size());
|
||||
while(!blockReceivedQueue.isEmpty()){
|
||||
while (!blockReceivedQueue.isEmpty()) {
|
||||
Block block = blockReceivedQueue.poll();
|
||||
|
||||
logger.info("Processing block index: {}", block.getNumber());
|
||||
@ -85,22 +93,23 @@ public class BlockQueue {
|
||||
blockReceivedQueue.addAll(blockList);
|
||||
lastBlock = blockList.get(blockList.size() - 1);
|
||||
|
||||
logger.info("Blocks waiting to be proceed: queue.size: [{}] lastBlock.number: [{}]" ,
|
||||
logger.info("Blocks waiting to be proceed: queue.size: [{}] lastBlock.number: [{}]",
|
||||
blockReceivedQueue.size(),
|
||||
lastBlock.getNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* adding single block to the queue usually
|
||||
* a result of a NEW_BLOCK message announce.
|
||||
* a result of a NEW_BLOCK message announce.
|
||||
*
|
||||
* @param block - new block
|
||||
*/
|
||||
public void addBlock(Block block){
|
||||
public void addBlock(Block block) {
|
||||
|
||||
blockReceivedQueue.add(block);
|
||||
lastBlock = block;
|
||||
|
||||
logger.debug("Blocks waiting to be proceed: queue.size: [{}] lastBlock.number: [{}]" ,
|
||||
logger.debug("Blocks waiting to be proceed: queue.size: [{}] lastBlock.number: [{}]",
|
||||
blockReceivedQueue.size(),
|
||||
lastBlock.getNumber());
|
||||
}
|
||||
@ -143,19 +152,19 @@ public class BlockQueue {
|
||||
public void addHash(byte[] hash) {
|
||||
blockHashQueue.addLast(hash);
|
||||
|
||||
if (logger.isTraceEnabled()){
|
||||
logger.trace("Adding hash to a hashQueue: [{}]" , Hex.toHexString(hash));
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Adding hash to a hashQueue: [{}]", Hex.toHexString(hash));
|
||||
}
|
||||
}
|
||||
|
||||
public void returnHashes(List<byte[]> hashes){
|
||||
public void returnHashes(List<byte[]> hashes) {
|
||||
|
||||
ListIterator iterator = hashes.listIterator(hashes.size());
|
||||
while(iterator.hasPrevious())
|
||||
blockHashQueue.addLast((byte[])iterator.previous());
|
||||
ListIterator iterator = hashes.listIterator(hashes.size());
|
||||
while (iterator.hasPrevious())
|
||||
blockHashQueue.addLast((byte[]) iterator.previous());
|
||||
}
|
||||
|
||||
public void addNewBlockHash(byte[] hash){
|
||||
public void addNewBlockHash(byte[] hash) {
|
||||
blockHashQueue.addFirst(hash);
|
||||
}
|
||||
|
||||
@ -168,14 +177,14 @@ public class BlockQueue {
|
||||
|
||||
List<byte[]> hashes = new ArrayList<>();
|
||||
while (!blockHashQueue.isEmpty() && hashes.size() < CONFIG.maxBlocksAsk()) {
|
||||
hashes.add(blockHashQueue.removeLast());
|
||||
hashes.add(blockHashQueue.removeLast());
|
||||
}
|
||||
return hashes;
|
||||
}
|
||||
|
||||
// a bit ugly but really gives
|
||||
// good result
|
||||
public void logHashQueueSize(){
|
||||
public void logHashQueueSize() {
|
||||
logger.info("Block hashes list size: [{}]", blockHashQueue.size());
|
||||
}
|
||||
|
||||
@ -213,11 +222,11 @@ public class BlockQueue {
|
||||
return blockReceivedQueue.size();
|
||||
}
|
||||
|
||||
public boolean isHashesEmpty(){
|
||||
public boolean isHashesEmpty() {
|
||||
return blockHashQueue.size() == 0;
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
public void clear() {
|
||||
this.blockHashQueue.clear();
|
||||
this.blockReceivedQueue.clear();
|
||||
}
|
||||
|
@ -16,16 +16,16 @@ import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* This class contains the logic for sending messages in a queue
|
||||
* This class contains the logic for sending messages in a queue
|
||||
*
|
||||
* Messages open by send and answered by receive of appropriate message
|
||||
* Messages open by send and answered by receive of appropriate message
|
||||
* PING by PONG
|
||||
* GET_PEERS by PEERS
|
||||
* GET_TRANSACTIONS by TRANSACTIONS
|
||||
* GET_BLOCK_HASHES by BLOCK_HASHES
|
||||
* GET_BLOCKS by BLOCKS
|
||||
*
|
||||
* The following messages will not be answered:
|
||||
* The following messages will not be answered:
|
||||
* PONG, PEERS, HELLO, STATUS, TRANSACTIONS, BLOCKS
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
@ -44,9 +44,10 @@ public class MessageQueue {
|
||||
WorldManager worldManager;
|
||||
boolean hasPing = false;
|
||||
|
||||
public MessageQueue(){}
|
||||
public MessageQueue() {
|
||||
}
|
||||
|
||||
public void activate(ChannelHandlerContext ctx){
|
||||
public void activate(ChannelHandlerContext ctx) {
|
||||
this.ctx = ctx;
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
@ -117,7 +118,7 @@ public class MessageQueue {
|
||||
}
|
||||
}
|
||||
|
||||
public void close(){
|
||||
public void close() {
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class Capability implements Comparable<Capability> {
|
||||
if (this == obj) return true;
|
||||
if (!(obj instanceof Capability)) return false;
|
||||
|
||||
Capability other = (Capability)obj;
|
||||
Capability other = (Capability) obj;
|
||||
if (this.name == null)
|
||||
return other.name == null;
|
||||
else
|
||||
|
@ -22,6 +22,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
/**
|
||||
* This class creates the connection to an remote address using the Netty framework
|
||||
*
|
||||
* @see <a href="http://netty.io">http://netty.io</a>
|
||||
*/
|
||||
@Component
|
||||
|
@ -18,7 +18,9 @@ import org.ethereum.util.Utils;
|
||||
*/
|
||||
public class BlockHashesMessage extends EthMessage {
|
||||
|
||||
/** List of block hashes from the peer ordered from child to parent */
|
||||
/**
|
||||
* List of block hashes from the peer ordered from child to parent
|
||||
*/
|
||||
private List<byte[]> blockHashes;
|
||||
|
||||
public BlockHashesMessage(byte[] payload) {
|
||||
@ -69,7 +71,7 @@ public class BlockHashesMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.BLOCK_HASHES;
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ public class BlocksMessage extends EthMessage {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public BlocksMessage(List<Block> blocks){
|
||||
public BlocksMessage(List<Block> blocks) {
|
||||
this.blocks = blocks;
|
||||
parsed = true;
|
||||
}
|
||||
@ -45,7 +45,7 @@ public class BlocksMessage extends EthMessage {
|
||||
List<byte[]> encodedElements = new Vector<>();
|
||||
encodedElements.add(RLP.encodeByte(BLOCKS.asByte()));
|
||||
|
||||
for (Block block : blocks){
|
||||
for (Block block : blocks) {
|
||||
encodedElements.add(block.getEncoded());
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ public class BlocksMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.BLOCKS;
|
||||
}
|
||||
|
||||
|
@ -73,7 +73,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
private List<byte[]> sentHashes;
|
||||
private Block lastBlock = Genesis.getInstance();
|
||||
|
||||
public EthHandler(){
|
||||
public EthHandler() {
|
||||
this.peerDiscoveryMode = false;
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
this.msgQueue = msgQueue;
|
||||
}
|
||||
|
||||
public void activate(){
|
||||
public void activate() {
|
||||
logger.info("ETH protocol activated");
|
||||
worldManager.getListener().trace("ETH protocol activated");
|
||||
|
||||
@ -95,7 +95,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
}
|
||||
|
||||
|
||||
public boolean isActive(){
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
@ -121,7 +121,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
break;
|
||||
case TRANSACTIONS:
|
||||
msgQueue.receivedMessage(msg);
|
||||
processTransactions((TransactionsMessage)msg);
|
||||
processTransactions((TransactionsMessage) msg);
|
||||
// List<Transaction> txList = transactionsMessage.getTransactions();
|
||||
// for(Transaction tx : txList)
|
||||
// WorldManager.getInstance().getBlockchain().applyTransaction(null,
|
||||
@ -138,7 +138,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
break;
|
||||
case GET_BLOCKS:
|
||||
msgQueue.receivedMessage(msg);
|
||||
processGetBlocks( (GetBlocksMessage) msg );
|
||||
processGetBlocks((GetBlocksMessage) msg);
|
||||
break;
|
||||
case BLOCKS:
|
||||
msgQueue.receivedMessage(msg);
|
||||
@ -146,7 +146,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
break;
|
||||
case NEW_BLOCK:
|
||||
msgQueue.receivedMessage(msg);
|
||||
procesNewBlock((NewBlockMessage)msg);
|
||||
procesNewBlock((NewBlockMessage) msg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -157,7 +157,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
Set<Transaction> txSet = msg.getTransactions();
|
||||
worldManager.addPendingTransactions(txSet);
|
||||
|
||||
for (Transaction tx : txSet){
|
||||
for (Transaction tx : txSet) {
|
||||
worldManager.getWallet().addTransaction(tx);
|
||||
}
|
||||
}
|
||||
@ -210,11 +210,11 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
BigInteger peerTotalDifficulty = new BigInteger(1, msg.getTotalDifficulty());
|
||||
BigInteger highestKnownTotalDifficulty = blockchain.getTotalDifficulty();
|
||||
|
||||
boolean synced=
|
||||
FastByteComparisons.compareTo(msg.getBestHash(), 0, 32, blockchain.getBestBlockHash(), 0, 32) == 0;
|
||||
boolean synced =
|
||||
FastByteComparisons.compareTo(msg.getBestHash(), 0, 32, blockchain.getBestBlockHash(), 0, 32) == 0;
|
||||
|
||||
if ( !synced && (highestKnownTotalDifficulty == null ||
|
||||
peerTotalDifficulty.compareTo(highestKnownTotalDifficulty) > 0)) {
|
||||
if (!synced && (highestKnownTotalDifficulty == null ||
|
||||
peerTotalDifficulty.compareTo(highestKnownTotalDifficulty) > 0)) {
|
||||
|
||||
logger.info(" Their chain is better: total difficulty : {} vs {}",
|
||||
peerTotalDifficulty.toString(),
|
||||
@ -225,7 +225,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
chainQueue.setBestHash(msg.getBestHash());
|
||||
syncStatus = SyncSatus.HASH_RETRIEVING;
|
||||
sendGetBlockHashes();
|
||||
} else{
|
||||
} else {
|
||||
logger.info("The peer sync process fully complete");
|
||||
syncStatus = SyncSatus.SYNC_DONE;
|
||||
}
|
||||
@ -249,10 +249,9 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
byte[] foundHash, latestHash = blockchain.getBestBlockHash();
|
||||
while (hashIterator.hasNext()) {
|
||||
foundHash = hashIterator.next();
|
||||
if (FastByteComparisons.compareTo(foundHash, 0, 32, latestHash, 0, 32) != 0){
|
||||
if (FastByteComparisons.compareTo(foundHash, 0, 32, latestHash, 0, 32) != 0) {
|
||||
chainQueue.addHash(foundHash); // store unknown hashes in queue until known hash is found
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
|
||||
logger.trace("Catch up with the hashes until: {[]}", foundHash);
|
||||
// if known hash is found, ignore the rest
|
||||
@ -270,10 +269,10 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
List<Block> blockList = blocksMessage.getBlocks();
|
||||
|
||||
if (!blockList.isEmpty())
|
||||
lastBlock = blockList.get(blockList.size()-1);
|
||||
lastBlock = blockList.get(blockList.size() - 1);
|
||||
|
||||
// check if you got less blocks than you asked
|
||||
if (blockList.size() < sentHashes.size()){
|
||||
if (blockList.size() < sentHashes.size()) {
|
||||
for (int i = 0; i < blockList.size(); ++i)
|
||||
sentHashes.remove(0);
|
||||
|
||||
@ -287,14 +286,14 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
syncStatus = SyncSatus.SYNC_DONE;
|
||||
blockchain.getQueue().addBlocks(blockList);
|
||||
blockchain.getQueue().logHashQueueSize();
|
||||
} else{
|
||||
} else {
|
||||
if (blockList.isEmpty()) return;
|
||||
blockchain.getQueue().addBlocks(blockList);
|
||||
blockchain.getQueue().logHashQueueSize();
|
||||
sendGetBlocks();
|
||||
}
|
||||
|
||||
for (Block block : blockList){
|
||||
for (Block block : blockList) {
|
||||
totalDifficulty.add(block.getCumulativeDifficulty());
|
||||
}
|
||||
}
|
||||
@ -302,9 +301,10 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
|
||||
/**
|
||||
* Processing NEW_BLOCK announce message
|
||||
*
|
||||
* @param newBlockMessage - new block message
|
||||
*/
|
||||
public void procesNewBlock(NewBlockMessage newBlockMessage){
|
||||
public void procesNewBlock(NewBlockMessage newBlockMessage) {
|
||||
|
||||
Block newBlock = newBlockMessage.getBlock();
|
||||
this.lastBlock = newBlock;
|
||||
@ -320,7 +320,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
|
||||
// If the GET_BLOCKs stage started add hash to the end of the hash list
|
||||
// then the block will be retrieved in it's turn;
|
||||
if (syncStatus == SyncSatus.BLOCK_RETRIEVING){
|
||||
if (syncStatus == SyncSatus.BLOCK_RETRIEVING) {
|
||||
logger.debug("Sync status BLOCK_RETREIVING add to the end of hash list: block.index: [{}]",
|
||||
newBlock.getNumber());
|
||||
blockchain.getQueue().addNewBlockHash(newBlock.getHash());
|
||||
@ -338,7 +338,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
totalDifficulty = new BigInteger(1, newBlockMessage.getDifficulty());
|
||||
}
|
||||
|
||||
private void sendStatus(){
|
||||
private void sendStatus() {
|
||||
byte protocolVersion = EthHandler.VERSION, networkId = EthHandler.NETWORK_ID;
|
||||
BigInteger totalDifficulty = blockchain.getTotalDifficulty();
|
||||
byte[] bestHash = blockchain.getBestBlockHash();
|
||||
@ -357,7 +357,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
msgQueue.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void sendNewBlock(Block block){
|
||||
public void sendNewBlock(Block block) {
|
||||
NewBlockMessage msg = new NewBlockMessage(block, block.getDifficulty());
|
||||
msgQueue.sendMessage(msg);
|
||||
}
|
||||
@ -375,7 +375,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
// Parallel download blocks based on hashQueue
|
||||
private void sendGetBlocks() {
|
||||
BlockQueue queue = blockchain.getQueue();
|
||||
if (queue.size() > CONFIG.maxBlocksQueued()){
|
||||
if (queue.size() > CONFIG.maxBlocksQueued()) {
|
||||
|
||||
logger.info("postpone asking for blocks: queue: {}", queue.size());
|
||||
getBlocksTimer.schedule(new TimerTask() {
|
||||
@ -420,8 +420,8 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
List<byte[]> hashes = msg.getBlockHashes();
|
||||
|
||||
Vector<Block> blocks = new Vector<>();
|
||||
for (byte[] hash : hashes){
|
||||
Block block = blockchain.getBlockByHash(hash);
|
||||
for (byte[] hash : hashes) {
|
||||
Block block = blockchain.getBlockByHash(hash);
|
||||
blocks.add(block);
|
||||
}
|
||||
|
||||
@ -468,37 +468,37 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||
stopGetTxTimer();
|
||||
}
|
||||
|
||||
public void setSyncStatus(SyncSatus syncStatus){
|
||||
public void setSyncStatus(SyncSatus syncStatus) {
|
||||
this.syncStatus = syncStatus;
|
||||
}
|
||||
|
||||
public SyncSatus getSyncStatus(){
|
||||
public SyncSatus getSyncStatus() {
|
||||
return syncStatus;
|
||||
}
|
||||
|
||||
public void setPeerId(String peerId){
|
||||
public void setPeerId(String peerId) {
|
||||
this.peerId = peerId;
|
||||
}
|
||||
|
||||
public enum SyncSatus{
|
||||
public enum SyncSatus {
|
||||
INIT,
|
||||
HASH_RETRIEVING,
|
||||
BLOCK_RETRIEVING,
|
||||
SYNC_DONE;
|
||||
}
|
||||
|
||||
public void setBestHash(byte[] hash){
|
||||
public void setBestHash(byte[] hash) {
|
||||
blockchain.getQueue().addHash(hash);
|
||||
}
|
||||
|
||||
public void doSync(){
|
||||
public void doSync() {
|
||||
logger.info("Sync force activated");
|
||||
syncStatus = SyncSatus.HASH_RETRIEVING;
|
||||
setBestHash(lastBlock.getHash());
|
||||
sendGetBlockHashes();
|
||||
}
|
||||
|
||||
public StatusMessage getHandshakeStatusMessage(){
|
||||
public StatusMessage getHandshakeStatusMessage() {
|
||||
return handshakeStatusMessage;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,8 @@ import org.ethereum.net.message.Message;
|
||||
|
||||
public abstract class EthMessage extends Message {
|
||||
|
||||
public EthMessage() {}
|
||||
public EthMessage() {
|
||||
}
|
||||
|
||||
public EthMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
|
@ -15,50 +15,65 @@ public enum EthMessageCodes {
|
||||
|
||||
/* Ethereum protocol */
|
||||
|
||||
/** [0x00, [PROTOCOL_VERSION, NETWORK_ID, TD, BEST_HASH, GENESIS_HASH] <br>
|
||||
/**
|
||||
* [0x00, [PROTOCOL_VERSION, NETWORK_ID, TD, BEST_HASH, GENESIS_HASH] <br>
|
||||
* Inform a peer of it's current ethereum state. This message should be
|
||||
* send after the initial handshake and prior to any ethereum related messages. */
|
||||
* send after the initial handshake and prior to any ethereum related messages.
|
||||
*/
|
||||
STATUS(0x00),
|
||||
|
||||
/** [+0x01] Request the peer to send all transactions
|
||||
* currently in the queue. */
|
||||
/**
|
||||
* [+0x01] Request the peer to send all transactions
|
||||
* currently in the queue.
|
||||
*/
|
||||
GET_TRANSACTIONS(0x01),
|
||||
|
||||
/** [+0x02, [nonce, receiving_address, value, ...], ...] <br>
|
||||
/**
|
||||
* [+0x02, [nonce, receiving_address, value, ...], ...] <br>
|
||||
* Specify (a) transaction(s) that the peer should make sure is included
|
||||
* on its transaction queue. The items in the list (following the first item 0x12)
|
||||
* are transactions in the format described in the main Ethereum specification. */
|
||||
* are transactions in the format described in the main Ethereum specification.
|
||||
*/
|
||||
TRANSACTIONS(0x02),
|
||||
|
||||
/** [+0x03, [hash : B_32, maxBlocks: P]: <br>
|
||||
/**
|
||||
* [+0x03, [hash : B_32, maxBlocks: P]: <br>
|
||||
* Requests a BlockHashes message of at most maxBlocks entries,
|
||||
* of block hashes from the blockchain, starting at the parent of block hash.
|
||||
* Does not require the peer to give maxBlocks hashes -
|
||||
* they could give somewhat fewer. */
|
||||
* they could give somewhat fewer.
|
||||
*/
|
||||
GET_BLOCK_HASHES(0x03),
|
||||
|
||||
/** [+0x04, [hash_0: B_32, hash_1: B_32, ....]: <br>Gives a series of hashes
|
||||
/**
|
||||
* [+0x04, [hash_0: B_32, hash_1: B_32, ....]: <br>Gives a series of hashes
|
||||
* of blocks (each the child of the next). This implies that the blocks
|
||||
* are ordered from youngest to oldest. */
|
||||
* are ordered from youngest to oldest.
|
||||
*/
|
||||
BLOCK_HASHES(0x04),
|
||||
|
||||
/** [+0x05, [hash_0: B_32, hash_1: B_32, ....]: <br>Requests a Blocks message
|
||||
/**
|
||||
* [+0x05, [hash_0: B_32, hash_1: B_32, ....]: <br>Requests a Blocks message
|
||||
* detailing a number of blocks to be sent, each referred to by a hash. <br>
|
||||
* <b>Note:</b> Don't expect that the peer necessarily give you all these blocks
|
||||
* in a single message - you might have to re-request them. */
|
||||
* in a single message - you might have to re-request them.
|
||||
*/
|
||||
GET_BLOCKS(0x05),
|
||||
|
||||
/** [+0x06, [block_header, transaction_list, uncle_list], ...] <br>
|
||||
/**
|
||||
* [+0x06, [block_header, transaction_list, uncle_list], ...] <br>
|
||||
* Specify (a) block(s) that the peer should know about.
|
||||
* The items in the list (following the first item, 0x13)
|
||||
* are blocks in the format described in the main Ethereum specification. */
|
||||
* are blocks in the format described in the main Ethereum specification.
|
||||
*/
|
||||
BLOCKS(0x06),
|
||||
|
||||
/**
|
||||
* [+0x07 [blockHeader, transactionList, uncleList], totalDifficulty] <br>
|
||||
* Specify a single block that the peer should know about. The composite item
|
||||
* in the list (following the message ID) is a block in the format described
|
||||
* in the main Ethereum specification. */
|
||||
* in the main Ethereum specification.
|
||||
*/
|
||||
NEW_BLOCK(0x07),
|
||||
|
||||
/**
|
||||
@ -70,6 +85,7 @@ public enum EthMessageCodes {
|
||||
private int cmd;
|
||||
|
||||
private static final Map<Integer, EthMessageCodes> intToTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (EthMessageCodes type : EthMessageCodes.values()) {
|
||||
intToTypeMap.put(type.cmd, type);
|
||||
@ -85,14 +101,15 @@ public enum EthMessageCodes {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean inRange(byte code){
|
||||
public static boolean inRange(byte code) {
|
||||
return code >= STATUS.asByte() && code <= PACKET_COUNT.asByte();
|
||||
}
|
||||
|
||||
public static void setOffset(byte offset){
|
||||
public static void setOffset(byte offset) {
|
||||
EthMessageCodes.OFFSET = offset;
|
||||
}
|
||||
|
||||
public byte asByte() {
|
||||
return (byte) (cmd + OFFSET);
|
||||
return (byte) (cmd + OFFSET);
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,15 @@ import org.spongycastle.util.encoders.Hex;
|
||||
*/
|
||||
public class GetBlockHashesMessage extends EthMessage {
|
||||
|
||||
/** The newest block hash from which to start sending older hashes */
|
||||
/**
|
||||
* The newest block hash from which to start sending older hashes
|
||||
*/
|
||||
private byte[] bestHash;
|
||||
|
||||
/** The maximum number of blocks to return.
|
||||
* <b>Note:</b> the peer could return fewer. */
|
||||
/**
|
||||
* The maximum number of blocks to return.
|
||||
* <b>Note:</b> the peer could return fewer.
|
||||
*/
|
||||
private int maxBlocks;
|
||||
|
||||
public GetBlockHashesMessage(byte[] encoded) {
|
||||
@ -51,7 +55,7 @@ public class GetBlockHashesMessage extends EthMessage {
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
if(encoded == null) encode();
|
||||
if (encoded == null) encode();
|
||||
return encoded;
|
||||
}
|
||||
|
||||
@ -72,7 +76,7 @@ public class GetBlockHashesMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.GET_BLOCK_HASHES;
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,9 @@ import static org.ethereum.net.eth.EthMessageCodes.GET_BLOCKS;
|
||||
*/
|
||||
public class GetBlocksMessage extends EthMessage {
|
||||
|
||||
/** List of block hashes for which to retrieve the blocks */
|
||||
/**
|
||||
* List of block hashes for which to retrieve the blocks
|
||||
*/
|
||||
private List<byte[]> blockHashes;
|
||||
|
||||
public GetBlocksMessage(byte[] encoded) {
|
||||
@ -67,7 +69,7 @@ public class GetBlocksMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.GET_BLOCKS;
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,9 @@ import org.spongycastle.util.encoders.Hex;
|
||||
*/
|
||||
public class GetTransactionsMessage extends EthMessage {
|
||||
|
||||
/** GetTransactions message is always a the same single command payload */
|
||||
/**
|
||||
* GetTransactions message is always a the same single command payload
|
||||
*/
|
||||
private final static byte[] FIXED_PAYLOAD = Hex.decode("C116");
|
||||
|
||||
public byte[] getEncoded() {
|
||||
@ -24,7 +26,7 @@ public class GetTransactionsMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.GET_TRANSACTIONS;
|
||||
}
|
||||
|
||||
|
@ -19,16 +19,16 @@ public class NewBlockMessage extends EthMessage {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public NewBlockMessage(Block block, byte[] difficulty){
|
||||
public NewBlockMessage(Block block, byte[] difficulty) {
|
||||
this.block = block;
|
||||
this.difficulty = difficulty;
|
||||
encode();
|
||||
}
|
||||
|
||||
private void encode(){
|
||||
byte[] command = RLP.encodeByte( this.getCommand().asByte());
|
||||
private void encode() {
|
||||
byte[] command = RLP.encodeByte(this.getCommand().asByte());
|
||||
byte[] block = this.block.getEncoded();
|
||||
byte[] diff = RLP.encodeElement(this.difficulty);
|
||||
byte[] diff = RLP.encodeElement(this.difficulty);
|
||||
|
||||
this.encoded = RLP.encodeList(command, block, diff);
|
||||
parsed = true;
|
||||
@ -39,17 +39,17 @@ public class NewBlockMessage extends EthMessage {
|
||||
|
||||
RLPList blockRLP = ((RLPList) paramsList.get(1));
|
||||
block = new Block(blockRLP.getRLPData());
|
||||
difficulty = paramsList.get(2).getRLPData();
|
||||
difficulty = paramsList.get(2).getRLPData();
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
public Block getBlock(){
|
||||
public Block getBlock() {
|
||||
if (!parsed) parse();
|
||||
return block;
|
||||
}
|
||||
|
||||
public byte[] getDifficulty(){
|
||||
public byte[] getDifficulty() {
|
||||
if (!parsed) parse();
|
||||
return difficulty;
|
||||
}
|
||||
@ -60,7 +60,7 @@ public class NewBlockMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.NEW_BLOCK;
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,6 @@ import org.ethereum.util.RLP;
|
||||
|
||||
/**
|
||||
* Wrapper around an Ethereum Ping message on the network
|
||||
*
|
||||
*/
|
||||
public class PacketCountMessage extends EthMessage {
|
||||
|
||||
@ -23,7 +22,7 @@ public class PacketCountMessage extends EthMessage {
|
||||
}
|
||||
|
||||
private void encode() {
|
||||
this.encoded = RLP.encodeList(new byte[] {EthMessageCodes.STATUS.asByte()} );
|
||||
this.encoded = RLP.encodeList(new byte[]{EthMessageCodes.STATUS.asByte()});
|
||||
}
|
||||
|
||||
|
||||
@ -33,7 +32,7 @@ public class PacketCountMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.PACKET_COUNT;
|
||||
}
|
||||
|
||||
|
@ -18,11 +18,17 @@ public class StatusMessage extends EthMessage {
|
||||
private byte protocolVersion;
|
||||
private byte networkId;
|
||||
|
||||
/** Total difficulty of the best chain as found in block header. */
|
||||
/**
|
||||
* Total difficulty of the best chain as found in block header.
|
||||
*/
|
||||
private byte[] totalDifficulty;
|
||||
/** The hash of the best (i.e. highest TD) known block. */
|
||||
/**
|
||||
* The hash of the best (i.e. highest TD) known block.
|
||||
*/
|
||||
private byte[] bestHash;
|
||||
/** The hash of the Genesis block */
|
||||
/**
|
||||
* The hash of the Genesis block
|
||||
*/
|
||||
private byte[] genesisHash;
|
||||
|
||||
public StatusMessage(byte[] encoded) {
|
||||
@ -30,7 +36,7 @@ public class StatusMessage extends EthMessage {
|
||||
}
|
||||
|
||||
public StatusMessage(byte protocolVersion, byte networkId,
|
||||
byte[] totalDifficulty, byte[] bestHash, byte[] genesisHash) {
|
||||
byte[] totalDifficulty, byte[] bestHash, byte[] genesisHash) {
|
||||
this.protocolVersion = protocolVersion;
|
||||
this.networkId = networkId;
|
||||
this.totalDifficulty = totalDifficulty;
|
||||
@ -42,23 +48,23 @@ public class StatusMessage extends EthMessage {
|
||||
private void parse() {
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
this.protocolVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0];
|
||||
byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
|
||||
this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0];
|
||||
this.totalDifficulty = ((RLPItem) paramsList.get(3)).getRLPData();
|
||||
this.bestHash = ((RLPItem) paramsList.get(4)).getRLPData();
|
||||
this.genesisHash = ((RLPItem) paramsList.get(5)).getRLPData();
|
||||
this.protocolVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0];
|
||||
byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
|
||||
this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0];
|
||||
this.totalDifficulty = ((RLPItem) paramsList.get(3)).getRLPData();
|
||||
this.bestHash = ((RLPItem) paramsList.get(4)).getRLPData();
|
||||
this.genesisHash = ((RLPItem) paramsList.get(5)).getRLPData();
|
||||
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
private void encode() {
|
||||
byte[] command = RLP.encodeByte(STATUS.asByte());
|
||||
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
|
||||
byte[] networkId = RLP.encodeByte(this.networkId);
|
||||
byte[] totalDifficulty = RLP.encodeElement(this.totalDifficulty);
|
||||
byte[] bestHash = RLP.encodeElement(this.bestHash);
|
||||
byte[] genesisHash = RLP.encodeElement(this.genesisHash);
|
||||
byte[] command = RLP.encodeByte(STATUS.asByte());
|
||||
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
|
||||
byte[] networkId = RLP.encodeByte(this.networkId);
|
||||
byte[] totalDifficulty = RLP.encodeElement(this.totalDifficulty);
|
||||
byte[] bestHash = RLP.encodeElement(this.bestHash);
|
||||
byte[] genesisHash = RLP.encodeElement(this.genesisHash);
|
||||
|
||||
this.encoded = RLP.encodeList(command, protocolVersion, networkId,
|
||||
totalDifficulty, bestHash, genesisHash);
|
||||
@ -101,7 +107,7 @@ public class StatusMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return STATUS;
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ public class TransactionsMessage extends EthMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public EthMessageCodes getCommand(){
|
||||
public EthMessageCodes getCommand() {
|
||||
return EthMessageCodes.TRANSACTIONS;
|
||||
}
|
||||
|
||||
@ -82,11 +82,11 @@ public class TransactionsMessage extends EthMessage {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if(!parsed) parse();
|
||||
if (!parsed) parse();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (Transaction transaction : transactions)
|
||||
sb.append("\n ").append(transaction);
|
||||
return "[" + this.getCommand().name() + " num:"
|
||||
+ transactions.size() + " " + sb.toString() + "]";
|
||||
+ transactions.size() + " " + sb.toString() + "]";
|
||||
}
|
||||
}
|
@ -9,10 +9,11 @@ package org.ethereum.net.message;
|
||||
public abstract class Message {
|
||||
|
||||
protected boolean parsed;
|
||||
protected byte[] encoded;
|
||||
protected byte[] encoded;
|
||||
protected byte code;
|
||||
|
||||
public Message() {}
|
||||
public Message() {
|
||||
}
|
||||
|
||||
public Message(byte[] encoded) {
|
||||
this.encoded = encoded;
|
||||
|
@ -13,7 +13,7 @@ public class MessageFactory {
|
||||
public static Message createMessage(byte[] encoded) {
|
||||
byte code = RLP.getCommandCode(encoded);
|
||||
|
||||
if (P2pMessageCodes.inRange(code)){
|
||||
if (P2pMessageCodes.inRange(code)) {
|
||||
|
||||
P2pMessageCodes receivedCommand = P2pMessageCodes.fromByte(code);
|
||||
switch (receivedCommand) {
|
||||
|
@ -9,39 +9,60 @@ import java.util.Map;
|
||||
*/
|
||||
public enum ReasonCode {
|
||||
|
||||
/** [0x00] Disconnect request by other peer */
|
||||
/**
|
||||
* [0x00] Disconnect request by other peer
|
||||
*/
|
||||
REQUESTED(0x00),
|
||||
|
||||
/** [0x01] */
|
||||
/**
|
||||
* [0x01]
|
||||
*/
|
||||
TCP_ERROR(0x01),
|
||||
|
||||
/** [0x02] Packets can not be parsed */
|
||||
/**
|
||||
* [0x02] Packets can not be parsed
|
||||
*/
|
||||
BAD_PROTOCOL(0x02),
|
||||
|
||||
/** [0x03] This peer is too slow or delivers unreliable data */
|
||||
/**
|
||||
* [0x03] This peer is too slow or delivers unreliable data
|
||||
*/
|
||||
USELESS_PEER(0x03),
|
||||
|
||||
/** [0x04] Already too many connections with other peers */
|
||||
/**
|
||||
* [0x04] Already too many connections with other peers
|
||||
*/
|
||||
TOO_MANY_PEERS(0x04),
|
||||
|
||||
/** [0x05] Already have a running connection with this peer */
|
||||
/**
|
||||
* [0x05] Already have a running connection with this peer
|
||||
*/
|
||||
ALREADY_CONNECTED(0x05),
|
||||
|
||||
/** [0x06] Version of the p2p protocol is not the same as ours */
|
||||
/**
|
||||
* [0x06] Version of the p2p protocol is not the same as ours
|
||||
*/
|
||||
INCOMPATIBLE_PROTOCOL(0x06),
|
||||
|
||||
/** [0x07] Peer identifies itself with the wrong networkId */
|
||||
/**
|
||||
* [0x07] Peer identifies itself with the wrong networkId
|
||||
*/
|
||||
INCOMPATIBLE_NETWORK(0x07),
|
||||
|
||||
/** [0x08] Peer quit voluntarily */
|
||||
/**
|
||||
* [0x08] Peer quit voluntarily
|
||||
*/
|
||||
PEER_QUITING(0x08),
|
||||
|
||||
/** [0xFF] Reason not specified */
|
||||
/**
|
||||
* [0xFF] Reason not specified
|
||||
*/
|
||||
UNKNOWN(0xFF);
|
||||
|
||||
private int reason;
|
||||
|
||||
private static final Map<Integer, ReasonCode> intToTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (ReasonCode type : ReasonCode.values()) {
|
||||
intToTypeMap.put(type.reason, type);
|
||||
|
@ -2,7 +2,8 @@ package org.ethereum.net.message;
|
||||
|
||||
public abstract class ShhMessage extends Message {
|
||||
|
||||
public ShhMessage() {}
|
||||
public ShhMessage() {
|
||||
}
|
||||
|
||||
public ShhMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
|
@ -27,10 +27,10 @@ public class StaticMessages {
|
||||
|
||||
public static final String PEER_ID = Hex.toHexString(HashUtil.randomPeerId());
|
||||
|
||||
public final static PingMessage PING_MESSAGE = new PingMessage();
|
||||
public final static PongMessage PONG_MESSAGE = new PongMessage();
|
||||
public final static HelloMessage HELLO_MESSAGE = generateHelloMessage();
|
||||
public final static GetPeersMessage GET_PEERS_MESSAGE = new GetPeersMessage();
|
||||
public final static PingMessage PING_MESSAGE = new PingMessage();
|
||||
public final static PongMessage PONG_MESSAGE = new PongMessage();
|
||||
public final static HelloMessage HELLO_MESSAGE = generateHelloMessage();
|
||||
public final static GetPeersMessage GET_PEERS_MESSAGE = new GetPeersMessage();
|
||||
public final static GetTransactionsMessage GET_TRANSACTIONS_MESSAGE = new GetTransactionsMessage();
|
||||
|
||||
public static final byte[] SYNC_TOKEN = Hex.decode("22400891");
|
||||
|
@ -52,7 +52,7 @@ public class DisconnectMessage extends P2pMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public P2pMessageCodes getCommand(){
|
||||
public P2pMessageCodes getCommand() {
|
||||
return P2pMessageCodes.DISCONNECT;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,9 @@ import org.spongycastle.util.encoders.Hex;
|
||||
*/
|
||||
public class GetPeersMessage extends P2pMessage {
|
||||
|
||||
/** GetPeers message is always a the same single command payload */
|
||||
/**
|
||||
* GetPeers message is always a the same single command payload
|
||||
*/
|
||||
private final static byte[] FIXED_PAYLOAD = Hex.decode("C104");
|
||||
|
||||
@Override
|
||||
@ -18,7 +20,7 @@ public class GetPeersMessage extends P2pMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public P2pMessageCodes getCommand(){
|
||||
public P2pMessageCodes getCommand() {
|
||||
return P2pMessageCodes.GET_PEERS;
|
||||
}
|
||||
|
||||
|
@ -20,16 +20,26 @@ import java.util.List;
|
||||
*/
|
||||
public class HelloMessage extends P2pMessage {
|
||||
|
||||
/** The implemented version of the P2P protocol. */
|
||||
/**
|
||||
* The implemented version of the P2P protocol.
|
||||
*/
|
||||
private byte p2pVersion;
|
||||
/** The underlying client. A user-readable string. */
|
||||
/**
|
||||
* The underlying client. A user-readable string.
|
||||
*/
|
||||
private String clientId;
|
||||
/** A peer-network capability code, readable ASCII and 3 letters.
|
||||
* Currently only "eth", "shh" and "bzz" are known. */
|
||||
/**
|
||||
* A peer-network capability code, readable ASCII and 3 letters.
|
||||
* Currently only "eth", "shh" and "bzz" are known.
|
||||
*/
|
||||
private List<Capability> capabilities;
|
||||
/** The port on which the peer is listening for an incoming connection */
|
||||
/**
|
||||
* The port on which the peer is listening for an incoming connection
|
||||
*/
|
||||
private int listenPort;
|
||||
/** The identity and public key of the peer */
|
||||
/**
|
||||
* The identity and public key of the peer
|
||||
*/
|
||||
private String peerId;
|
||||
|
||||
public HelloMessage(byte[] encoded) {
|
||||
@ -62,8 +72,8 @@ public class HelloMessage extends P2pMessage {
|
||||
this.capabilities = new ArrayList<>();
|
||||
for (int i = 0; i < capabilityList.size(); i++) {
|
||||
|
||||
RLPElement capId = ((RLPList)capabilityList.get(i)).get(0);
|
||||
RLPElement capVersion = ((RLPList)capabilityList.get(i)).get(1);
|
||||
RLPElement capId = ((RLPList) capabilityList.get(i)).get(0);
|
||||
RLPElement capVersion = ((RLPList) capabilityList.get(i)).get(1);
|
||||
|
||||
String name = new String(capId.getRLPData());
|
||||
byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0];
|
||||
@ -89,7 +99,7 @@ public class HelloMessage extends P2pMessage {
|
||||
Capability capability = this.capabilities.get(i);
|
||||
capabilities[i] = RLP.encodeList(
|
||||
RLP.encodeElement(capability.getName().getBytes()),
|
||||
RLP.encodeElement(new byte[] {capability.getVersion() }));
|
||||
RLP.encodeElement(new byte[]{capability.getVersion()}));
|
||||
}
|
||||
byte[] capabilityList = RLP.encodeList(capabilities);
|
||||
byte[] peerPort = RLP.encodeInt(this.listenPort);
|
||||
@ -131,7 +141,7 @@ public class HelloMessage extends P2pMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public P2pMessageCodes getCommand(){
|
||||
public P2pMessageCodes getCommand() {
|
||||
return P2pMessageCodes.HELLO;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
startTimers();
|
||||
}
|
||||
|
||||
public void activate(){
|
||||
public void activate() {
|
||||
|
||||
// logger.info("Incoming connection from: {}", ch.remoteAddress().toString());
|
||||
|
||||
@ -100,7 +100,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
worldManager.getListener().trace("P2P protocol activated");
|
||||
}
|
||||
|
||||
public boolean isActive(){
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
@ -112,7 +112,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
if (P2pMessageCodes.inRange(msg.getCommand().asByte()))
|
||||
logger.info("P2PHandler invoke: [{}]", msg.getCommand());
|
||||
|
||||
worldManager.getListener().trace(String.format( "P2PHandler invoke: [%s]", msg.getCommand()));
|
||||
worldManager.getListener().trace(String.format("P2PHandler invoke: [%s]", msg.getCommand()));
|
||||
|
||||
switch (msg.getCommand()) {
|
||||
case HELLO:
|
||||
@ -139,7 +139,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
processPeers(ctx, (PeersMessage) msg);
|
||||
|
||||
if (peerDiscoveryMode &&
|
||||
!handshakeHelloMessage.getCapabilities().contains(Capability.ETH)){
|
||||
!handshakeHelloMessage.getCapabilities().contains(Capability.ETH)) {
|
||||
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.REQUESTED));
|
||||
killTimers();
|
||||
ctx.close().sync();
|
||||
@ -172,21 +172,21 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
worldManager.getPeerDiscovery().addPeers(peersMessage.getPeers());
|
||||
}
|
||||
|
||||
private void sendGetPeers(){
|
||||
msgQueue.sendMessage( StaticMessages.GET_PEERS_MESSAGE );
|
||||
private void sendGetPeers() {
|
||||
msgQueue.sendMessage(StaticMessages.GET_PEERS_MESSAGE);
|
||||
}
|
||||
|
||||
private void sendPeers() {
|
||||
|
||||
Set<PeerInfo> peers = worldManager.getPeerDiscovery().getPeers();
|
||||
|
||||
if (lastPeersSent != null && peers.equals(lastPeersSent)){
|
||||
if (lastPeersSent != null && peers.equals(lastPeersSent)) {
|
||||
logger.info("No new peers discovered don't answer for GetPeers");
|
||||
return;
|
||||
}
|
||||
|
||||
Set<Peer> peerSet = new HashSet<>();
|
||||
for (PeerInfo peer : peers){
|
||||
for (PeerInfo peer : peers) {
|
||||
new Peer(peer.getAddress(), peer.getPort(), peer.getPeerId());
|
||||
}
|
||||
|
||||
@ -205,20 +205,19 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
List<Capability> capInCommon = new ArrayList<>();
|
||||
for (Capability capability : msg.getCapabilities()) {
|
||||
if (HELLO_MESSAGE.getCapabilities().contains(capability)) {
|
||||
if (capability.getName().equals(Capability.ETH)){
|
||||
if (capability.getName().equals(Capability.ETH)) {
|
||||
|
||||
// Activate EthHandler for this peer
|
||||
EthHandler ethHandler =
|
||||
(EthHandler)ctx.pipeline().get(Capability.ETH);
|
||||
(EthHandler) ctx.pipeline().get(Capability.ETH);
|
||||
|
||||
ethHandler.setPeerId(msg.getPeerId());
|
||||
ethHandler.activate();
|
||||
}
|
||||
else if (capability.getName().equals(Capability.SHH)){
|
||||
} else if (capability.getName().equals(Capability.SHH)) {
|
||||
|
||||
// Activate ShhHandler for this peer
|
||||
ShhHandler shhHandler =
|
||||
(ShhHandler)ctx.pipeline().get(Capability.SHH);
|
||||
(ShhHandler) ctx.pipeline().get(Capability.SHH);
|
||||
shhHandler.activate();
|
||||
}
|
||||
capInCommon.add(capability);
|
||||
@ -239,15 +238,16 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
|
||||
/**
|
||||
* submit transaction to the network
|
||||
*
|
||||
* @param tx - fresh transaction object
|
||||
*/
|
||||
public void sendTransaction(Transaction tx ){
|
||||
public void sendTransaction(Transaction tx) {
|
||||
|
||||
TransactionsMessage msg = new TransactionsMessage(tx);
|
||||
msgQueue.sendMessage(msg);
|
||||
}
|
||||
|
||||
public void sendNewBlock(Block block ){
|
||||
public void sendNewBlock(Block block) {
|
||||
|
||||
NewBlockMessage msg = new NewBlockMessage(block, block.getDifficulty());
|
||||
msgQueue.sendMessage(msg);
|
||||
@ -296,7 +296,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
*/
|
||||
}
|
||||
|
||||
public void killTimers(){
|
||||
public void killTimers() {
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
msgQueue.close();
|
||||
|
@ -5,7 +5,8 @@ import org.ethereum.net.p2p.P2pMessageCodes;
|
||||
|
||||
public abstract class P2pMessage extends Message {
|
||||
|
||||
public P2pMessage() {}
|
||||
public P2pMessage() {
|
||||
}
|
||||
|
||||
public P2pMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
|
@ -8,6 +8,7 @@ import java.util.Map;
|
||||
* <br>
|
||||
* The codes for these commands are the first byte in every packet.
|
||||
* ÐΞV
|
||||
*
|
||||
* @see <a href="https://github.com/ethereum/wiki/wiki/%C3%90%CE%9EVp2p-Wire-Protocol">
|
||||
* https://github.com/ethereum/wiki/wiki/ÐΞVp2p-Wire-Protocol</a>
|
||||
*/
|
||||
@ -15,33 +16,45 @@ public enum P2pMessageCodes {
|
||||
|
||||
/* P2P protocol */
|
||||
|
||||
/** [0x00, P2P_VERSION, CLIEND_ID, CAPS, LISTEN_PORT, CLIENT_ID] <br>
|
||||
/**
|
||||
* [0x00, P2P_VERSION, CLIEND_ID, CAPS, LISTEN_PORT, CLIENT_ID] <br>
|
||||
* First packet sent over the connection, and sent once by both sides.
|
||||
* No other messages may be sent until a Hello is received. */
|
||||
* No other messages may be sent until a Hello is received.
|
||||
*/
|
||||
HELLO(0x00),
|
||||
|
||||
/** [0x01, REASON] <br>Inform the peer that a disconnection is imminent;
|
||||
/**
|
||||
* [0x01, REASON] <br>Inform the peer that a disconnection is imminent;
|
||||
* if received, a peer should disconnect immediately. When sending,
|
||||
* well-behaved hosts give their peers a fighting chance (read: wait 2 seconds)
|
||||
* to disconnect to before disconnecting themselves. */
|
||||
* to disconnect to before disconnecting themselves.
|
||||
*/
|
||||
DISCONNECT(0x01),
|
||||
|
||||
/** [0x02] <br>Requests an immediate reply of Pong from the peer. */
|
||||
/**
|
||||
* [0x02] <br>Requests an immediate reply of Pong from the peer.
|
||||
*/
|
||||
PING(0x02),
|
||||
|
||||
/** [0x03] <br>Reply to peer's Ping packet. */
|
||||
/**
|
||||
* [0x03] <br>Reply to peer's Ping packet.
|
||||
*/
|
||||
PONG(0x03),
|
||||
|
||||
/** [0x04] <br>Request the peer to enumerate some known peers
|
||||
* for us to connect to. This should include the peer itself. */
|
||||
/**
|
||||
* [0x04] <br>Request the peer to enumerate some known peers
|
||||
* for us to connect to. This should include the peer itself.
|
||||
*/
|
||||
GET_PEERS(0x04),
|
||||
|
||||
/** [0x05, [IP1, Port1, Id1], [IP2, Port2, Id2], ... ] <br>
|
||||
/**
|
||||
* [0x05, [IP1, Port1, Id1], [IP2, Port2, Id2], ... ] <br>
|
||||
* Specifies a number of known peers. IP is a 4-byte array 'ABCD'
|
||||
* that should be interpreted as the IP address A.B.C.D.
|
||||
* Port is a 2-byte array that should be interpreted as a
|
||||
* 16-bit big-endian integer. Id is the 512-bit hash that acts
|
||||
* as the unique identifier of the node. */
|
||||
* as the unique identifier of the node.
|
||||
*/
|
||||
PEERS(0x05),
|
||||
|
||||
|
||||
@ -54,6 +67,7 @@ public enum P2pMessageCodes {
|
||||
private int cmd;
|
||||
|
||||
private static final Map<Integer, P2pMessageCodes> intToTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (P2pMessageCodes type : P2pMessageCodes.values()) {
|
||||
intToTypeMap.put(type.cmd, type);
|
||||
@ -69,7 +83,7 @@ public enum P2pMessageCodes {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static boolean inRange(byte code){
|
||||
public static boolean inRange(byte code) {
|
||||
|
||||
if (code >= HELLO.asByte() && code <= USER.asByte())
|
||||
return true;
|
||||
|
@ -47,7 +47,7 @@ public class Peer {
|
||||
byte[] port = RLP.encodeInt(this.port);
|
||||
byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId));
|
||||
byte[][] encodedCaps = new byte[this.capabilities.size()][];
|
||||
for (int i = 0; i < this.capabilities.size()*2; i++) {
|
||||
for (int i = 0; i < this.capabilities.size() * 2; i++) {
|
||||
encodedCaps[i] = RLP.encodeString(this.capabilities.get(i).getName());
|
||||
encodedCaps[i] = RLP.encodeByte(this.capabilities.get(i).getVersion());
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ public class PeersMessage extends P2pMessage {
|
||||
int peerPort = ByteUtil.byteArrayToInt(portBytes);
|
||||
InetAddress address = InetAddress.getByAddress(ipBytes);
|
||||
|
||||
String peerId = peerIdRaw == null ? "" : Hex.toHexString(peerIdRaw);
|
||||
String peerId = peerIdRaw == null ? "" : Hex.toHexString(peerIdRaw);
|
||||
Peer peer = new Peer(address, peerPort, peerId);
|
||||
peers.add(peer);
|
||||
} catch (UnknownHostException e) {
|
||||
@ -80,7 +80,7 @@ public class PeersMessage extends P2pMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public P2pMessageCodes getCommand(){
|
||||
public P2pMessageCodes getCommand() {
|
||||
return P2pMessageCodes.PEERS;
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,9 @@ import org.spongycastle.util.encoders.Hex;
|
||||
*/
|
||||
public class PingMessage extends P2pMessage {
|
||||
|
||||
/** Ping message is always a the same single command payload */
|
||||
/**
|
||||
* Ping message is always a the same single command payload
|
||||
*/
|
||||
private static byte[] FIXED_PAYLOAD = Hex.decode("C102");
|
||||
|
||||
public byte[] getEncoded() {
|
||||
@ -22,7 +24,7 @@ public class PingMessage extends P2pMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public P2pMessageCodes getCommand(){
|
||||
public P2pMessageCodes getCommand() {
|
||||
return P2pMessageCodes.PING;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,9 @@ import org.spongycastle.util.encoders.Hex;
|
||||
*/
|
||||
public class PongMessage extends P2pMessage {
|
||||
|
||||
/** Pong message is always a the same single command payload */
|
||||
/**
|
||||
* Pong message is always a the same single command payload
|
||||
*/
|
||||
private static byte[] FIXED_PAYLOAD = Hex.decode("C103");
|
||||
|
||||
@Override
|
||||
@ -24,7 +26,7 @@ public class PongMessage extends P2pMessage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public P2pMessageCodes getCommand(){
|
||||
public P2pMessageCodes getCommand() {
|
||||
return P2pMessageCodes.PONG;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
||||
|
||||
/**
|
||||
* This class creates the connection to an remote address using the Netty framework
|
||||
*
|
||||
* @see <a href="http://netty.io">http://netty.io</a>
|
||||
*/
|
||||
@Component
|
||||
@ -93,7 +94,7 @@ public class DiscoveryChannel {
|
||||
|
||||
b.handler(
|
||||
|
||||
new ChannelInitializer<NioSocketChannel>(){
|
||||
new ChannelInitializer<NioSocketChannel>() {
|
||||
@Override
|
||||
protected void initChannel(NioSocketChannel ch) throws Exception {
|
||||
|
||||
@ -128,7 +129,7 @@ public class DiscoveryChannel {
|
||||
} finally {
|
||||
workerGroup.shutdownGracefully();
|
||||
|
||||
if (!peerDiscoveryMode){
|
||||
if (!peerDiscoveryMode) {
|
||||
// EthereumListener listener = WorldManager.getInstance().getListener();
|
||||
// listener.onPeerDisconnect(host, port);
|
||||
}
|
||||
@ -136,12 +137,11 @@ public class DiscoveryChannel {
|
||||
}
|
||||
}
|
||||
|
||||
public HelloMessage getHelloHandshake(){
|
||||
public HelloMessage getHelloHandshake() {
|
||||
return p2pHandler.getHandshakeHelloMessage();
|
||||
}
|
||||
|
||||
public StatusMessage getStatusHandshake()
|
||||
{
|
||||
public StatusMessage getStatusHandshake() {
|
||||
return ethHandler.getHandshakeStatusMessage();
|
||||
}
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ public class PeerDiscovery {
|
||||
for (final Peer newPeer : newPeers) {
|
||||
PeerInfo peerInfo =
|
||||
new PeerInfo(newPeer.getAddress(), newPeer.getPort(), newPeer.getPeerId());
|
||||
if (started.get() && !peers.contains(peerInfo )){
|
||||
if (started.get() && !peers.contains(peerInfo)) {
|
||||
startWorker(peerInfo);
|
||||
}
|
||||
peers.add(peerInfo);
|
||||
@ -103,8 +103,8 @@ public class PeerDiscovery {
|
||||
|
||||
public void addPeers(Collection<PeerInfo> newPeers) {
|
||||
synchronized (peers) {
|
||||
peers.addAll(newPeers);
|
||||
}
|
||||
peers.addAll(newPeers);
|
||||
}
|
||||
}
|
||||
|
||||
private void startWorker(PeerInfo peerInfo) {
|
||||
@ -115,12 +115,12 @@ public class PeerDiscovery {
|
||||
executorPool.execute(workerThread);
|
||||
}
|
||||
|
||||
public List<PeerInfo> parsePeerDiscoveryIpList(final String peerDiscoveryIpList){
|
||||
public List<PeerInfo> parsePeerDiscoveryIpList(final String peerDiscoveryIpList) {
|
||||
|
||||
final List<String> ipList = Arrays.asList( peerDiscoveryIpList.split(",") );
|
||||
final List<String> ipList = Arrays.asList(peerDiscoveryIpList.split(","));
|
||||
final List<PeerInfo> peers = new ArrayList<>();
|
||||
|
||||
for (String ip : ipList){
|
||||
for (String ip : ipList) {
|
||||
String[] addr = ip.trim().split(":");
|
||||
String ip_trim = addr[0];
|
||||
String port_trim = addr[1];
|
||||
|
@ -20,7 +20,7 @@ public class PeerInfo {
|
||||
private String peerId;
|
||||
|
||||
private List<Capability> capabilities;
|
||||
private HelloMessage handshakeHelloMessage;
|
||||
private HelloMessage handshakeHelloMessage;
|
||||
private StatusMessage statusMessage;
|
||||
|
||||
private transient boolean isOnline = false;
|
||||
@ -77,7 +77,7 @@ public class PeerInfo {
|
||||
.append(" port=").append(getPort())
|
||||
.append(" peerId=").append(getPeerId()).append("] \n")
|
||||
.append(this.handshakeHelloMessage == null ? "" : handshakeHelloMessage + "\n")
|
||||
.append(this.statusMessage == null ? "" : statusMessage + "\n");
|
||||
.append(this.statusMessage == null ? "" : statusMessage + "\n");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ public class WorkerThread implements Runnable {
|
||||
public WorkerThread() {
|
||||
}
|
||||
|
||||
public void init(PeerInfo peer, ThreadPoolExecutor poolExecutor){
|
||||
public void init(PeerInfo peer, ThreadPoolExecutor poolExecutor) {
|
||||
this.peerInfo = peer;
|
||||
this.poolExecutor = poolExecutor;
|
||||
}
|
||||
@ -54,7 +54,7 @@ public class WorkerThread implements Runnable {
|
||||
peerInfo.setOnline(true);
|
||||
|
||||
peerInfo.setHandshakeHelloMessage(discoveryChannel.getHelloHandshake());
|
||||
peerInfo.setStatusMessage( discoveryChannel.getStatusHandshake() );
|
||||
peerInfo.setStatusMessage(discoveryChannel.getStatusHandshake());
|
||||
|
||||
logger.info("Peer is online: [{}] ", peerInfo);
|
||||
|
||||
@ -72,7 +72,7 @@ public class WorkerThread implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void sleep(long milliseconds){
|
||||
private void sleep(long milliseconds) {
|
||||
|
||||
try {
|
||||
Thread.sleep(milliseconds);
|
||||
|
@ -52,7 +52,7 @@ public class Channel {
|
||||
public Channel() {
|
||||
}
|
||||
|
||||
public void init(){
|
||||
public void init() {
|
||||
p2pHandler.setMsgQueue(msgQueue);
|
||||
ethHandler.setMsgQueue(msgQueue);
|
||||
shhHandler.setMsgQueue(msgQueue);
|
||||
@ -80,27 +80,27 @@ public class Channel {
|
||||
return messageEncoder;
|
||||
}
|
||||
|
||||
public void sendTransaction(Transaction tx){
|
||||
public void sendTransaction(Transaction tx) {
|
||||
ethHandler.sendTransaction(tx);
|
||||
}
|
||||
|
||||
public void sendNewBlock(Block block){
|
||||
public void sendNewBlock(Block block) {
|
||||
|
||||
// 1. check by best block send or not to send
|
||||
ethHandler.sendNewBlock(block);
|
||||
|
||||
}
|
||||
|
||||
public boolean isSync(){
|
||||
public boolean isSync() {
|
||||
return ethHandler.getSyncStatus() == EthHandler.SyncSatus.SYNC_DONE;
|
||||
}
|
||||
|
||||
|
||||
public BigInteger getTotalDifficulty(){
|
||||
public BigInteger getTotalDifficulty() {
|
||||
return ethHandler.getTotalDifficulty();
|
||||
}
|
||||
|
||||
public void ethSync(){
|
||||
public void ethSync() {
|
||||
ethHandler.doSync();
|
||||
}
|
||||
|
||||
|
@ -36,63 +36,63 @@ public class ChannelManager {
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init(){
|
||||
public void init() {
|
||||
scheduleChannelCollector();
|
||||
}
|
||||
|
||||
public void recvTransaction(){
|
||||
public void recvTransaction() {
|
||||
// ???
|
||||
}
|
||||
|
||||
|
||||
public void recvBlock(){ // todo:
|
||||
public void recvBlock() { // todo:
|
||||
// 1. Check in the cache if the hash exist
|
||||
// 2. Exist: go and send it to the queue
|
||||
}
|
||||
|
||||
public void sendTransaction(Transaction tx){
|
||||
for (Channel channel : channels){
|
||||
public void sendTransaction(Transaction tx) {
|
||||
for (Channel channel : channels) {
|
||||
channel.sendTransaction(tx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void sendNewBlock(Block block){
|
||||
public void sendNewBlock(Block block) {
|
||||
// 1. Go over all channels and send the block
|
||||
for (Channel channel : channels){
|
||||
for (Channel channel : channels) {
|
||||
channel.sendNewBlock(block);
|
||||
}
|
||||
}
|
||||
|
||||
public void addChannel(Channel channel){
|
||||
synchronized (channels){
|
||||
public void addChannel(Channel channel) {
|
||||
synchronized (channels) {
|
||||
channels.add(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAllSync(){
|
||||
public boolean isAllSync() {
|
||||
|
||||
boolean result = true;
|
||||
for (Channel channel : channels){
|
||||
for (Channel channel : channels) {
|
||||
result &= channel.isSync();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public void scheduleChannelCollector(){
|
||||
public void scheduleChannelCollector() {
|
||||
inactivesCollector.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
Iterator<Channel> iter = channels.iterator();
|
||||
while(iter.hasNext()){
|
||||
while (iter.hasNext()) {
|
||||
Channel channel = iter.next();
|
||||
if(!channel.p2pHandler.isActive()){
|
||||
if (!channel.p2pHandler.isActive()) {
|
||||
iter.remove();
|
||||
logger.info("Channel removed: {}", channel.p2pHandler.getHandshakeHelloMessage());
|
||||
}
|
||||
}
|
||||
|
||||
if (channels.size() == 0){
|
||||
if (channels.size() == 0) {
|
||||
worldManager.getListener().onNoConnections();
|
||||
}
|
||||
}
|
||||
@ -102,10 +102,10 @@ public class ChannelManager {
|
||||
public void ethSync() {
|
||||
|
||||
Channel bestChannel = channels.get(0);
|
||||
for (Channel channel : channels){
|
||||
for (Channel channel : channels) {
|
||||
|
||||
if (bestChannel.getTotalDifficulty().
|
||||
compareTo(channel.getTotalDifficulty()) < 0 ){
|
||||
compareTo(channel.getTotalDifficulty()) < 0) {
|
||||
bestChannel = channel;
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,6 @@ import org.springframework.stereotype.Component;
|
||||
* Process the messages between peers with 'shh' capability on the network.
|
||||
*
|
||||
* Peers with 'shh' capability can send/receive:
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
@Scope("prototype")
|
||||
@ -31,7 +29,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
|
||||
@Autowired
|
||||
WorldManager worldManager;
|
||||
|
||||
public ShhHandler(){
|
||||
public ShhHandler() {
|
||||
}
|
||||
|
||||
public ShhHandler(MessageQueue msgQueue) {
|
||||
@ -46,7 +44,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
|
||||
if (ShhMessageCodes.inRange(msg.getCommand().asByte()))
|
||||
logger.info("ShhHandler invoke: [{}]", msg.getCommand());
|
||||
|
||||
worldManager.getListener().trace(String.format( "ShhHandler invoke: [%s]", msg.getCommand()));
|
||||
worldManager.getListener().trace(String.format("ShhHandler invoke: [%s]", msg.getCommand()));
|
||||
|
||||
switch (msg.getCommand()) {
|
||||
case STATUS:
|
||||
@ -77,7 +75,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
|
||||
logger.debug("handlerRemoved: ... ");
|
||||
}
|
||||
|
||||
public void activate(){
|
||||
public void activate() {
|
||||
logger.info("SHH protocol activated");
|
||||
worldManager.getListener().trace("SHH protocol activated");
|
||||
this.active = true;
|
||||
|
@ -4,7 +4,8 @@ import org.ethereum.net.message.Message;
|
||||
|
||||
public abstract class ShhMessage extends Message {
|
||||
|
||||
public ShhMessage() {}
|
||||
public ShhMessage() {
|
||||
}
|
||||
|
||||
public ShhMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
|
@ -15,25 +15,36 @@ public enum ShhMessageCodes {
|
||||
|
||||
/* Whisper Protocol */
|
||||
|
||||
/** [+0x00] */
|
||||
/**
|
||||
* [+0x00]
|
||||
*/
|
||||
STATUS(0x00),
|
||||
|
||||
/** [+0x01] */
|
||||
/**
|
||||
* [+0x01]
|
||||
*/
|
||||
MESSAGE(0x01),
|
||||
|
||||
/** [+0x02] */
|
||||
/**
|
||||
* [+0x02]
|
||||
*/
|
||||
ADD_FILTER(0x02),
|
||||
|
||||
/** [+0x03] */
|
||||
/**
|
||||
* [+0x03]
|
||||
*/
|
||||
REMOVE_FILTER(0x03),
|
||||
|
||||
/** [+0x04] */
|
||||
/**
|
||||
* [+0x04]
|
||||
*/
|
||||
PACKET_COUNT(0x04);
|
||||
|
||||
static byte OFFSET = 0;
|
||||
private int cmd;
|
||||
|
||||
private static final Map<Integer, ShhMessageCodes> intToTypeMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (ShhMessageCodes type : ShhMessageCodes.values()) {
|
||||
intToTypeMap.put(type.cmd, type);
|
||||
@ -49,11 +60,11 @@ public enum ShhMessageCodes {
|
||||
return type;
|
||||
}
|
||||
|
||||
public static void setOffset(byte offset){
|
||||
public static void setOffset(byte offset) {
|
||||
ShhMessageCodes.OFFSET = offset;
|
||||
}
|
||||
|
||||
public static boolean inRange(byte code){
|
||||
public static boolean inRange(byte code) {
|
||||
|
||||
if (code >= STATUS.asByte() && code <= PACKET_COUNT.asByte())
|
||||
return true;
|
||||
@ -62,6 +73,6 @@ public enum ShhMessageCodes {
|
||||
}
|
||||
|
||||
public byte asByte() {
|
||||
return (byte) (cmd + OFFSET);
|
||||
return (byte) (cmd + OFFSET);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ public class TransactionExecutor {
|
||||
static {
|
||||
instance = new TransactionExecutor();
|
||||
}
|
||||
|
||||
public static TransactionExecutor instance;
|
||||
private ExecutorService executor = Executors.newFixedThreadPool(1);
|
||||
|
||||
|
@ -62,10 +62,10 @@ public class MessageDecoder extends ByteToMessageDecoder {
|
||||
|
||||
long syncToken = in.readUnsignedInt();
|
||||
|
||||
if (!((syncToken >> 24 & 0xFF) == 0x22 &&
|
||||
(syncToken >> 16 & 0xFF) == 0x40 &&
|
||||
(syncToken >> 8 & 0xFF) == 0x08 &&
|
||||
(syncToken & 0xFF) == 0x91 )) {
|
||||
if (!((syncToken >> 24 & 0xFF) == 0x22 &&
|
||||
(syncToken >> 16 & 0xFF) == 0x40 &&
|
||||
(syncToken >> 8 & 0xFF) == 0x08 &&
|
||||
(syncToken & 0xFF) == 0x91)) {
|
||||
|
||||
// TODO: Drop frame and continue.
|
||||
// A collision can happen (although rare)
|
||||
|
@ -24,7 +24,7 @@ import org.springframework.stereotype.Component;
|
||||
public class MessageEncoder extends MessageToByteEncoder<Message> {
|
||||
|
||||
private static final Logger loggerWire = LoggerFactory.getLogger("wire");
|
||||
private static final Logger loggerNet = LoggerFactory.getLogger("net");
|
||||
private static final Logger loggerNet = LoggerFactory.getLogger("net");
|
||||
|
||||
@Autowired
|
||||
WorldManager worldManager;
|
||||
|
@ -6,6 +6,7 @@ import org.apache.maven.plugin.MojoFailureException;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 25/04/14 17:06
|
||||
*/
|
||||
@ -17,7 +18,7 @@ public class ParserGenerator {
|
||||
|
||||
String grammarName = userDir + "\\src\\main\\antlr4\\org\\ethereum\\serpent\\Serpent.g4";
|
||||
|
||||
String options[] = {grammarName, "-visitor", "-package", "org.ethereum.serpent"};
|
||||
String options[] = {grammarName, "-visitor", "-package", "org.ethereum.serpent"};
|
||||
Tool tool = new Tool(options);
|
||||
tool.outputDirectory = userDir + "\\src\\main\\java\\org\\ethereum\\serpent\\";
|
||||
tool.processGrammarsOnCommandLine();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user