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:
Chris Beams 2014-12-26 11:07:01 +01:00
parent e5fcf5b48e
commit 58874cfc7e
No known key found for this signature in database
GPG Key ID: 3D214F8F5BC5ED73
199 changed files with 4309 additions and 3331 deletions

View File

@ -1,4 +1,3 @@
<!-- <!--
Publish from local ${user.home}/.m2/repository 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/> <tstamp/>
<property name="artifact.groupId" value="org.ethereum"/> <property name="artifact.groupId" value="org.ethereum"/>
<property name="artifact.id" value="ethereumj"/> <property name="artifact.id" value="ethereumj"/>
<property name="artifact.version" value="0.7.14"/> <property name="artifact.version" value="0.7.14"/>
<property name="artifact.path" value="" /> <property name="artifact.path" value=""/>
<property name="artifact.snapshot" value="snapshot" /> <property name="artifact.snapshot" value="snapshot"/>
<property name="repo.location" value="${user.home}/.m2/repository"/> <property name="repo.location" value="${user.home}/.m2/repository"/>
<property name="artifact.group.path" value="${artifact.groupId}"/> <property name="artifact.group.path" value="${artifact.groupId}"/>
@ -43,24 +41,24 @@
<property file="credentials.properties"/> <property file="credentials.properties"/>
<property name="ant.contrib.lib" value="${user.home}/.ant/lib/ant-contrib-1.0b3.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="ant.missinglink.lib" value="${user.home}/.ant/lib/ml-ant-http-1.1.3.jar"/>
<property name="bintray.subject" value="ethereum"/> <property name="bintray.subject" value="ethereum"/>
<property name="bintray.repo" value="maven"/> <property name="bintray.repo" value="maven"/>
<property name="bintray.package" value="${artifact.groupId}"/> <property name="bintray.package" value="${artifact.groupId}"/>
<condition property="bintray.version" value="${artifact.version}.${DSTAMP}.${TSTAMP}" <condition property="bintray.version" value="${artifact.version}.${DSTAMP}.${TSTAMP}"
else="${artifact.version}"> else="${artifact.version}">
<isset property="artifact.snapshot" /> <isset property="artifact.snapshot"/>
</condition> </condition>
<property name="bintray.publish" value="1"/> <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=""/> <property name="encoded.bintray.file.path" value=""/>
@ -78,8 +76,6 @@
</taskdef> </taskdef>
<target name="definePath"> <target name="definePath">
<!--[groupId('.'->'/')]\[artifactId]\[version]--> <!--[groupId('.'->'/')]\[artifactId]\[version]-->
<!--[artifactId]-[version][suffix]--> <!--[artifactId]-[version][suffix]-->
@ -93,11 +89,11 @@
<var name="artifact.full.path" unset="true"/> <var name="artifact.full.path" unset="true"/>
<property name="artifact.full.path" <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"/> <var name="bintray.file.path" unset="true"/>
<property name="bintray.file.path" <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}"/> <echo message="${bintray.file.path}"/>
@ -116,10 +112,9 @@
</target> </target>
<target name="publish" depends="dependency, definePath"> <target name="publish" depends="dependency, definePath">
<parallel> <parallel>
<antcall target="upload"> <antcall target="upload">
<param name="artifact.suffix" value=".pom"/> <param name="artifact.suffix" value=".pom"/>
</antcall> </antcall>
@ -132,11 +127,11 @@
<param name="artifact.suffix" value="-sources.jar"/> <param name="artifact.suffix" value="-sources.jar"/>
</antcall> </antcall>
<antcall target="upload"> <antcall target="upload">
<param name="artifact.suffix" value="-javadoc.jar"/> <param name="artifact.suffix" value="-javadoc.jar"/>
</antcall> </antcall>
</parallel> </parallel>
</target> </target>
@ -169,6 +164,4 @@
</target> </target>
</project> </project>

View File

@ -1,5 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <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> <modelVersion>4.0.0</modelVersion>
<groupId>org.ethereum</groupId> <groupId>org.ethereum</groupId>
<artifactId>ethereumj</artifactId> <artifactId>ethereumj</artifactId>
@ -8,14 +8,14 @@
<name>EthereumJ</name> <name>EthereumJ</name>
<url>http://www.ethereumj.org</url> <url>http://www.ethereumj.org</url>
<!-- <!--
* Install jar with sources to the local maven repository * Install jar with sources to the local maven repository
mvn install -Dmaven.test.skip=true mvn install -Dmaven.test.skip=true
* To generate source for ANTLR parser/lexer * To generate source for ANTLR parser/lexer
mvn antlr4:antlr4 mvn antlr4:antlr4
--> -->
<developers> <developers>
<developer> <developer>
@ -70,9 +70,9 @@
</dependency> </dependency>
<!-- Added Cedarsoft for DeepEquals function --> <!-- Added Cedarsoft for DeepEquals function -->
<dependency> <dependency>
<groupId>com.cedarsoftware</groupId> <groupId>com.cedarsoftware</groupId>
<artifactId>java-util</artifactId> <artifactId>java-util</artifactId>
<version>1.8.0</version> <version>1.8.0</version>
</dependency> </dependency>
<!-- For Serpent compile --> <!-- For Serpent compile -->
<dependency> <dependency>
@ -347,7 +347,7 @@
</configuration> </configuration>
</plugin> </plugin>
<!-- <!--
<plugin> <plugin>
<artifactId>maven-antrun-plugin</artifactId> <artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version> <version>1.3</version>
@ -367,8 +367,7 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
--> -->
<plugin> <plugin>
<groupId>org.antlr</groupId> <groupId>org.antlr</groupId>
@ -400,9 +399,8 @@
</plugin> </plugin>
</plugins> </plugins>
<pluginManagement> <pluginManagement>
<plugins> <plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.--> <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
<plugin> <plugin>

View File

@ -14,7 +14,7 @@ import org.ethereum.facade.EthereumFactory;
public class Start { public class Start {
public static void main(String args[]){ public static void main(String args[]) {
CLIInterface.call(args); CLIInterface.call(args);
Ethereum ethereum = EthereumFactory.createEthereum(); Ethereum ethereum = EthereumFactory.createEthereum();

View File

@ -19,35 +19,35 @@ public class CLIInterface {
private static final Logger logger = LoggerFactory.getLogger("cli"); private static final Logger logger = LoggerFactory.getLogger("cli");
public static void call(String[] args){ public static void call(String[] args) {
try { try {
for (int i = 0; i < args.length; ++i){ for (int i = 0; i < args.length; ++i) {
// override the db directory // override the db directory
if (args[i].equals("--help")){ if (args[i].equals("--help")) {
printHelp(); printHelp();
System.exit(1); System.exit(1);
} }
// override the db directory // override the db directory
if (args[i].equals("-db") && i + 1 < args.length){ if (args[i].equals("-db") && i + 1 < args.length) {
String db = args[i+1]; String db = args[i + 1];
logger.info("DB directory set to [{}]", db); logger.info("DB directory set to [{}]", db);
CONFIG.setDataBaseDir(db); CONFIG.setDataBaseDir(db);
} }
// override the listen port directory // override the listen port directory
if (args[i].equals("-listen") && i + 1 < args.length){ if (args[i].equals("-listen") && i + 1 < args.length) {
String port = args[i+1]; String port = args[i + 1];
logger.info("Listen port set to [{}]", port); logger.info("Listen port set to [{}]", port);
CONFIG.setListenPort(Integer.valueOf(port)); CONFIG.setListenPort(Integer.valueOf(port));
} }
// override the connect host:port directory // override the connect host:port directory
if (args[i].equals("-connect") && i + 1 < args.length){ if (args[i].equals("-connect") && i + 1 < args.length) {
String connectStr = args[i+1]; String connectStr = args[i + 1];
logger.info("Connect host:port set to [{}]", connectStr); logger.info("Connect host:port set to [{}]", connectStr);
String[] params = connectStr.split(":"); String[] params = connectStr.split(":");
String host = params[0]; String host = params[0];
@ -57,8 +57,8 @@ public class CLIInterface {
} }
// override the listen port directory // override the listen port directory
if (args[i].equals("-reset") && i + 1 < args.length){ if (args[i].equals("-reset") && i + 1 < args.length) {
Boolean resetStr = interpret( args[i+1] ); Boolean resetStr = interpret(args[i + 1]);
logger.info("Resetting db set to [{}]", resetStr); logger.info("Resetting db set to [{}]", resetStr);
CONFIG.setDatabaseReset(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; if (arg.equals("off") || arg.equals("false") || arg.equals("no")) return false;
throw new Error("Can't interpret the answer: " + arg); 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("--help -- this help message ");
System.out.println("-reset <yes/no> -- reset yes/no the all database "); System.out.println("-reset <yes/no> -- reset yes/no the all database ");

View File

@ -14,41 +14,41 @@ import org.springframework.stereotype.Component;
* Utility class to retrieve property values from the system.properties files * Utility class to retrieve property values from the system.properties files
* *
* @author Roman Mandeleil * @author Roman Mandeleil
* Created on: 22/05/2014 19:22 * Created on: 22/05/2014 19:22
*/ */
public class SystemProperties { public class SystemProperties {
private static Logger logger = LoggerFactory.getLogger("general"); private static Logger logger = LoggerFactory.getLogger("general");
private static int DEFAULT_TX_APPROVE_TIMEOUT = 10; private static int DEFAULT_TX_APPROVE_TIMEOUT = 10;
private static String DEFAULT_DISCOVERY_PEER_LIST = "poc-7.ethdev.com:30303"; 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 String DEFAULT_ACTIVE_PEER_IP = "poc-7.ethdev.com";
private static int DEFAULT_ACTIVE_PORT = 30303; private static int DEFAULT_ACTIVE_PORT = 30303;
private static String DEFAULT_SAMPLES_DIR = "samples"; private static String DEFAULT_SAMPLES_DIR = "samples";
private static String DEFAULT_COINBASE_SECRET = "monkey"; private static String DEFAULT_COINBASE_SECRET = "monkey";
private static int DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT = 5; private static int DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT = 5;
private static Boolean DEFAULT_DB_RESET = false; private static Boolean DEFAULT_DB_RESET = false;
private static Boolean DEFAULT_DUMP_FULL = false; private static Boolean DEFAULT_DUMP_FULL = false;
private static Boolean DEFAULT_RECORD_BLOCKS = false; private static Boolean DEFAULT_RECORD_BLOCKS = false;
private static String DEFAULT_DUMP_DIR = "dmp"; private static String DEFAULT_DUMP_DIR = "dmp";
private static String DEFAULT_DUMP_STYLE = "standard+"; private static String DEFAULT_DUMP_STYLE = "standard+";
private static Integer DEFAULT_VMTRACE_BLOCK = 0; private static Integer DEFAULT_VMTRACE_BLOCK = 0;
private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir"); private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir");
private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true; private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true;
private static Boolean DEFAULT_PLAY_VM = true; private static Boolean DEFAULT_PLAY_VM = true;
private static Boolean DEFAULT_BLOCKCHAIN_ONLY = false; private static Boolean DEFAULT_BLOCKCHAIN_ONLY = false;
private static int DEFAULT_TRACE_STARTBLOCK = -1; private static int DEFAULT_TRACE_STARTBLOCK = -1;
private static int DEFAULT_MAX_HASHES_ASK = -1; // unlimited private static int DEFAULT_MAX_HASHES_ASK = -1; // unlimited
private static int DEFAULT_MAX_BLOCKS_ASK = 10; private static int DEFAULT_MAX_BLOCKS_ASK = 10;
private static int DEFAULT_MAX_BLOCKS_QUEUED = 300; private static int DEFAULT_MAX_BLOCKS_QUEUED = 300;
private static String DEFAULT_PROJECT_VERSION = ""; private static String DEFAULT_PROJECT_VERSION = "";
private static String DEFAULT_HELLO_PHRASE = "Dev"; private static String DEFAULT_HELLO_PHRASE = "Dev";
private static Boolean DEFAULT_VM_TRACE = false; private static Boolean DEFAULT_VM_TRACE = false;
private static String DEFAULT_VM_TRACE_DIR = "dmp"; private static String DEFAULT_VM_TRACE_DIR = "dmp";
private static int DEFAULT_PEER_LISTEN_PORT = 30303; private static int DEFAULT_PEER_LISTEN_PORT = 30303;
/* Testing */ /* 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"); 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")); return Boolean.parseBoolean(prop.getProperty("database.reset"));
} }
public void setDatabaseReset(Boolean reset){ public void setDatabaseReset(Boolean reset) {
prop.setProperty("database.reset", reset.toString()); prop.setProperty("database.reset", reset.toString());
} }
@ -131,7 +131,7 @@ public class SystemProperties {
return prop.getProperty("peer.active.ip"); return prop.getProperty("peer.active.ip");
} }
public void setActivePeerIP(String host){ public void setActivePeerIP(String host) {
prop.setProperty("peer.active.ip", host.toString()); prop.setProperty("peer.active.ip", host.toString());
} }
@ -140,7 +140,7 @@ public class SystemProperties {
return Integer.parseInt(prop.getProperty("peer.active.port")); 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()); prop.setProperty("peer.active.port", port.toString());
} }
@ -195,7 +195,7 @@ public class SystemProperties {
return prop.getProperty("database.dir"); return prop.getProperty("database.dir");
} }
public void setDataBaseDir(String dataBaseDir){ public void setDataBaseDir(String dataBaseDir) {
prop.setProperty("database.dir", dataBaseDir); prop.setProperty("database.dir", dataBaseDir);
} }
@ -247,13 +247,13 @@ public class SystemProperties {
return hash; return hash;
} }
public List<String> peerCapabilities(){ public List<String> peerCapabilities() {
if (prop.isEmpty()) return DEFAULT_PROTOCOL_LIST; if (prop.isEmpty()) return DEFAULT_PROTOCOL_LIST;
String capabilitiesList = prop.getProperty("peer.capabilities"); String capabilitiesList = prop.getProperty("peer.capabilities");
return Arrays.asList(capabilitiesList.split(",")); return Arrays.asList(capabilitiesList.split(","));
} }
public boolean vmTrace(){ public boolean vmTrace() {
if (prop.isEmpty()) return DEFAULT_VM_TRACE; if (prop.isEmpty()) return DEFAULT_VM_TRACE;
return Boolean.parseBoolean(prop.getProperty("vm.structured.trace")); return Boolean.parseBoolean(prop.getProperty("vm.structured.trace"));
} }
@ -263,12 +263,12 @@ public class SystemProperties {
return prop.getProperty("vm.structured.dir"); return prop.getProperty("vm.structured.dir");
} }
public int listenPort(){ public int listenPort() {
if (prop.isEmpty()) return DEFAULT_PEER_LISTEN_PORT; if (prop.isEmpty()) return DEFAULT_PEER_LISTEN_PORT;
return Integer.parseInt(prop.getProperty("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()); prop.setProperty("peer.listen.port", port.toString());
} }

View File

@ -16,7 +16,7 @@ import org.springframework.stereotype.Component;
*/ */
@Component @Component
@Scope("prototype") @Scope("prototype")
public class Account { public class Account {
private ECKey ecKey; private ECKey ecKey;
private byte[] address; private byte[] address;
@ -30,7 +30,7 @@ public class Account {
public Account() { public Account() {
} }
public void init(){ public void init() {
this.ecKey = new ECKey(Utils.getRandom()); this.ecKey = new ECKey(Utils.getRandom());
address = this.ecKey.getAddress(); address = this.ecKey.getAddress();
} }
@ -40,14 +40,14 @@ public class Account {
address = this.ecKey.getAddress(); address = this.ecKey.getAddress();
} }
public BigInteger getNonce(){ public BigInteger getNonce() {
AccountState accountState = AccountState accountState =
worldManager.getRepository().getAccountState(getAddress()); worldManager.getRepository().getAccountState(getAddress());
return accountState.getNonce(); return accountState.getNonce();
} }
public BigInteger getBalance(){ public BigInteger getBalance() {
AccountState accountState = AccountState accountState =
worldManager.getRepository().getAccountState(this.getAddress()); worldManager.getRepository().getAccountState(this.getAddress());
@ -57,15 +57,15 @@ public class Account {
if (accountState != null) if (accountState != null)
balance = accountState.getBalance(); balance = accountState.getBalance();
synchronized (getPendingTransactins()){ synchronized (getPendingTransactins()) {
if (!getPendingTransactins().isEmpty()){ if (!getPendingTransactins().isEmpty()) {
for (Transaction tx : getPendingTransactins()){ for (Transaction tx : getPendingTransactins()) {
if (Arrays.equals(getAddress(), tx.getSender())){ if (Arrays.equals(getAddress(), tx.getSender())) {
balance = balance.subtract(new BigInteger(1, tx.getValue())); 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())); balance = balance.add(new BigInteger(1, tx.getValue()));
} }
} }
@ -94,14 +94,14 @@ public class Account {
return this.pendingTransactions; return this.pendingTransactions;
} }
public void addPendingTransaction(Transaction transaction){ public void addPendingTransaction(Transaction transaction) {
synchronized (pendingTransactions){ synchronized (pendingTransactions) {
pendingTransactions.add(transaction); pendingTransactions.add(transaction);
} }
} }
public void clearAllPendingTransactions(){ public void clearAllPendingTransactions() {
synchronized (pendingTransactions){ synchronized (pendingTransactions) {
pendingTransactions.clear(); pendingTransactions.clear();
} }
} }

View File

@ -41,7 +41,7 @@ public class AccountState {
* retrieval */ * retrieval */
private byte[] codeHash = EMPTY_DATA_HASH; private byte[] codeHash = EMPTY_DATA_HASH;
private boolean dirty = false; private boolean dirty = false;
private boolean deleted = false; private boolean deleted = false;
@ -57,13 +57,13 @@ public class AccountState {
public AccountState(byte[] rlpData) { public AccountState(byte[] rlpData) {
this.rlpEncoded = 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 this.nonce = items.get(0).getRLPData() == null ? BigInteger.ZERO
: new BigInteger(1, items.get(0).getRLPData()); : new BigInteger(1, items.get(0).getRLPData());
this.balance = items.get(1).getRLPData() == null ? BigInteger.ZERO this.balance = items.get(1).getRLPData() == null ? BigInteger.ZERO
: new BigInteger(1, items.get(1).getRLPData()); : new BigInteger(1, items.get(1).getRLPData());
this.stateRoot = items.get(2).getRLPData(); this.stateRoot = items.get(2).getRLPData();
this.codeHash = items.get(3).getRLPData(); this.codeHash = items.get(3).getRLPData();
} }
public BigInteger getNonce() { public BigInteger getNonce() {
@ -117,11 +117,11 @@ public class AccountState {
} }
public byte[] getEncoded() { public byte[] getEncoded() {
if(rlpEncoded == null) { if (rlpEncoded == null) {
byte[] nonce = RLP.encodeBigInteger(this.nonce); byte[] nonce = RLP.encodeBigInteger(this.nonce);
byte[] balance = RLP.encodeBigInteger(this.balance); byte[] balance = RLP.encodeBigInteger(this.balance);
byte[] stateRoot = RLP.encodeElement(this.stateRoot); byte[] stateRoot = RLP.encodeElement(this.stateRoot);
byte[] codeHash = RLP.encodeElement(this.codeHash); byte[] codeHash = RLP.encodeElement(this.codeHash);
this.rlpEncoded = RLP.encodeList(nonce, balance, stateRoot, codeHash); this.rlpEncoded = RLP.encodeList(nonce, balance, stateRoot, codeHash);
} }
return rlpEncoded; return rlpEncoded;
@ -143,7 +143,7 @@ public class AccountState {
return deleted; return deleted;
} }
public AccountState clone(){ public AccountState clone() {
AccountState accountState = new AccountState(); AccountState accountState = new AccountState();
accountState.addToBalance(this.getBalance()); accountState.addToBalance(this.getBalance());
@ -156,10 +156,10 @@ public class AccountState {
} }
public String toString() { public String toString() {
String ret = " Nonce: " + this.getNonce().toString() + "\n" + String ret = " Nonce: " + this.getNonce().toString() + "\n" +
" Balance: " + getBalance() + "\n" + " Balance: " + getBalance() + "\n" +
" State Root: " + Hex.toHexString(this.getStateRoot()) + "\n" + " State Root: " + Hex.toHexString(this.getStateRoot()) + "\n" +
" Code Hash: " + Hex.toHexString(this.getCodeHash()); " Code Hash: " + Hex.toHexString(this.getCodeHash());
return ret; return ret;
} }
} }

View File

@ -23,6 +23,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
* (such blocks are known as uncles). * (such blocks are known as uncles).
* *
* www.ethereumJ.com * www.ethereumJ.com
*
* @author Roman Mandeleil, * @author Roman Mandeleil,
* Nick Savers * Nick Savers
* Created on: 20/05/2014 10:44 * Created on: 20/05/2014 10:44
@ -31,7 +32,7 @@ public class Block {
private static final Logger logger = LoggerFactory.getLogger("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( public static BigInteger UNCLE_REWARD = BLOCK_REWARD.multiply(
BigInteger.valueOf(15)).divide(BigInteger.valueOf(16)); BigInteger.valueOf(15)).divide(BigInteger.valueOf(16));
public static BigInteger INCLUSION_REWARD = Block.BLOCK_REWARD public static BigInteger INCLUSION_REWARD = Block.BLOCK_REWARD
@ -65,11 +66,11 @@ public class Block {
long gasUsed, long timestamp, byte[] extraData, byte[] nonce, long gasUsed, long timestamp, byte[] extraData, byte[] nonce,
List<Transaction> transactionsList, List<BlockHeader> uncleList) { List<Transaction> transactionsList, List<BlockHeader> uncleList) {
this.header = new BlockHeader(parentHash, unclesHash, coinbase, logsBloom, this.header = new BlockHeader(parentHash, unclesHash, coinbase, logsBloom,
difficulty, number, gasLimit, gasUsed, difficulty, number, gasLimit, gasUsed,
timestamp, extraData, nonce); timestamp, extraData, nonce);
this.transactionsList = transactionsList; this.transactionsList = transactionsList;
if (this.transactionsList == null){ if (this.transactionsList == null) {
this.transactionsList = new CopyOnWriteArrayList<Transaction>(); this.transactionsList = new CopyOnWriteArrayList<Transaction>();
} }
@ -105,7 +106,7 @@ public class Block {
this.parsed = true; this.parsed = true;
} }
public BlockHeader getHeader(){ public BlockHeader getHeader() {
if (!parsed) parseRLP(); if (!parsed) parseRLP();
return this.header; return this.header;
} }
@ -162,7 +163,7 @@ public class Block {
return this.header.getTxTrieRoot(); return this.header.getTxTrieRoot();
} }
public byte[] getLogBloom(){ public byte[] getLogBloom() {
if (!parsed) parseRLP(); if (!parsed) parseRLP();
return this.header.getLogsBloom(); return this.header.getLogsBloom();
} }
@ -243,7 +244,7 @@ public class Block {
toStringBuff.append(header.toString()); toStringBuff.append(header.toString());
toStringBuff.append("\nUncles [\n"); toStringBuff.append("\nUncles [\n");
for (BlockHeader uncle : getUncleList()){ for (BlockHeader uncle : getUncleList()) {
toStringBuff.append(uncle.toString()); toStringBuff.append(uncle.toString());
toStringBuff.append("\n"); toStringBuff.append("\n");
} }
@ -277,20 +278,21 @@ public class Block {
for (int i = 0; i < txTransactions.size(); i++) { for (int i = 0; i < txTransactions.size(); i++) {
RLPElement transactionRaw = txTransactions.get(i); RLPElement transactionRaw = txTransactions.get(i);
this.transactionsList.add(new Transaction(transactionRaw.getRLPData())); 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()); 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"); logger.error("Added tx receipts don't match the given txsStateRoot");
} }
/** /**
* check if param block is son of this block * check if param block is son of this block
*
* @param block - possible a son of this * @param block - possible a son of this
* @return - true if this block is parent of param block * @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()); return Arrays.areEqual(this.getHash(), block.getParentHash());
} }
@ -298,29 +300,29 @@ public class Block {
return this.header.isGenesis(); return this.header.isGenesis();
} }
public boolean isEqual(Block block){ public boolean isEqual(Block block) {
return Arrays.areEqual(this.getHash(), block.getHash()); return Arrays.areEqual(this.getHash(), block.getHash());
} }
private byte[] getUnclesEncoded(){ private byte[] getUnclesEncoded() {
byte[][] unclesEncoded = new byte[uncleList.size()][]; byte[][] unclesEncoded = new byte[uncleList.size()][];
int i = 0; int i = 0;
for( BlockHeader uncle : uncleList ){ for (BlockHeader uncle : uncleList) {
unclesEncoded[i] = uncle.getEncoded(); unclesEncoded[i] = uncle.getEncoded();
++i; ++i;
} }
return RLP.encodeList(unclesEncoded); return RLP.encodeList(unclesEncoded);
} }
public void addUncle(BlockHeader uncle){ public void addUncle(BlockHeader uncle) {
uncleList.add(uncle); uncleList.add(uncle);
this.getHeader().setUnclesHash( SHA3Helper.sha3( getUnclesEncoded() )); this.getHeader().setUnclesHash(SHA3Helper.sha3(getUnclesEncoded()));
rlpEncoded = null; rlpEncoded = null;
} }
public byte[] getEncoded() { public byte[] getEncoded() {
if(rlpEncoded == null) { if (rlpEncoded == null) {
byte[] header = this.header.getEncoded(); byte[] header = this.header.getEncoded();
byte[] transactions = RLP.encodeList(); byte[] transactions = RLP.encodeList();
byte[] uncles = getUnclesEncoded(); byte[] uncles = getUnclesEncoded();
@ -335,7 +337,7 @@ public class Block {
return header; return header;
} }
public String getShortHash(){ public String getShortHash() {
if (!parsed) parseRLP(); if (!parsed) parseRLP();
return Hex.toHexString(getHash()).substring(0, 6); return Hex.toHexString(getHash()).substring(0, 6);
} }

View File

@ -18,7 +18,7 @@ public class BlockHeader {
/* The SHA3 256-bit hash of the parent block, in its entirety */ /* 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 */ /* The SHA3 256-bit hash of the uncles list portion of this block */
private byte[] unclesHash; private byte[] unclesHash;
/* The 160-bit address to which all fees collected from the /* The 160-bit address to which all fees collected from the
@ -63,40 +63,40 @@ public class BlockHeader {
public BlockHeader(RLPList rlpHeader) { public BlockHeader(RLPList rlpHeader) {
this.parentHash = rlpHeader.get(0).getRLPData(); this.parentHash = rlpHeader.get(0).getRLPData();
this.unclesHash = rlpHeader.get(1).getRLPData(); this.unclesHash = rlpHeader.get(1).getRLPData();
this.coinbase = rlpHeader.get(2).getRLPData(); this.coinbase = rlpHeader.get(2).getRLPData();
this.stateRoot = rlpHeader.get(3).getRLPData(); this.stateRoot = rlpHeader.get(3).getRLPData();
this.txTrieRoot = rlpHeader.get(4).getRLPData(); this.txTrieRoot = rlpHeader.get(4).getRLPData();
if(this.txTrieRoot == null) if (this.txTrieRoot == null)
this.txTrieRoot = EMPTY_TRIE_HASH; this.txTrieRoot = EMPTY_TRIE_HASH;
this.recieptTrieRoot = rlpHeader.get(5).getRLPData(); this.recieptTrieRoot = rlpHeader.get(5).getRLPData();
if(this.recieptTrieRoot == null) if (this.recieptTrieRoot == null)
this.recieptTrieRoot = EMPTY_TRIE_HASH; this.recieptTrieRoot = EMPTY_TRIE_HASH;
this.logsBloom = rlpHeader.get(6).getRLPData(); this.logsBloom = rlpHeader.get(6).getRLPData();
this.difficulty = rlpHeader.get(7).getRLPData(); this.difficulty = rlpHeader.get(7).getRLPData();
byte[] nrBytes = rlpHeader.get(8).getRLPData(); byte[] nrBytes = rlpHeader.get(8).getRLPData();
byte[] glBytes = rlpHeader.get(9).getRLPData(); byte[] glBytes = rlpHeader.get(9).getRLPData();
byte[] guBytes = rlpHeader.get(10).getRLPData(); byte[] guBytes = rlpHeader.get(10).getRLPData();
byte[] tsBytes = rlpHeader.get(11).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.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue(); this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue(); this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue();
this.extraData = rlpHeader.get(12).getRLPData(); this.extraData = rlpHeader.get(12).getRLPData();
this.nonce = rlpHeader.get(13).getRLPData(); this.nonce = rlpHeader.get(13).getRLPData();
} }
public BlockHeader(byte[] parentHash, byte[] unclesHash, byte[] coinbase, 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, long gasLimit, long gasUsed, long timestamp,
byte[] extraData, byte[] nonce) { byte[] extraData, byte[] nonce) {
this.parentHash = parentHash; this.parentHash = parentHash;
@ -117,6 +117,7 @@ public class BlockHeader {
/** /**
* Calculate Difficulty * Calculate Difficulty
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (24) * See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (24)
*
* @return byte array value of the difficulty * @return byte array value of the difficulty
*/ */
public byte[] calcDifficulty() { public byte[] calcDifficulty() {
@ -132,8 +133,6 @@ public class BlockHeader {
} }
public boolean isGenesis() { public boolean isGenesis() {
return this.getNumber() == Genesis.NUMBER; return this.getNumber() == Genesis.NUMBER;
} }
@ -141,79 +140,107 @@ public class BlockHeader {
public byte[] getParentHash() { public byte[] getParentHash() {
return parentHash; return parentHash;
} }
public void setParentHash(byte[] parentHash) { public void setParentHash(byte[] parentHash) {
this.parentHash = parentHash; this.parentHash = parentHash;
} }
public byte[] getUnclesHash() { public byte[] getUnclesHash() {
return unclesHash; return unclesHash;
} }
public void setUnclesHash(byte[] unclesHash) { public void setUnclesHash(byte[] unclesHash) {
this.unclesHash = unclesHash; this.unclesHash = unclesHash;
} }
public byte[] getCoinbase() { public byte[] getCoinbase() {
return coinbase; return coinbase;
} }
public void setCoinbase(byte[] coinbase) { public void setCoinbase(byte[] coinbase) {
this.coinbase = coinbase; this.coinbase = coinbase;
} }
public byte[] getStateRoot() { public byte[] getStateRoot() {
return stateRoot; return stateRoot;
} }
public void setStateRoot(byte[] stateRoot) { public void setStateRoot(byte[] stateRoot) {
this.stateRoot = stateRoot; this.stateRoot = stateRoot;
} }
public byte[] getTxTrieRoot() { public byte[] getTxTrieRoot() {
return txTrieRoot; return txTrieRoot;
} }
public void setTxTrieRoot(byte[] txTrieRoot) { public void setTxTrieRoot(byte[] txTrieRoot) {
this.txTrieRoot = txTrieRoot; this.txTrieRoot = txTrieRoot;
} }
public byte[] getRecieptTrieRoot() { public byte[] getRecieptTrieRoot() {
return recieptTrieRoot; return recieptTrieRoot;
} }
public byte[] getLogsBloom() {return logsBloom;}
public byte[] getLogsBloom() {
return logsBloom;
}
public void setRecieptTrieRoot(byte[] recieptTrieRoot) { public void setRecieptTrieRoot(byte[] recieptTrieRoot) {
this.recieptTrieRoot = recieptTrieRoot; this.recieptTrieRoot = recieptTrieRoot;
} }
public byte[] getDifficulty() { public byte[] getDifficulty() {
return difficulty; return difficulty;
} }
public void setDifficulty(byte[] difficulty) { public void setDifficulty(byte[] difficulty) {
this.difficulty = difficulty; this.difficulty = difficulty;
} }
public long getTimestamp() { public long getTimestamp() {
return timestamp; return timestamp;
} }
public void setTimestamp(long timestamp) { public void setTimestamp(long timestamp) {
this.timestamp = timestamp; this.timestamp = timestamp;
} }
public long getNumber() { public long getNumber() {
return number; return number;
} }
public void setNumber(long number) { public void setNumber(long number) {
this.number = number; this.number = number;
} }
public long getGasLimit() { public long getGasLimit() {
return gasLimit; return gasLimit;
} }
public void setGasLimit(long gasLimit) { public void setGasLimit(long gasLimit) {
this.gasLimit = gasLimit; this.gasLimit = gasLimit;
} }
public long getGasUsed() { public long getGasUsed() {
return gasUsed; return gasUsed;
} }
public void setGasUsed(long gasUsed) { public void setGasUsed(long gasUsed) {
this.gasUsed = gasUsed; this.gasUsed = gasUsed;
} }
public byte[] getExtraData() { public byte[] getExtraData() {
return extraData; return extraData;
} }
public void setExtraData(byte[] extraData) { public void setExtraData(byte[] extraData) {
this.extraData = extraData; this.extraData = extraData;
} }
public byte[] getNonce() { public byte[] getNonce() {
return nonce; return nonce;
} }
public void setNonce(byte[] nonce) { public void setNonce(byte[] nonce) {
this.nonce = nonce; this.nonce = nonce;
} }
@ -227,31 +254,31 @@ public class BlockHeader {
} }
public byte[] getEncoded(boolean withNonce) { public byte[] getEncoded(boolean withNonce) {
byte[] parentHash = RLP.encodeElement(this.parentHash); byte[] parentHash = RLP.encodeElement(this.parentHash);
byte[] unclesHash = RLP.encodeElement(this.unclesHash); byte[] unclesHash = RLP.encodeElement(this.unclesHash);
byte[] coinbase = RLP.encodeElement(this.coinbase); 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; 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; 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[] logsBloom = RLP.encodeElement(this.logsBloom);
byte[] difficulty = RLP.encodeElement(this.difficulty); byte[] difficulty = RLP.encodeElement(this.difficulty);
byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number)); byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number));
byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit)); byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit));
byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed)); byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed));
byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp)); byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp));
byte[] extraData = RLP.encodeElement(this.extraData); byte[] extraData = RLP.encodeElement(this.extraData);
if(withNonce) { if (withNonce) {
byte[] nonce = RLP.encodeElement(this.nonce); byte[] nonce = RLP.encodeElement(this.nonce);
return RLP.encodeList(parentHash, unclesHash, coinbase, return RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number, stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
gasLimit, gasUsed, timestamp, extraData, nonce); gasLimit, gasUsed, timestamp, extraData, nonce);
} else { } else {
return RLP.encodeList(parentHash, unclesHash, coinbase, return RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number, stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
@ -260,7 +287,6 @@ public class BlockHeader {
} }
private StringBuffer toStringBuff = new StringBuffer(); private StringBuffer toStringBuff = new StringBuffer();
public String toString() { public String toString() {
@ -269,16 +295,16 @@ public class BlockHeader {
toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("\n"); toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("\n");
toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("\n"); toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("\n");
toStringBuff.append(" coinbase=" + toHexString(coinbase)).append("\n"); toStringBuff.append(" coinbase=" + toHexString(coinbase)).append("\n");
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("\n"); toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("\n");
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("\n"); toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("\n");
toStringBuff.append(" reciptsTrieHash=" + toHexString(recieptTrieRoot)).append("\n"); toStringBuff.append(" reciptsTrieHash=" + toHexString(recieptTrieRoot)).append("\n");
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("\n"); toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("\n");
toStringBuff.append(" number=" + number).append("\n"); toStringBuff.append(" number=" + number).append("\n");
toStringBuff.append(" gasLimit=" + gasLimit).append("\n"); toStringBuff.append(" gasLimit=" + gasLimit).append("\n");
toStringBuff.append(" gasUsed=" + gasUsed).append("\n"); toStringBuff.append(" gasUsed=" + gasUsed).append("\n");
toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n"); toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n");
toStringBuff.append(" extraData=" + toHexString(extraData)).append("\n"); toStringBuff.append(" extraData=" + toHexString(extraData)).append("\n");
toStringBuff.append(" nonce=" + toHexString(nonce)).append("\n"); toStringBuff.append(" nonce=" + toHexString(nonce)).append("\n");
return toStringBuff.toString(); return toStringBuff.toString();
} }
@ -286,15 +312,15 @@ public class BlockHeader {
toStringBuff.append(" parentHash=" + toHexString(parentHash)).append(""); toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("");
toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append(""); toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("");
toStringBuff.append(" coinbase=" + toHexString(coinbase)).append(""); toStringBuff.append(" coinbase=" + toHexString(coinbase)).append("");
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append(""); toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("");
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append(""); toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("");
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append(""); toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("");
toStringBuff.append(" number=" + number).append(""); toStringBuff.append(" number=" + number).append("");
toStringBuff.append(" gasLimit=" + gasLimit).append(""); toStringBuff.append(" gasLimit=" + gasLimit).append("");
toStringBuff.append(" gasUsed=" + gasUsed).append(""); toStringBuff.append(" gasUsed=" + gasUsed).append("");
toStringBuff.append(" timestamp=" + timestamp).append(""); toStringBuff.append(" timestamp=" + timestamp).append("");
toStringBuff.append(" extraData=" + toHexString(extraData)).append(""); toStringBuff.append(" extraData=" + toHexString(extraData)).append("");
toStringBuff.append(" nonce=" + toHexString(nonce)).append(""); toStringBuff.append(" nonce=" + toHexString(nonce)).append("");
return toStringBuff.toString(); return toStringBuff.toString();
} }

View File

@ -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>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 S[0] be the STATE_ROOT of the previous block.</li>
* <li>Let TX be the block's transaction list, with n transactions. * <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 * 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> * 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> * <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> * See <a href="https://github.com/ethereum/wiki/wiki/White-Paper#blockchain-and-mining">Ethereum Whitepaper</a>
* *
* www.etherJ.com * www.etherJ.com
*
* @author Roman Mandeleil, * @author Roman Mandeleil,
* Nick Savers * Nick Savers
* Created on: 20/05/2014 10:44 * Created on: 20/05/2014 10:44
@ -119,23 +120,23 @@ public class BlockchainImpl implements Blockchain {
} }
@Override @Override
public TransactionReceipt getTransactionReceiptByHash(byte[] hash){ public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
return blockStore.getTransactionReceiptByHash(hash); return blockStore.getTransactionReceiptByHash(hash);
} }
@Override @Override
public Block getBlockByHash(byte[] hash){ public Block getBlockByHash(byte[] hash) {
return blockStore.getBlockByHash(hash); return blockStore.getBlockByHash(hash);
} }
@Override @Override
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty){ public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty) {
return blockStore.getListOfHashesStartFrom(hash, qty); return blockStore.getListOfHashesStartFrom(hash, qty);
} }
public void tryToConnect(Block block){ public void tryToConnect(Block block) {
recordBlock(block); recordBlock(block);
@ -144,7 +145,7 @@ public class BlockchainImpl implements Blockchain {
Hex.toHexString(block.getHash()).substring(0, 6), Hex.toHexString(block.getHash()).substring(0, 6),
block.getNumber()); block.getNumber());
if (blockStore.getBlockByHash(block.getHash()) != null){ if (blockStore.getBlockByHash(block.getHash()) != null) {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("Block already exist hash: {}, number: {}", logger.debug("Block already exist hash: {}, number: {}",
@ -157,12 +158,12 @@ public class BlockchainImpl implements Blockchain {
// The simple case got the block // The simple case got the block
// to connect to the main chain // to connect to the main chain
if (bestBlock.isParentOf(block)){ if (bestBlock.isParentOf(block)) {
add(block); add(block);
return; return;
} }
if (!hasParentOnTheChain(block) && block.getNumber() > bestBlock.getNumber()){ if (!hasParentOnTheChain(block) && block.getNumber() > bestBlock.getNumber()) {
logger.info("*** Blockchain will rollback and resynchronise now "); logger.info("*** Blockchain will rollback and resynchronise now ");
@ -198,7 +199,7 @@ public class BlockchainImpl implements Blockchain {
// keep chain continuity // keep chain continuity
if (!Arrays.equals(getBestBlock().getHash(), if (!Arrays.equals(getBestBlock().getHash(),
block.getParentHash())) return; block.getParentHash())) return;
if (block.getNumber() >= CONFIG.traceStartBlock() && CONFIG.traceStartBlock() != -1) { if (block.getNumber() >= CONFIG.traceStartBlock() && CONFIG.traceStartBlock() != -1) {
AdvancedDeviceUtils.adjustDetailedTracing(block.getNumber()); AdvancedDeviceUtils.adjustDetailedTracing(block.getNumber());
@ -221,8 +222,8 @@ public class BlockchainImpl implements Blockchain {
listener.onBlock(block); listener.onBlock(block);
if (blockQueue.size() == 0 && if (blockQueue.size() == 0 &&
!syncDoneCalled && !syncDoneCalled &&
channelManager.isAllSync()){ channelManager.isAllSync()) {
logger.info("Sync done"); logger.info("Sync done");
syncDoneCalled = true; 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()); return blockStore.getBlockByHash(header.getParentHash());
} }
@ -239,6 +240,7 @@ public class BlockchainImpl implements Blockchain {
/** /**
* Calculate GasLimit * Calculate GasLimit
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (25) * See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (25)
*
* @return long value of the gasLimit * @return long value of the gasLimit
*/ */
public long calcGasLimit(BlockHeader header) { 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, * likely next period. Conversely, if the period is too large, the difficulty,
* and expected time to the next block, is reduced. * and expected time to the next block, is reduced.
*/ */
private boolean isValid(Block block){ private boolean isValid(Block block) {
boolean isValid = true; boolean isValid = true;
if (isValid) return (isValid); // todo get back to the real header validation if (isValid) return (isValid); // todo get back to the real header validation
if(!block.isGenesis()) { if (!block.isGenesis()) {
isValid = isValid(block.getHeader()); isValid = isValid(block.getHeader());
for (BlockHeader uncle : block.getUncleList()) { for (BlockHeader uncle : block.getUncleList()) {
@ -291,7 +293,7 @@ public class BlockchainImpl implements Blockchain {
isValid = generationGap > 0 && generationGap < 7; isValid = generationGap > 0 && generationGap < 7;
} }
} }
if(!isValid) if (!isValid)
logger.warn("WARNING: Invalid - {}", this); logger.warn("WARNING: Invalid - {}", this);
return isValid; return isValid;
@ -300,7 +302,7 @@ public class BlockchainImpl implements Blockchain {
private void processBlock(Block block) { private void processBlock(Block block) {
List<TransactionReceipt> receipts = new ArrayList<>(); List<TransactionReceipt> receipts = new ArrayList<>();
if(isValid(block)) { if (isValid(block)) {
if (!block.isGenesis()) { if (!block.isGenesis()) {
if (!CONFIG.blockChainOnly()) { if (!CONFIG.blockChainOnly()) {
wallet.addTransactions(block.getTransactionsList()); wallet.addTransactions(block.getTransactionsList());
@ -341,9 +343,9 @@ public class BlockchainImpl implements Blockchain {
stateLogger.info("[{}] ", receipt.toString()); stateLogger.info("[{}] ", receipt.toString());
if (stateLogger.isInfoEnabled()) 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()); repository.dumpState(block, totalGasUsed, i++, tx.getHash());
reciepts.add(receipt); reciepts.add(receipt);
@ -354,7 +356,7 @@ public class BlockchainImpl implements Blockchain {
track.commit(); track.commit();
if(block.getNumber() >= CONFIG.traceStartBlock()) if (block.getNumber() >= CONFIG.traceStartBlock())
repository.dumpState(block, totalGasUsed, 0, null); repository.dumpState(block, totalGasUsed, 0, null);
return reciepts; return reciepts;
@ -372,7 +374,7 @@ public class BlockchainImpl implements Blockchain {
BigInteger totalBlockReward = Block.BLOCK_REWARD; BigInteger totalBlockReward = Block.BLOCK_REWARD;
// Add extra rewards based on number of uncles // Add extra rewards based on number of uncles
if(block.getUncleList().size() > 0) { if (block.getUncleList().size() > 0) {
for (BlockHeader uncle : block.getUncleList()) { for (BlockHeader uncle : block.getUncleList()) {
track.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD); track.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD);
} }
@ -386,10 +388,10 @@ public class BlockchainImpl implements Blockchain {
public void storeBlock(Block block, List<TransactionReceipt> receipts) { public void storeBlock(Block block, List<TransactionReceipt> receipts) {
/* Debug check to see if the state is still as expected */ /* Debug check to see if the state is still as expected */
if(logger.isWarnEnabled()) { if (logger.isWarnEnabled()) {
String blockStateRootHash = Hex.toHexString(block.getStateRoot()); String blockStateRootHash = Hex.toHexString(block.getStateRoot());
String worldStateRootHash = Hex.toHexString(repository.getRoot()); 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); stateLogger.info("BLOCK: STATE CONFLICT! block: {} worldstate {} mismatch", block.getNumber(), worldStateRootHash);
adminInfo.lostConsensus(); 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; return getParent(block.getHeader()) != null;
} }
@Override @Override
public List<Chain> getAltChains(){ public List<Chain> getAltChains() {
return altChains; return altChains;
} }
@Override @Override
public List<Block> getGarbage(){ public List<Block> getGarbage() {
return garbage; return garbage;
} }
@ -442,14 +444,14 @@ public class BlockchainImpl implements Blockchain {
} }
@Override @Override
public void reset(){ public void reset() {
blockStore.reset(); blockStore.reset();
altChains = new ArrayList<>(); altChains = new ArrayList<>();
garbage = new ArrayList<>(); garbage = new ArrayList<>();
} }
@Override @Override
public void close(){ public void close() {
blockQueue.close(); blockQueue.close();
} }
@ -468,12 +470,15 @@ public class BlockchainImpl implements Blockchain {
this.totalDifficulty = totalDifficulty; this.totalDifficulty = totalDifficulty;
} }
private void recordBlock(Block block){ private void recordBlock(Block block) {
if (!CONFIG.recordBlocks()) return; if (!CONFIG.recordBlocks()) return;
if (bestBlock.isGenesis()){ if (bestBlock.isGenesis()) {
try {FileUtils.deleteDirectory(CONFIG.dumpDir());} catch (IOException e) {} try {
FileUtils.deleteDirectory(CONFIG.dumpDir());
} catch (IOException e) {
}
} }
String dir = CONFIG.dumpDir() + "/"; String dir = CONFIG.dumpDir() + "/";
@ -490,7 +495,7 @@ public class BlockchainImpl implements Blockchain {
fw = new FileWriter(dumpFile.getAbsoluteFile(), true); fw = new FileWriter(dumpFile.getAbsoluteFile(), true);
bw = new BufferedWriter(fw); bw = new BufferedWriter(fw);
if (bestBlock.isGenesis()){ if (bestBlock.isGenesis()) {
bw.write(Hex.toHexString(bestBlock.getEncoded())); bw.write(Hex.toHexString(bestBlock.getEncoded()));
bw.write("\n"); bw.write("\n");
} }
@ -516,15 +521,15 @@ public class BlockchainImpl implements Blockchain {
this.repository = repository; this.repository = repository;
} }
public void setProgramInvokeFactory(ProgramInvokeFactory factory){ public void setProgramInvokeFactory(ProgramInvokeFactory factory) {
this.programInvokeFactory = factory; this.programInvokeFactory = factory;
} }
public void startTracking(){ public void startTracking() {
track = repository.startTracking(); track = repository.startTracking();
} }
public void commitTracking(){ public void commitTracking() {
track.commit(); track.commit();
} }

View File

@ -15,14 +15,14 @@ import java.util.Arrays;
* http://www.herongyang.com/Java/Bit-String-Set-Bit-to-Byte-Array.html * http://www.herongyang.com/Java/Bit-String-Set-Bit-to-Byte-Array.html
*/ */
public class Bloom { public class Bloom {
byte[] data = new byte[64]; byte[] data = new byte[64];
public Bloom() { public Bloom() {
} }
public Bloom(byte[] data){ public Bloom(byte[] data) {
this.data = data; this.data = data;
} }
@ -41,8 +41,8 @@ public class Bloom {
return bloom; return bloom;
} }
public void or(Bloom bloom){ public void or(Bloom bloom) {
for (int i = 0; i < data.length; ++i){ for (int i = 0; i < data.length; ++i) {
data[i] |= bloom.data[i]; data[i] |= bloom.data[i];
} }
} }

View File

@ -27,7 +27,7 @@ public class Chain {
private Map<ByteArrayWrapper, Block> index = new HashMap<>(); private Map<ByteArrayWrapper, Block> index = new HashMap<>();
public boolean tryToConnect(Block block){ public boolean tryToConnect(Block block) {
if (chain.isEmpty()) { if (chain.isEmpty()) {
add(block); add(block);
@ -35,14 +35,14 @@ public class Chain {
} }
Block lastBlock = chain.get(chain.size() - 1); Block lastBlock = chain.get(chain.size() - 1);
if (lastBlock.isParentOf(block)){ if (lastBlock.isParentOf(block)) {
add(block); add(block);
return true; return true;
} }
return false; return false;
} }
public void add(Block block){ public void add(Block block) {
logger.info("adding block to alt chain block.hash: [{}] ", block.getShortHash()); logger.info("adding block to alt chain block.hash: [{}] ", block.getShortHash());
totalDifficulty = totalDifficulty.add(block.getCumulativeDifficulty()); totalDifficulty = totalDifficulty.add(block.getCumulativeDifficulty());
logger.info("total difficulty on alt chain is: [{}] ", totalDifficulty); logger.info("total difficulty on alt chain is: [{}] ", totalDifficulty);
@ -50,15 +50,15 @@ public class Chain {
index.put(new ByteArrayWrapper(block.getHash()), block); index.put(new ByteArrayWrapper(block.getHash()), block);
} }
public Block get(int i){ public Block get(int i) {
return chain.get(i); return chain.get(i);
} }
public Block getLast(){ public Block getLast() {
return chain.get(chain.size() - 1); return chain.get(chain.size() - 1);
} }
public BigInteger getTotalDifficulty(){ public BigInteger getTotalDifficulty() {
return totalDifficulty; return totalDifficulty;
} }
@ -66,11 +66,11 @@ public class Chain {
this.totalDifficulty = totalDifficulty; this.totalDifficulty = totalDifficulty;
} }
public boolean isParentOnTheChain(Block block){ public boolean isParentOnTheChain(Block block) {
return (index.get(new ByteArrayWrapper( block.getParentHash() )) != null); return (index.get(new ByteArrayWrapper(block.getParentHash())) != null);
} }
public long getSize(){ public long getSize() {
return chain.size(); return chain.size();
} }

View File

@ -30,7 +30,7 @@ public class Genesis extends Block {
public final static BigInteger PREMINE_AMOUNT = BigInteger.valueOf(2).pow(200); public final static BigInteger PREMINE_AMOUNT = BigInteger.valueOf(2).pow(200);
private static String[] premine = new String[] { private static String[] premine = new String[]{
"51ba59315b3a95761d0863b05ccc7a7f54703d99", "51ba59315b3a95761d0863b05ccc7a7f54703d99",
"e6716f9544a56c530d868e4bfbacb172315bdead", // # (J) "e6716f9544a56c530d868e4bfbacb172315bdead", // # (J)
"b9c015918bdaba24b4ff057a92a3873d6eb201be", // # (V) "b9c015918bdaba24b4ff057a92a3873d6eb201be", // # (V)
@ -50,10 +50,10 @@ public class Genesis extends Block {
public static byte[] COINBASE = zeroHash160; public static byte[] COINBASE = zeroHash160;
public static byte[] LOG_BLOOM = zeroHash512; public static byte[] LOG_BLOOM = zeroHash512;
public static byte[] DIFFICULTY = BigInteger.valueOf(2).pow(17).toByteArray(); public static byte[] DIFFICULTY = BigInteger.valueOf(2).pow(17).toByteArray();
public static long NUMBER = 0; public static long NUMBER = 0;
public static long GAS_LIMIT = 1000000; public static long GAS_LIMIT = 1000000;
public static long GAS_USED = 0; public static long GAS_USED = 0;
public static long TIMESTAMP = 0; public static long TIMESTAMP = 0;
public static byte[] EXTRA_DATA = new byte[0]; public static byte[] EXTRA_DATA = new byte[0];
public static byte[] NONCE = sha3(new byte[]{42}); public static byte[] NONCE = sha3(new byte[]{42});

View File

@ -10,6 +10,7 @@ import org.ethereum.util.RLPList;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.spongycastle.util.BigIntegers; import org.spongycastle.util.BigIntegers;
import java.security.SignatureException; import java.security.SignatureException;
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY; import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
@ -86,7 +87,7 @@ public class Transaction {
this.value = value; this.value = value;
this.data = data; this.data = data;
if(receiveAddress == null) { if (receiveAddress == null) {
this.receiveAddress = ByteUtil.EMPTY_BYTE_ARRAY; this.receiveAddress = ByteUtil.EMPTY_BYTE_ARRAY;
} }
@ -97,25 +98,25 @@ public class Transaction {
public void rlpParse() { public void rlpParse() {
RLPList decodedTxList = RLP.decode2(rlpEncoded); RLPList decodedTxList = RLP.decode2(rlpEncoded);
RLPList transaction = (RLPList) decodedTxList.get(0); RLPList transaction = (RLPList) decodedTxList.get(0);
this.nonce = transaction.get(0).getRLPData(); this.nonce = transaction.get(0).getRLPData();
this.gasPrice = transaction.get(1).getRLPData(); this.gasPrice = transaction.get(1).getRLPData();
this.gasLimit = transaction.get(2).getRLPData(); this.gasLimit = transaction.get(2).getRLPData();
this.receiveAddress = transaction.get(3).getRLPData(); this.receiveAddress = transaction.get(3).getRLPData();
this.value = transaction.get(4).getRLPData(); this.value = transaction.get(4).getRLPData();
this.data = transaction.get(5).getRLPData(); this.data = transaction.get(5).getRLPData();
// only parse signature in case tx is signed // only parse signature in case tx is signed
if(transaction.get(6).getRLPData() != null) { if (transaction.get(6).getRLPData() != null) {
byte v = transaction.get(6).getRLPData()[0]; byte v = transaction.get(6).getRLPData()[0];
byte[] r = transaction.get(7).getRLPData(); byte[] r = transaction.get(7).getRLPData();
byte[] s = transaction.get(8).getRLPData(); byte[] s = transaction.get(8).getRLPData();
this.signature = ECDSASignature.fromComponents(r, s, v); this.signature = ECDSASignature.fromComponents(r, s, v);
} else { } else {
logger.debug("RLP encoded tx is not signed!"); logger.debug("RLP encoded tx is not signed!");
} }
this.parsed = true; this.parsed = true;
this.hash = getHash(); this.hash = getHash();
} }
public boolean isParsed() { public boolean isParsed() {
@ -158,7 +159,7 @@ public class Transaction {
public byte[] getGasPrice() { public byte[] getGasPrice() {
if (!parsed) rlpParse(); if (!parsed) rlpParse();
return gasPrice== null ? ZERO_BYTE_ARRAY : gasPrice; return gasPrice == null ? ZERO_BYTE_ARRAY : gasPrice;
} }
public byte[] getGasLimit() { public byte[] getGasLimit() {
@ -166,7 +167,7 @@ public class Transaction {
return gasLimit; return gasLimit;
} }
public long nonZeroDataBytes(){ public long nonZeroDataBytes() {
if (data == null) return 0; if (data == null) return 0;
int counter = 0; int counter = 0;
for (final byte aData : data) { for (final byte aData : data) {
@ -175,7 +176,7 @@ public class Transaction {
return counter; return counter;
} }
public long zeroDataBytes(){ public long zeroDataBytes() {
if (data == null) return 0; if (data == null) return 0;
int counter = 0; int counter = 0;
for (final byte aData : data) { for (final byte aData : data) {
@ -237,7 +238,7 @@ public class Transaction {
@Override @Override
public String toString() { public String toString() {
if (!parsed) rlpParse(); if (!parsed) rlpParse();
return "TransactionData [" + "hash=" + ByteUtil.toHexString(hash) + return "TransactionData [" + "hash=" + ByteUtil.toHexString(hash) +
" nonce=" + ByteUtil.toHexString(nonce) + " nonce=" + ByteUtil.toHexString(nonce) +
", gasPrice=" + ByteUtil.toHexString(gasPrice) + ", gasPrice=" + ByteUtil.toHexString(gasPrice) +
", gas=" + ByteUtil.toHexString(gasLimit) + ", gas=" + ByteUtil.toHexString(gasLimit) +
@ -251,8 +252,8 @@ public class Transaction {
} }
/** /**
* For signatures you have to keep also * For signatures you have to keep also
* RLP of the transaction without any signature data * RLP of the transaction without any signature data
*/ */
public byte[] getEncodedRaw() { public byte[] getEncodedRaw() {
@ -261,16 +262,16 @@ public class Transaction {
// parse null as 0 for nonce // parse null as 0 for nonce
byte[] nonce = null; byte[] nonce = null;
if ( this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0){ if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) {
nonce = RLP.encodeElement(null); nonce = RLP.encodeElement(null);
} else { } else {
nonce = RLP.encodeElement(this.nonce); nonce = RLP.encodeElement(this.nonce);
} }
byte[] gasPrice = RLP.encodeElement(this.gasPrice); byte[] gasPrice = RLP.encodeElement(this.gasPrice);
byte[] gasLimit = RLP.encodeElement(this.gasLimit); byte[] gasLimit = RLP.encodeElement(this.gasLimit);
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress); byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
byte[] value = RLP.encodeElement(this.value); byte[] value = RLP.encodeElement(this.value);
byte[] data = RLP.encodeElement(this.data); byte[] data = RLP.encodeElement(this.data);
rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress,
value, data); value, data);
@ -279,25 +280,25 @@ public class Transaction {
public byte[] getEncoded() { public byte[] getEncoded() {
if(rlpEncoded != null) return rlpEncoded; if (rlpEncoded != null) return rlpEncoded;
// parse null as 0 for nonce // parse null as 0 for nonce
byte[] nonce = null; byte[] nonce = null;
if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0){ if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) {
nonce = RLP.encodeElement(null); nonce = RLP.encodeElement(null);
} else { } else {
nonce = RLP.encodeElement(this.nonce); nonce = RLP.encodeElement(this.nonce);
} }
byte[] gasPrice = RLP.encodeElement(this.gasPrice); byte[] gasPrice = RLP.encodeElement(this.gasPrice);
byte[] gasLimit = RLP.encodeElement(this.gasLimit); byte[] gasLimit = RLP.encodeElement(this.gasLimit);
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress); byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
byte[] value = RLP.encodeElement(this.value); byte[] value = RLP.encodeElement(this.value);
byte[] data = RLP.encodeElement(this.data); byte[] data = RLP.encodeElement(this.data);
byte[] v, r, s; byte[] v, r, s;
if(signature != null) { if (signature != null) {
v = RLP.encodeByte( signature.v ); v = RLP.encodeByte(signature.v);
r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r)); r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r));
s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s)); s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s));
} else { } else {
@ -309,7 +310,7 @@ public class Transaction {
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit,
receiveAddress, value, data, v, r, s); receiveAddress, value, data, v, r, s);
this.hash = this.getHash(); this.hash = this.getHash();
return rlpEncoded; return rlpEncoded;
} }
@ -331,7 +332,7 @@ public class Transaction {
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (!(obj instanceof Transaction)) return false; if (!(obj instanceof Transaction)) return false;
Transaction tx = (Transaction)obj; Transaction tx = (Transaction) obj;
return tx.hashCode() == this.hashCode(); return tx.hashCode() == this.hashCode();
} }

View File

@ -38,7 +38,7 @@ public class TransactionExecutor {
ProgramInvokeFactory programInvokeFactory, Block currentBlock) { ProgramInvokeFactory programInvokeFactory, Block currentBlock) {
this.tx = tx; this.tx = tx;
this.coinbase = coinbase; this.coinbase = coinbase;
this.track = track; this.track = track;
this.programInvokeFactory = programInvokeFactory; this.programInvokeFactory = programInvokeFactory;
this.currentBlock = currentBlock; this.currentBlock = currentBlock;
@ -53,7 +53,7 @@ public class TransactionExecutor {
// https://github.com/ethereum/cpp-ethereum/blob/develop/libethereum/Executive.cpp#L55 // 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())); logger.info("applyTransaction: [{}]", Hex.toHexString(tx.getHash()));
@ -166,8 +166,8 @@ public class TransactionExecutor {
try { try {
// CREATE NEW CONTRACT ADDRESS AND ADD TX VALUE // CREATE NEW CONTRACT ADDRESS AND ADD TX VALUE
if(isContractCreation) { if (isContractCreation) {
if(stateLogger.isDebugEnabled()) if (stateLogger.isDebugEnabled())
stateLogger.debug("new contract created address={}", stateLogger.debug("new contract created address={}",
Hex.toHexString(receiverAddress)); Hex.toHexString(receiverAddress));
} }
@ -199,9 +199,9 @@ public class TransactionExecutor {
trackTx.commit(); trackTx.commit();
} else { } else {
// REFUND GASDEBIT EXCEPT FOR FEE (500 + 5*TX_NO_ZERO_DATA) // 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.nonZeroDataBytes() * GasCost.TX_NO_ZERO_DATA +
tx.zeroDataBytes() * GasCost.TX_ZERO_DATA; tx.zeroDataBytes() * GasCost.TX_ZERO_DATA;
gasUsed = GasCost.TRANSACTION + dataCost; gasUsed = GasCost.TRANSACTION + dataCost;
BigInteger refund = gasDebit.subtract(BigInteger.valueOf(gasUsed).multiply(gasPrice)); BigInteger refund = gasDebit.subtract(BigInteger.valueOf(gasUsed).multiply(gasPrice));
@ -253,7 +253,7 @@ public class TransactionExecutor {
repository.addBalance(coinbase, refund.negate()); repository.addBalance(coinbase, refund.negate());
} }
if (result.getFutureRefund() > 0){ if (result.getFutureRefund() > 0) {
long futureRefund = Math.min(result.getFutureRefund(), result.getGasUsed() / 2); long futureRefund = Math.min(result.getFutureRefund(), result.getGasUsed() / 2);
BigInteger futureRefundBI = BigInteger.valueOf(futureRefund); BigInteger futureRefundBI = BigInteger.valueOf(futureRefund);
@ -284,11 +284,12 @@ public class TransactionExecutor {
Hex.toHexString(contractAddress), Hex.toHexString(contractAddress),
Hex.toHexString(bodyCode)); 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); BigInteger balance = repository.getBalance(senderAddress);
// check if can be charged for the contract data save // check if can be charged for the contract data save
if (storageCost.compareTo(balance) > 1){ if (storageCost.compareTo(balance) > 1) {
bodyCode = EMPTY_BYTE_ARRAY; bodyCode = EMPTY_BYTE_ARRAY;
} else { } else {
repository.addBalance(coinbase, storageCost); repository.addBalance(coinbase, storageCost);
@ -301,7 +302,7 @@ public class TransactionExecutor {
// delete the marked to die accounts // delete the marked to die accounts
if (result.getDeleteAccounts() == null) return; if (result.getDeleteAccounts() == null) return;
for (DataWord address : result.getDeleteAccounts()){ for (DataWord address : result.getDeleteAccounts()) {
repository.delete(address.getNoLeadZeroesData()); repository.delete(address.getNoLeadZeroesData());
} }
} }

View File

@ -17,8 +17,6 @@ import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
* comprising the transaction, together with the post-transaction state, * comprising the transaction, together with the post-transaction state,
* and the cumulative gas used in the block containing the transaction receipt * and the cumulative gas used in the block containing the transaction receipt
* as of immediately after the transaction has happened, * as of immediately after the transaction has happened,
*
*
*/ */
public class TransactionReceipt { public class TransactionReceipt {
@ -26,7 +24,7 @@ public class TransactionReceipt {
private byte[] postTxState = EMPTY_BYTE_ARRAY; private byte[] postTxState = EMPTY_BYTE_ARRAY;
private byte[] cumulativeGas = 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>(); private List<LogInfo> logInfoList = new ArrayList<LogInfo>();
/* Tx Receipt in encoded form */ /* Tx Receipt in encoded form */
@ -40,10 +38,10 @@ public class TransactionReceipt {
RLPList params = RLP.decode2(rlp); RLPList params = RLP.decode2(rlp);
RLPList receipt = (RLPList) params.get(0); 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 cumulativeGasRLP = (RLPItem) receipt.get(1);
RLPItem bloomRLP = (RLPItem) receipt.get(2); RLPItem bloomRLP = (RLPItem) receipt.get(2);
RLPList logs = (RLPList) receipt.get(3); RLPList logs = (RLPList) receipt.get(3);
postTxState = postTxStateRLP.getRLPData(); postTxState = postTxStateRLP.getRLPData();
cumulativeGas = cumulativeGasRLP.getRLPData(); cumulativeGas = cumulativeGasRLP.getRLPData();
@ -92,11 +90,11 @@ public class TransactionReceipt {
/* [postTxState, cumulativeGas, bloomFilter, logInfoList] */ /* [postTxState, cumulativeGas, bloomFilter, logInfoList] */
public byte[] getEncoded() { 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[] cumulativeGasRLP = RLP.encodeElement(this.cumulativeGas);
byte[] bloomRLP = RLP.encodeElement(this.bloomFilter.data); byte[] bloomRLP = RLP.encodeElement(this.bloomFilter.data);
byte[] logInfoListRLP = null; byte[] logInfoListRLP = null;
if (logInfoList != null) { if (logInfoList != null) {
@ -104,11 +102,11 @@ public class TransactionReceipt {
int i = 0; int i = 0;
for (LogInfo logInfo : logInfoList) { for (LogInfo logInfo : logInfoList) {
logInfoListE[i] = logInfo.getEncoded() ; logInfoListE[i] = logInfo.getEncoded();
++i; ++i;
} }
logInfoListRLP = RLP.encodeList(logInfoListE); logInfoListRLP = RLP.encodeList(logInfoListE);
} else{ } else {
logInfoListRLP = RLP.encodeList(); logInfoListRLP = RLP.encodeList();
} }
@ -122,7 +120,7 @@ public class TransactionReceipt {
} }
public void setCumulativeGas(long cumulativeGas) { public void setCumulativeGas(long cumulativeGas) {
this.cumulativeGas = BigIntegers.asUnsignedByteArray( BigInteger.valueOf( cumulativeGas ) ); this.cumulativeGas = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(cumulativeGas));
} }
public void setCumulativeGas(byte[] cumulativeGas) { public void setCumulativeGas(byte[] cumulativeGas) {
@ -135,16 +133,16 @@ public class TransactionReceipt {
this.rlpEncoded = null; this.rlpEncoded = null;
this.logInfoList = logInfoList; this.logInfoList = logInfoList;
for (LogInfo loginfo : logInfoList){ for (LogInfo loginfo : logInfoList) {
bloomFilter.or(loginfo.getBloom()); bloomFilter.or(loginfo.getBloom());
} }
} }
public void setTransaction(Transaction transaction){ public void setTransaction(Transaction transaction) {
this.transaction = transaction; this.transaction = transaction;
} }
public Transaction getTransaction(){ public Transaction getTransaction() {
return transaction; return transaction;
} }

View File

@ -110,7 +110,7 @@ public class Wallet {
* @param transaction * @param transaction
* @return * @return
*/ */
public WalletTransaction addByWalletTransaction(Transaction transaction){ public WalletTransaction addByWalletTransaction(Transaction transaction) {
String hash = Hex.toHexString(transaction.getHash()); String hash = Hex.toHexString(transaction.getHash());
WalletTransaction walletTransaction = new WalletTransaction(transaction); WalletTransaction walletTransaction = new WalletTransaction(transaction);
this.walletTransactions.put(hash, walletTransaction); this.walletTransactions.put(hash, walletTransaction);
@ -127,9 +127,9 @@ public class Wallet {
*/ */
public WalletTransaction addTransaction(Transaction transaction) { public WalletTransaction addTransaction(Transaction transaction) {
String hash = Hex.toHexString(transaction.getHash()); 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) if (walletTransaction != null)
walletTransaction.incApproved(); walletTransaction.incApproved();
else { else {
@ -158,7 +158,7 @@ public class Wallet {
public void removeTransaction(Transaction transaction) { public void removeTransaction(Transaction transaction) {
String hash = Hex.toHexString(transaction.getHash()); 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); walletTransactions.remove(hash);
} }
@ -167,7 +167,7 @@ public class Wallet {
transactionMap.put(new ByteArrayWrapper(transaction.getHash()), transaction); transactionMap.put(new ByteArrayWrapper(transaction.getHash()), transaction);
byte[] senderAddress = transaction.getSender(); byte[] senderAddress = transaction.getSender();
Account sender = rows.get(Hex.toHexString(senderAddress)); Account sender = rows.get(Hex.toHexString(senderAddress));
if (sender != null) { if (sender != null) {
sender.addPendingTransaction(transaction); sender.addPendingTransaction(transaction);
@ -178,8 +178,8 @@ public class Wallet {
} }
byte[] receiveAddress = transaction.getReceiveAddress(); byte[] receiveAddress = transaction.getReceiveAddress();
if(receiveAddress != null) { if (receiveAddress != null) {
Account receiver = rows.get(Hex.toHexString(receiveAddress)); Account receiver = rows.get(Hex.toHexString(receiveAddress));
if (receiver != null) { if (receiver != null) {
receiver.addPendingTransaction(transaction); receiver.addPendingTransaction(transaction);
@ -195,7 +195,7 @@ public class Wallet {
public void processBlock(Block block) { public void processBlock(Block block) {
for (Account account : getAccountCollection()){ for (Account account : getAccountCollection()) {
account.clearAllPendingTransactions(); account.clearAllPendingTransactions();
} }
@ -237,11 +237,11 @@ public class Wallet {
NodeList rowNodes = walletNode.getChildNodes(); 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 rowNode = rowNodes.item(i);
Node addrNode = rowNode.getChildNodes().item(0); Node addrNode = rowNode.getChildNodes().item(0);
Node privNode = rowNode.getChildNodes().item(1); Node privNode = rowNode.getChildNodes().item(1);
Node valueNode = rowNode.getChildNodes().item(2); Node valueNode = rowNode.getChildNodes().item(2);
// TODO: complete load func // TODO: complete load func
@ -287,11 +287,11 @@ public class Wallet {
doc.appendChild(walletElement); doc.appendChild(walletElement);
Attr high = doc.createAttribute("high"); Attr high = doc.createAttribute("high");
high.setValue(Long.toString( this.high )); high.setValue(Long.toString(this.high));
walletElement.setAttributeNode(high); walletElement.setAttributeNode(high);
int i = 0; int i = 0;
for (Account account : getAccountCollection()) { for (Account account : getAccountCollection()) {
Element raw = doc.createElement("raw"); Element raw = doc.createElement("raw");
Attr id = doc.createAttribute("id"); Attr id = doc.createAttribute("id");
@ -308,7 +308,7 @@ public class Wallet {
Element privKey = doc.createElement("privkey"); Element privKey = doc.createElement("privkey");
privKey.setTextContent(Hex.toHexString(account.getEcKey().getPrivKeyBytes())); privKey.setTextContent(Hex.toHexString(account.getEcKey().getPrivKeyBytes()));
Element value = doc.createElement("value"); Element value = doc.createElement("value");
value.setTextContent(account.getBalance().toString()); value.setTextContent(account.getBalance().toString());
raw.appendChild(addressE); raw.appendChild(addressE);
@ -334,7 +334,7 @@ public class Wallet {
listener.valueChanged(); listener.valueChanged();
} }
public interface WalletListener{ public interface WalletListener {
public void valueChanged(); public void valueChanged();
} }

View File

@ -14,6 +14,7 @@ package org.ethereum.crypto;
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import static org.ethereum.util.ByteUtil.bigIntegerToBytes; import static org.ethereum.util.ByteUtil.bigIntegerToBytes;
import java.io.Serializable; import java.io.Serializable;
@ -66,12 +67,15 @@ import org.spongycastle.util.encoders.Hex;
* can usually ignore the compressed/uncompressed distinction.</p> * can usually ignore the compressed/uncompressed distinction.</p>
* *
* This code is borrowed from the bitcoinj project and altered to fit Ethereum.<br> * 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 { public class ECKey implements Serializable {
private static final Logger logger = LoggerFactory.getLogger(ECKey.class); 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; public static final ECDomainParameters CURVE;
/** /**
@ -125,7 +129,7 @@ public class ECKey implements Serializable {
public ECKey(@Nullable BigInteger priv, ECPoint pub) { public ECKey(@Nullable BigInteger priv, ECPoint pub) {
this.priv = priv; this.priv = priv;
if(pub == null) if (pub == null)
throw new IllegalArgumentException("Public key may not be null"); throw new IllegalArgumentException("Public key may not be null");
this.pub = pub; this.pub = pub;
} }
@ -234,7 +238,9 @@ public class ECKey implements Serializable {
return point.getEncoded(compressed); 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() { public byte[] getAddress() {
if (pubKeyHash == null) { if (pubKeyHash == null) {
byte[] pubBytes = this.pub.getEncoded(false); byte[] pubBytes = this.pub.getEncoded(false);
@ -251,7 +257,9 @@ public class ECKey implements Serializable {
return pub.getEncoded(); 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() { public ECPoint getPubKeyPoint() {
return pub; return pub;
} }
@ -300,7 +308,9 @@ public class ECKey implements Serializable {
* components can be useful for doing further EC maths on them. * components can be useful for doing further EC maths on them.
*/ */
public static class ECDSASignature { public static class ECDSASignature {
/** The two components of the signature. */ /**
* The two components of the signature.
*/
public final BigInteger r, s; public final BigInteger r, s;
public byte v; 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 * <p>When using native ECDSA verification, data must be 32 bytes, and no element may be
* larger than 520 bytes.</p> * 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 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) { public static boolean verify(byte[] data, ECDSASignature signature, byte[] pub) {
ECDSASigner signer = new ECDSASigner(); 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. * 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 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) { public static boolean verify(byte[] data, byte[] signature, byte[] pub) {
return verify(data, signature, 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. * 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 signature signature.
*/ */
public boolean verify(byte[] data, byte[] signature) { public boolean verify(byte[] data, byte[] signature) {
@ -601,11 +611,13 @@ public class ECKey implements Serializable {
return ECKey.fromPublicOnly(q.getEncoded(compressed)); 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) { private static ECPoint decompressKey(BigInteger xBN, boolean yBit) {
X9IntegerConverter x9 = new X9IntegerConverter(); X9IntegerConverter x9 = new X9IntegerConverter();
byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve())); 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); return CURVE.getCurve().decodePoint(compEnc);
} }
@ -643,6 +655,6 @@ public class ECKey implements Serializable {
} }
private static void check(boolean test, String message) { private static void check(boolean test, String message) {
if(!test) throw new IllegalArgumentException(message); if (!test) throw new IllegalArgumentException(message);
} }
} }

View File

@ -41,7 +41,7 @@ public class HashUtil {
public static byte[] sha3(byte[] input) { public static byte[] sha3(byte[] input) {
ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input); ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input);
byte[] result = sha3Cache.get(inputByteArray); byte[] result = sha3Cache.get(inputByteArray);
if(result != null) if (result != null)
return result; return result;
result = SHA3Helper.sha3(input); result = SHA3Helper.sha3(input);
sha3Cache.put(inputByteArray, result); sha3Cache.put(inputByteArray, result);
@ -71,7 +71,7 @@ public class HashUtil {
/** /**
* The way to calculate new address inside ethereum * The way to calculate new address inside ethereum
* *
* @param addr - creating addres * @param addr - creating addres
* @param nonce - nonce of creating address * @param nonce - nonce of creating address
* @return new address * @return new address
*/ */

View File

@ -20,7 +20,7 @@ import java.util.List;
* Created on: 12/11/2014 17:16 * Created on: 12/11/2014 17:16
*/ */
@Repository @Repository
@Transactional(propagation= Propagation.SUPPORTS) @Transactional(propagation = Propagation.SUPPORTS)
public class BlockStore { public class BlockStore {
@Autowired @Autowired
@ -35,10 +35,10 @@ public class BlockStore {
List result = sessionFactory.getCurrentSession(). List result = sessionFactory.getCurrentSession().
createQuery("from BlockVO where number = :number"). createQuery("from BlockVO where number = :number").
setParameter("number", blockNumber).list(); setParameter("number", blockNumber).list();
if (result.size() == 0) return null; if (result.size() == 0) return null;
BlockVO vo = (BlockVO)result.get(0); BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp); return new Block(vo.rlp);
} }
@ -51,7 +51,7 @@ public class BlockStore {
setParameter("hash", hash).list(); setParameter("hash", hash).list();
if (result.size() == 0) return null; if (result.size() == 0) return null;
BlockVO vo = (BlockVO)result.get(0); BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp); return new Block(vo.rlp);
} }
@ -72,7 +72,7 @@ public class BlockStore {
setParameter("limit", block.getNumber() - qty). setParameter("limit", block.getNumber() - qty).
setMaxResults(qty).list(); setMaxResults(qty).list();
for (byte[] h : result){ for (byte[] h : result) {
hashes.add(h); hashes.add(h);
} }
@ -80,7 +80,7 @@ public class BlockStore {
} }
@Transactional @Transactional
public void deleteBlocksSince(long number){ public void deleteBlocksSince(long number) {
sessionFactory.getCurrentSession(). sessionFactory.getCurrentSession().
createQuery("delete from BlockVO where number > :number"). createQuery("delete from BlockVO where number > :number").
@ -92,10 +92,10 @@ public class BlockStore {
@Transactional @Transactional
public void saveBlock(Block block, List<TransactionReceipt> receipts) { 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()); block.getEncoded(), block.getCumulativeDifficulty());
for (TransactionReceipt receipt : receipts){ for (TransactionReceipt receipt : receipts) {
byte[] hash = receipt.getTransaction().getHash(); byte[] hash = receipt.getTransaction().getHash();
byte[] rlp = receipt.getEncoded(); byte[] rlp = receipt.getEncoded();
@ -108,9 +108,9 @@ public class BlockStore {
} }
@Transactional(readOnly = true) @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"). createQuery("select sum(cummulativeDifficulty) from BlockVO where number > :number").
setParameter("number", number). setParameter("number", number).
uniqueResult(); uniqueResult();
@ -120,9 +120,9 @@ public class BlockStore {
@Transactional(readOnly = true) @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(); createQuery("select sum(cummulativeDifficulty) from BlockVO").uniqueResult();
return result; return result;
@ -130,15 +130,15 @@ public class BlockStore {
@Transactional(readOnly = true) @Transactional(readOnly = true)
public Block getBestBlock(){ public Block getBestBlock() {
Long bestNumber = (Long) Long bestNumber = (Long)
sessionFactory.getCurrentSession().createQuery("select max(number) from BlockVO").uniqueResult(); sessionFactory.getCurrentSession().createQuery("select max(number) from BlockVO").uniqueResult();
List result = sessionFactory.getCurrentSession(). 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; if (result.isEmpty()) return null;
BlockVO vo = (BlockVO)result.get(0); BlockVO vo = (BlockVO) result.get(0);
return new Block(vo.rlp); return new Block(vo.rlp);
} }
@ -151,7 +151,7 @@ public class BlockStore {
createQuery("from BlockVO").list(); createQuery("from BlockVO").list();
ArrayList<Block> blocks = new ArrayList<>(); ArrayList<Block> blocks = new ArrayList<>();
for (BlockVO blockVO : (List<BlockVO>)result){ for (BlockVO blockVO : (List<BlockVO>) result) {
blocks.add(new Block(blockVO.getRlp())); blocks.add(new Block(blockVO.getRlp()));
} }
@ -161,7 +161,7 @@ public class BlockStore {
@Transactional @Transactional
public void reset() { public void reset() {
sessionFactory.getCurrentSession(). sessionFactory.getCurrentSession().
createQuery("delete from BlockVO").executeUpdate(); createQuery("delete from BlockVO").executeUpdate();
} }
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) { public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
@ -171,7 +171,7 @@ public class BlockStore {
setParameter("hash", hash).list(); setParameter("hash", hash).list();
if (result.size() == 0) return null; if (result.size() == 0) return null;
TransactionReceiptVO vo = (TransactionReceiptVO)result.get(0); TransactionReceiptVO vo = (TransactionReceiptVO) result.get(0);
return new TransactionReceipt(vo.rlp); return new TransactionReceipt(vo.rlp);

View File

@ -19,7 +19,7 @@ public class BlockVO {
@Id @Id
byte[] hash; byte[] hash;
Long number; Long number;
@Lob @Lob
byte[] rlp; byte[] rlp;
@ -31,8 +31,8 @@ public class BlockVO {
public BlockVO(Long number, byte[] hash, byte[] rlp, BigInteger cummulativeDifficulty) { public BlockVO(Long number, byte[] hash, byte[] rlp, BigInteger cummulativeDifficulty) {
this.number = number; this.number = number;
this.hash = hash; this.hash = hash;
this.rlp = rlp; this.rlp = rlp;
this.cummulativeDifficulty = cummulativeDifficulty; this.cummulativeDifficulty = cummulativeDifficulty;
} }

View File

@ -20,12 +20,12 @@ public class ContractDetails {
private byte[] rlpEncoded; private byte[] rlpEncoded;
private List<DataWord> storageKeys = new ArrayList<>(); private List<DataWord> storageKeys = new ArrayList<>();
private List<DataWord> storageValues = new ArrayList<>(); private List<DataWord> storageValues = new ArrayList<>();
private byte[] code = ByteUtil.EMPTY_BYTE_ARRAY; private byte[] code = ByteUtil.EMPTY_BYTE_ARRAY;
private boolean dirty = false; private boolean dirty = false;
private boolean deleted = false; private boolean deleted = false;
private Trie storageTrie = new TrieImpl(null); private Trie storageTrie = new TrieImpl(null);
@ -75,8 +75,7 @@ public class ContractDetails {
if (foundIndex != -1) { if (foundIndex != -1) {
DataWord value = storageValues.get(foundIndex); DataWord value = storageValues.get(foundIndex);
return value.clone(); return value.clone();
} } else
else
return null; return null;
} }
@ -94,7 +93,7 @@ public class ContractDetails {
storageTrie = new TrieImpl(null); storageTrie = new TrieImpl(null);
// calc the trie for root hash // 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 storageTrie.update(storageKeys.get(i).getData(), RLP
.encodeElement(storageValues.get(i).getNoLeadZeroesData())); .encodeElement(storageValues.get(i).getNoLeadZeroesData()));
} }
@ -197,7 +196,7 @@ public class ContractDetails {
keys.addAll(storageKeys); keys.addAll(storageKeys);
List<DataWord> values = new ArrayList<>(); List<DataWord> values = new ArrayList<>();
for (DataWord key : keys){ for (DataWord key : keys) {
DataWord value = storage.get(key); DataWord value = storage.get(key);
values.add(value); values.add(value);
@ -208,18 +207,17 @@ public class ContractDetails {
} }
public ContractDetails clone() {
public ContractDetails clone(){
ContractDetails contractDetails = new ContractDetails(); ContractDetails contractDetails = new ContractDetails();
contractDetails.setCode(this.getCode()); contractDetails.setCode(this.getCode());
contractDetails.setStorage(new ArrayList<DataWord>(this.storageKeys) , contractDetails.setStorage(new ArrayList<DataWord>(this.storageKeys),
new ArrayList<DataWord>(this.storageValues)); new ArrayList<DataWord>(this.storageValues));
return contractDetails; return contractDetails;
} }
public String toString(){ public String toString() {
String ret = " Code: " + Hex.toHexString(code) + "\n"; String ret = " Code: " + Hex.toHexString(code) + "\n";
ret += " Storage: " + getStorage().toString(); ret += " Storage: " + getStorage().toString();

View File

@ -18,12 +18,12 @@ import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex; 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. * LevelDB key/value pair DB implementation will be used.
* Choice must be made between: * Choice must be made between:
* Pure Java: https://github.com/dain/leveldb * Pure Java: https://github.com/dain/leveldb
* JNI binding: https://github.com/fusesource/leveldbjni * JNI binding: https://github.com/fusesource/leveldbjni
*/ */
public class DatabaseImpl implements Database { public class DatabaseImpl implements Database {
@ -40,10 +40,10 @@ public class DatabaseImpl implements Database {
try { try {
logger.debug("Opening database"); logger.debug("Opening database");
File dbLocation = new File(System.getProperty("user.dir") + "/" + File dbLocation = new File(System.getProperty("user.dir") + "/" +
SystemProperties.CONFIG.databaseDir() + "/"); SystemProperties.CONFIG.databaseDir() + "/");
File fileLocation = new File(dbLocation, name); File fileLocation = new File(dbLocation, name);
if(SystemProperties.CONFIG.databaseReset()) { if (SystemProperties.CONFIG.databaseReset()) {
destroyDB(fileLocation); destroyDB(fileLocation);
} }
@ -53,13 +53,13 @@ public class DatabaseImpl implements Database {
// String stats = DATABASE.getProperty("leveldb.stats"); // String stats = DATABASE.getProperty("leveldb.stats");
// logger.debug(stats); // logger.debug(stats);
if (logger.isTraceEnabled()){ if (logger.isTraceEnabled()) {
logger.trace("Dump for: {}", fileLocation.toString()); logger.trace("Dump for: {}", fileLocation.toString());
DBIterator iter = db.iterator(); DBIterator iter = db.iterator();
while(iter.hasNext()){ while (iter.hasNext()) {
byte[] key = iter.peekNext().getKey(); byte[] key = iter.peekNext().getKey();
byte[] value = iter.peekNext().getValue(); byte[] value = iter.peekNext().getValue();
logger.trace("key={}, value={}", Hex.toHexString(key), Hex.toHexString(value)); logger.trace("key={}, value={}", Hex.toHexString(key), Hex.toHexString(value));
@ -90,7 +90,7 @@ public class DatabaseImpl implements Database {
@Override @Override
public void put(byte[] key, byte[] value) { public void put(byte[] key, byte[] value) {
if(logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("put: key: [{}], value: [{}]", logger.debug("put: key: [{}], value: [{}]",
Hex.toHexString(key), Hex.toHexString(key),
Hex.toHexString(value)); Hex.toHexString(value));
@ -99,7 +99,7 @@ public class DatabaseImpl implements Database {
@Override @Override
public void delete(byte[] key) { public void delete(byte[] key) {
if(logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug("delete: key: [{}]"); logger.debug("delete: key: [{}]");
db.delete(key); db.delete(key);

View File

@ -41,7 +41,7 @@ public class RepositoryDummy implements Repository {
private static final Logger logger = LoggerFactory.getLogger("repository"); private static final Logger logger = LoggerFactory.getLogger("repository");
private Map<ByteArrayWrapper, AccountState> worldState = new HashMap<>(); private Map<ByteArrayWrapper, AccountState> worldState = new HashMap<>();
private Map<ByteArrayWrapper, ContractDetails> detailsDB = new HashMap<>() ; private Map<ByteArrayWrapper, ContractDetails> detailsDB = new HashMap<>();
@Override @Override
@ -53,12 +53,12 @@ public class RepositoryDummy implements Repository {
@Override @Override
public void close() { public void close() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public boolean isClosed() { public boolean isClosed() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -71,21 +71,21 @@ public class RepositoryDummy implements Repository {
AccountState accountState = stateCache.get(hash); AccountState accountState = stateCache.get(hash);
ContractDetails contractDetails = detailsCache.get(hash); ContractDetails contractDetails = detailsCache.get(hash);
if (accountState.isDeleted()){ if (accountState.isDeleted()) {
worldState.remove( hash ) ; worldState.remove(hash);
detailsDB.remove( hash ); detailsDB.remove(hash);
logger.debug("delete: [{}]", logger.debug("delete: [{}]",
Hex.toHexString(hash.getData())); Hex.toHexString(hash.getData()));
} else{ } else {
if (accountState.isDirty() || contractDetails.isDirty()){ if (accountState.isDirty() || contractDetails.isDirty()) {
detailsDB.put( hash, contractDetails); detailsDB.put(hash, contractDetails);
accountState.setStateRoot(contractDetails.getStorageHash()); accountState.setStateRoot(contractDetails.getStorageHash());
accountState.setCodeHash(sha3(contractDetails.getCode())); accountState.setCodeHash(sha3(contractDetails.getCode()));
worldState.put( hash, accountState); worldState.put(hash, accountState);
if (logger.isDebugEnabled()){ if (logger.isDebugEnabled()) {
logger.debug("update: [{}],nonce: [{}] balance: [{}] \n [{}]", logger.debug("update: [{}],nonce: [{}] balance: [{}] \n [{}]",
Hex.toHexString(hash.getData()), Hex.toHexString(hash.getData()),
accountState.getNonce(), accountState.getNonce(),
@ -106,23 +106,23 @@ public class RepositoryDummy implements Repository {
@Override @Override
public void flush() { public void flush() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void rollback() { public void rollback() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void commit() { public void commit() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void syncToRoot(byte[] root) { public void syncToRoot(byte[] root) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
@ -140,7 +140,7 @@ public class RepositoryDummy implements Repository {
return null; return null;
} }
public Set<ByteArrayWrapper> getFullAddressSet(){ public Set<ByteArrayWrapper> getFullAddressSet() {
return worldState.keySet(); return worldState.keySet();
} }
@ -170,7 +170,7 @@ public class RepositoryDummy implements Repository {
@Override @Override
public DataWord getStorageValue(byte[] addr, DataWord key) { public DataWord getStorageValue(byte[] addr, DataWord key) {
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (details == null) if (details == null)
return null; return null;
@ -180,11 +180,11 @@ public class RepositoryDummy implements Repository {
@Override @Override
public void addStorageRow(byte[] addr, DataWord key, DataWord value) { 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); createAccount(addr);
details = getContractDetails(addr); details = getContractDetails(addr);
} }
details.put(key, value); details.put(key, value);
@ -193,7 +193,7 @@ public class RepositoryDummy implements Repository {
@Override @Override
public byte[] getCode(byte[] addr) { public byte[] getCode(byte[] addr) {
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (details == null) if (details == null)
return null; return null;
@ -204,15 +204,15 @@ public class RepositoryDummy implements Repository {
@Override @Override
public void saveCode(byte[] addr, byte[] code) { public void saveCode(byte[] addr, byte[] code) {
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (details == null){ if (details == null) {
createAccount(addr); createAccount(addr);
details = getContractDetails(addr); details = getContractDetails(addr);
} }
details.setCode(code); details.setCode(code);
detailsDB.put(wrap( addr ), details); detailsDB.put(wrap(addr), details);
} }
@Override @Override
@ -295,8 +295,8 @@ public class RepositoryDummy implements Repository {
@Override @Override
public void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts, HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) { public void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts, HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) {
AccountState account = getAccountState(addr); AccountState account = getAccountState(addr);
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (account == null) if (account == null)
account = new AccountState(); account = new AccountState();

View File

@ -43,37 +43,37 @@ public class RepositoryImpl implements Repository {
private static final Logger logger = LoggerFactory.getLogger("repository"); private static final Logger logger = LoggerFactory.getLogger("repository");
private Trie worldState; private Trie worldState;
private DatabaseImpl detailsDB = null; private DatabaseImpl detailsDB = null;
private DatabaseImpl stateDB = null; private DatabaseImpl stateDB = null;
public RepositoryImpl() { public RepositoryImpl() {
this(DETAILS_DB, STATE_DB); this(DETAILS_DB, STATE_DB);
} }
public RepositoryImpl(String detailsDbName, String stateDbName) { public RepositoryImpl(String detailsDbName, String stateDbName) {
detailsDB = new DatabaseImpl(detailsDbName); detailsDB = new DatabaseImpl(detailsDbName);
stateDB = new DatabaseImpl(stateDbName); stateDB = new DatabaseImpl(stateDbName);
worldState = new TrieImpl(stateDB.getDb()); worldState = new TrieImpl(stateDB.getDb());
} }
@Override @Override
public void reset() { public void reset() {
close(); close();
detailsDB = new DatabaseImpl(DETAILS_DB); detailsDB = new DatabaseImpl(DETAILS_DB);
stateDB = new DatabaseImpl(STATE_DB); stateDB = new DatabaseImpl(STATE_DB);
worldState = new TrieImpl(stateDB.getDb()); worldState = new TrieImpl(stateDB.getDb());
} }
@Override @Override
public void close() { public void close() {
if (this.detailsDB != null){ if (this.detailsDB != null) {
detailsDB.close(); detailsDB.close();
detailsDB = null; detailsDB = null;
} }
if (this.stateDB != null){ if (this.stateDB != null) {
stateDB.close(); stateDB.close();
stateDB = null; stateDB = null;
} }
@ -93,21 +93,21 @@ public class RepositoryImpl implements Repository {
AccountState accountState = stateCache.get(hash); AccountState accountState = stateCache.get(hash);
ContractDetails contractDetails = detailsCache.get(hash); ContractDetails contractDetails = detailsCache.get(hash);
if (accountState.isDeleted()){ if (accountState.isDeleted()) {
worldState.delete(hash.getData()); worldState.delete(hash.getData());
detailsDB.delete(hash.getData()); detailsDB.delete(hash.getData());
logger.debug("delete: [{}]", logger.debug("delete: [{}]",
Hex.toHexString(hash.getData())); Hex.toHexString(hash.getData()));
} else{ } else {
if (accountState.isDirty() || contractDetails.isDirty()){ if (accountState.isDirty() || contractDetails.isDirty()) {
detailsDB.put(hash.getData(), contractDetails.getEncoded()); detailsDB.put(hash.getData(), contractDetails.getEncoded());
accountState.setStateRoot(contractDetails.getStorageHash()); accountState.setStateRoot(contractDetails.getStorageHash());
accountState.setCodeHash(sha3(contractDetails.getCode())); accountState.setCodeHash(sha3(contractDetails.getCode()));
worldState.update(hash.getData(), accountState.getEncoded()); worldState.update(hash.getData(), accountState.getEncoded());
if (logger.isDebugEnabled()){ if (logger.isDebugEnabled()) {
logger.debug("update: [{}],nonce: [{}] balance: [{}] \n [{}]", logger.debug("update: [{}],nonce: [{}] balance: [{}] \n [{}]",
Hex.toHexString(hash.getData()), Hex.toHexString(hash.getData()),
accountState.getNonce(), accountState.getNonce(),
@ -126,7 +126,7 @@ public class RepositoryImpl implements Repository {
} }
@Override @Override
public void flush(){ public void flush() {
logger.info("flush to disk"); logger.info("flush to disk");
worldState.sync(); worldState.sync();
} }
@ -134,12 +134,12 @@ public class RepositoryImpl implements Repository {
@Override @Override
public void rollback() { public void rollback() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
public void commit() { public void commit() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
@ -164,7 +164,9 @@ public class RepositoryImpl implements Repository {
if (block.getNumber() == 0 && txNumber == 0) if (block.getNumber() == 0 && txNumber == 0)
if (CONFIG.dumpCleanOnRestart()) { if (CONFIG.dumpCleanOnRestart()) {
try { try {
FileUtils.deleteDirectory(CONFIG.dumpDir());} catch (IOException e) {} FileUtils.deleteDirectory(CONFIG.dumpDir());
} catch (IOException e) {
}
} }
String dir = CONFIG.dumpDir() + "/"; 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())) if (!(CONFIG.dumpFull() || CONFIG.dumpBlock() == block.getNumber()))
return; return;
@ -239,9 +241,11 @@ public class RepositoryImpl implements Repository {
logger.error(e.getMessage(), e); logger.error(e.getMessage(), e);
} finally { } finally {
try { try {
if (bw != null)bw.close(); if (bw != null) bw.close();
if (fw != null)fw.close(); if (fw != null) fw.close();
} catch (IOException e) {e.printStackTrace();} } catch (IOException e) {
e.printStackTrace();
}
} }
} }
@ -279,7 +283,7 @@ public class RepositoryImpl implements Repository {
@Override @Override
public DataWord getStorageValue(byte[] addr, DataWord key) { public DataWord getStorageValue(byte[] addr, DataWord key) {
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (details == null) if (details == null)
return null; return null;
@ -290,11 +294,11 @@ public class RepositoryImpl implements Repository {
@Override @Override
public void addStorageRow(byte[] addr, DataWord key, DataWord value) { 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); createAccount(addr);
details = getContractDetails(addr); details = getContractDetails(addr);
} }
details.put(key, value); details.put(key, value);
@ -304,7 +308,7 @@ public class RepositoryImpl implements Repository {
@Override @Override
public byte[] getCode(byte[] addr) { public byte[] getCode(byte[] addr) {
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (details == null) if (details == null)
return null; return null;
@ -314,11 +318,11 @@ public class RepositoryImpl implements Repository {
@Override @Override
public void saveCode(byte[] addr, byte[] code) { public void saveCode(byte[] addr, byte[] code) {
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (details == null){ if (details == null) {
createAccount(addr); createAccount(addr);
details = getContractDetails(addr); details = getContractDetails(addr);
} }
details.setCode(code); details.setCode(code);
@ -365,8 +369,6 @@ public class RepositoryImpl implements Repository {
} }
@Override @Override
public void delete(byte[] addr) { public void delete(byte[] addr) {
worldState.delete(addr); worldState.delete(addr);
@ -419,8 +421,8 @@ public class RepositoryImpl implements Repository {
HashMap<ByteArrayWrapper, AccountState> cacheAccounts, HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) { HashMap<ByteArrayWrapper, ContractDetails> cacheDetails) {
AccountState account = getAccountState(addr); AccountState account = getAccountState(addr);
ContractDetails details = getContractDetails(addr); ContractDetails details = getContractDetails(addr);
if (account == null) if (account == null)
account = new AccountState(); account = new AccountState();

View File

@ -27,12 +27,12 @@ public class RepositoryTrack implements Repository {
private static final Logger logger = LoggerFactory.getLogger("repository"); private static final Logger logger = LoggerFactory.getLogger("repository");
HashMap<ByteArrayWrapper, AccountState> cacheAccounts = new HashMap<>(); HashMap<ByteArrayWrapper, AccountState> cacheAccounts = new HashMap<>();
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails = new HashMap<>(); HashMap<ByteArrayWrapper, ContractDetails> cacheDetails = new HashMap<>();
Repository repository; Repository repository;
public RepositoryTrack(){ public RepositoryTrack() {
this.repository = new RepositoryDummy(); this.repository = new RepositoryDummy();
} }
@ -43,7 +43,7 @@ public class RepositoryTrack implements Repository {
@Override @Override
public AccountState createAccount(byte[] addr) { public AccountState createAccount(byte[] addr) {
logger.trace("createAccount: [{}]", Hex.toHexString(addr)) ; logger.trace("createAccount: [{}]", Hex.toHexString(addr));
AccountState accountState = new AccountState(); AccountState accountState = new AccountState();
cacheAccounts.put(wrap(addr), accountState); cacheAccounts.put(wrap(addr), accountState);
@ -59,7 +59,7 @@ public class RepositoryTrack implements Repository {
AccountState accountState = cacheAccounts.get(wrap(addr)); AccountState accountState = cacheAccounts.get(wrap(addr));
if (accountState == null){ if (accountState == null) {
repository.loadAccount(addr, cacheAccounts, cacheDetails); repository.loadAccount(addr, cacheAccounts, cacheDetails);
accountState = cacheAccounts.get(wrap(addr)); accountState = cacheAccounts.get(wrap(addr));
} }
@ -83,7 +83,7 @@ public class RepositoryTrack implements Repository {
ContractDetails contractDetails = cacheDetails.get(wrap(addr)); ContractDetails contractDetails = cacheDetails.get(wrap(addr));
if (contractDetails == null){ if (contractDetails == null) {
repository.loadAccount(addr, cacheAccounts, cacheDetails); repository.loadAccount(addr, cacheAccounts, cacheDetails);
contractDetails = cacheDetails.get(wrap(addr)); contractDetails = cacheDetails.get(wrap(addr));
} }
@ -93,12 +93,12 @@ public class RepositoryTrack implements Repository {
@Override @Override
public void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts, 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)); ContractDetails contractDetails = this.cacheDetails.get(wrap(addr));
if (accountState == null){ if (accountState == null) {
repository.loadAccount(addr, cacheAccounts, cacheDetails); repository.loadAccount(addr, cacheAccounts, cacheDetails);
} else { } else {
cacheAccounts.put(wrap(addr), accountState.clone()); cacheAccounts.put(wrap(addr), accountState.clone());
@ -110,7 +110,7 @@ public class RepositoryTrack implements Repository {
@Override @Override
public void delete(byte[] addr) { public void delete(byte[] addr) {
logger.trace("delete account: [{}]", Hex.toHexString(addr)) ; logger.trace("delete account: [{}]", Hex.toHexString(addr));
getAccountState(addr).setDeleted(true); getAccountState(addr).setDeleted(true);
getContractDetails(addr).setDeleted(true); getContractDetails(addr).setDeleted(true);
} }
@ -165,7 +165,7 @@ public class RepositoryTrack implements Repository {
public BigInteger addBalance(byte[] addr, BigInteger value) { public BigInteger addBalance(byte[] addr, BigInteger value) {
AccountState accountState = getAccountState(addr); AccountState accountState = getAccountState(addr);
if (accountState == null){ if (accountState == null) {
accountState = createAccount(addr); accountState = createAccount(addr);
} }
@ -210,7 +210,7 @@ public class RepositoryTrack implements Repository {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public Set<ByteArrayWrapper> getFullAddressSet(){ public Set<ByteArrayWrapper> getFullAddressSet() {
return cacheAccounts.keySet(); return cacheAccounts.keySet();
} }
@ -228,7 +228,7 @@ public class RepositoryTrack implements Repository {
@Override @Override
public void flush(){ public void flush() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -256,14 +256,14 @@ public class RepositoryTrack implements Repository {
} }
@Override @Override
public void updateBatch(HashMap<ByteArrayWrapper, AccountState> accountStates, public void updateBatch(HashMap<ByteArrayWrapper, AccountState> accountStates,
HashMap<ByteArrayWrapper, ContractDetails> contractDetailes){ HashMap<ByteArrayWrapper, ContractDetails> contractDetailes) {
for (ByteArrayWrapper hash : accountStates.keySet()){ for (ByteArrayWrapper hash : accountStates.keySet()) {
cacheAccounts.put(hash, accountStates.get(hash)); cacheAccounts.put(hash, accountStates.get(hash));
} }
for (ByteArrayWrapper hash : contractDetailes.keySet()){ for (ByteArrayWrapper hash : contractDetailes.keySet()) {
cacheDetails.put(hash, contractDetailes.get(hash)); cacheDetails.put(hash, contractDetailes.get(hash));
} }
} }

View File

@ -30,10 +30,10 @@ public class TrackDatabase implements Database {
} }
public void commitTrack() { public void commitTrack() {
for(ByteArrayWrapper key : changes.keySet()) { for (ByteArrayWrapper key : changes.keySet()) {
db.put(key.getData(), changes.get(key)); db.put(key.getData(), changes.get(key));
} }
for(ByteArrayWrapper key : deletes) { for (ByteArrayWrapper key : deletes) {
db.delete(key.getData()); db.delete(key.getData());
} }
changes = null; changes = null;
@ -57,7 +57,7 @@ public class TrackDatabase implements Database {
} }
public byte[] get(byte[] key) { public byte[] get(byte[] key) {
if(trackingChanges) { if (trackingChanges) {
ByteArrayWrapper wKey = new ByteArrayWrapper(key); ByteArrayWrapper wKey = new ByteArrayWrapper(key);
if (deletes.contains(wKey)) return null; if (deletes.contains(wKey)) return null;
if (changes.get(wKey) != null) return changes.get(wKey); if (changes.get(wKey) != null) return changes.get(wKey);
@ -65,7 +65,9 @@ public class TrackDatabase implements Database {
return db.get(key); return db.get(key);
} }
/** Delete object (key) from db **/ /**
* Delete object (key) from db *
*/
public void delete(byte[] key) { public void delete(byte[] key) {
if (trackingChanges) { if (trackingChanges) {
ByteArrayWrapper wKey = new ByteArrayWrapper(key); ByteArrayWrapper wKey = new ByteArrayWrapper(key);
@ -76,7 +78,7 @@ public class TrackDatabase implements Database {
} }
@Override @Override
public void close(){ public void close() {
db.close(); db.close();
} }
} }

View File

@ -26,8 +26,8 @@ public class TransactionReceiptVO {
} }
public TransactionReceiptVO(byte[] hash, byte[] rlp) { public TransactionReceiptVO(byte[] hash, byte[] rlp) {
this.hash = hash; this.hash = hash;
this.rlp = rlp; this.rlp = rlp;
} }
public byte[] getHash() { public byte[] getHash() {

View File

@ -11,30 +11,47 @@ import org.ethereum.db.ByteArrayWrapper;
import org.ethereum.net.BlockQueue; import org.ethereum.net.BlockQueue;
import org.ethereum.core.Genesis; import org.ethereum.core.Genesis;
public interface Blockchain { public interface Blockchain {
public static final byte[] GENESIS_HASH = Genesis.getInstance().getHash(); public static final byte[] GENESIS_HASH = Genesis.getInstance().getHash();
public long getSize(); public long getSize();
public void add(Block block); public void add(Block block);
public void tryToConnect(Block block); public void tryToConnect(Block block);
public void storeBlock(Block block, List<TransactionReceipt> receipts); public void storeBlock(Block block, List<TransactionReceipt> receipts);
public Block getBlockByNumber(long blockNr); public Block getBlockByNumber(long blockNr);
public void setBestBlock(Block block); public void setBestBlock(Block block);
public Block getBestBlock(); public Block getBestBlock();
public BlockQueue getQueue(); public BlockQueue getQueue();
public boolean hasParentOnTheChain(Block block); public boolean hasParentOnTheChain(Block block);
public void reset(); public void reset();
public void close(); public void close();
public void updateTotalDifficulty(Block block); public void updateTotalDifficulty(Block block);
public BigInteger getTotalDifficulty(); public BigInteger getTotalDifficulty();
public void setTotalDifficulty(BigInteger totalDifficulty); public void setTotalDifficulty(BigInteger totalDifficulty);
public byte[] getBestBlockHash(); public byte[] getBestBlockHash();
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty); public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty);
TransactionReceipt getTransactionReceiptByHash(byte[] hash); TransactionReceipt getTransactionReceiptByHash(byte[] hash);
public Block getBlockByHash(byte[] hash); public Block getBlockByHash(byte[] hash);
public List<Chain> getAltChains(); public List<Chain> getAltChains();
public List<Block> getGarbage(); public List<Block> getGarbage();
} }

View File

@ -24,10 +24,11 @@ public interface Ethereum {
/** /**
* Find a peer but not this one * Find a peer but not this one
*
* @param excludePeer - peer to exclude * @param excludePeer - peer to exclude
* @return online peer if available otherwise null * @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 * Find an online peer but not from excluded list
@ -35,7 +36,7 @@ public interface Ethereum {
* @param excludePeerSet - peers to exclude * @param excludePeerSet - peers to exclude
* @return online peer if available otherwise null * @return online peer if available otherwise null
*/ */
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeerSet) ; public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeerSet);
/** /**
* @return online peer if available * @return online peer if available
@ -64,9 +65,11 @@ public interface Ethereum {
public Set<PeerInfo> getPeers(); public Set<PeerInfo> getPeers();
public void startPeerDiscovery(); public void startPeerDiscovery();
public void stopPeerDiscovery(); public void stopPeerDiscovery();
public void connect(InetAddress addr, int port); public void connect(InetAddress addr, int port);
public void connect(String ip, int port); public void connect(String ip, int port);
public Blockchain getBlockchain(); public Blockchain getBlockchain();

View File

@ -61,7 +61,7 @@ public class EthereumFactory {
@Bean @Bean
public DataSourceTransactionManager transactionManager(){ public DataSourceTransactionManager transactionManager() {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(); DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource()); dataSourceTransactionManager.setDataSource(dataSource());
@ -69,18 +69,18 @@ public class EthereumFactory {
} }
@Bean(name = "dataSource") @Bean(name = "dataSource")
public DriverManagerDataSource dataSource(){ public DriverManagerDataSource dataSource() {
logger.info("Connecting to the block store"); logger.info("Connecting to the block store");
System.setProperty("hsqldb.reconfig_logging", "false"); System.setProperty("hsqldb.reconfig_logging", "false");
String url = String url =
String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" + String.format("jdbc:hsqldb:file:./%s/blockchain/blockchain.db;" +
"create=%s;hsqldb.default_table_type=cached", "create=%s;hsqldb.default_table_type=cached",
SystemProperties.CONFIG.databaseDir(), SystemProperties.CONFIG.databaseDir(),
SystemProperties.CONFIG.databaseReset()); SystemProperties.CONFIG.databaseReset());
DriverManagerDataSource ds = new DriverManagerDataSource(); DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.hsqldb.jdbcDriver"); ds.setDriverClassName("org.hsqldb.jdbcDriver");
@ -99,12 +99,12 @@ public class EthereumFactory {
private static EthereumFactory factory; private static EthereumFactory factory;
public static Ethereum createEthereum(){ public static Ethereum createEthereum() {
logger.info("capability eth version: [{}]", EthHandler.VERSION); logger.info("capability eth version: [{}]", EthHandler.VERSION);
logger.info("capability shh version: [{}]", ShhHandler.VERSION); logger.info("capability shh version: [{}]", ShhHandler.VERSION);
if (context == null){ if (context == null) {
context = new AnnotationConfigApplicationContext(EthereumFactory.class); context = new AnnotationConfigApplicationContext(EthereumFactory.class);
factory = context.getBean(EthereumFactory.class); factory = context.getBean(EthereumFactory.class);
} }

View File

@ -60,19 +60,22 @@ public class EthereumImpl implements Ethereum {
} }
@PostConstruct @PostConstruct
public void init(){ public void init() {
worldManager.loadBlockchain(); worldManager.loadBlockchain();
if (CONFIG.listenPort() > 0){ if (CONFIG.listenPort() > 0) {
Executors.newSingleThreadExecutor().submit( Executors.newSingleThreadExecutor().submit(
new Runnable() { public void run() { new Runnable() {
peerServer.start(CONFIG.listenPort()); public void run() {
}} peerServer.start(CONFIG.listenPort());
}
}
); );
} }
} }
/** /**
* Find a peer but not this one * Find a peer but not this one
*
* @param peer - peer to exclude * @param peer - peer to exclude
* @return online peer * @return online peer
*/ */
@ -90,7 +93,7 @@ public class EthereumImpl implements Ethereum {
} }
@Override @Override
public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeers) { public PeerInfo findOnlinePeer(Set<PeerInfo> excludePeers) {
logger.info("Looking for online peers..."); logger.info("Looking for online peers...");
final EthereumListener listener = worldManager.getListener(); final EthereumListener listener = worldManager.getListener();
@ -132,7 +135,7 @@ public class EthereumImpl implements Ethereum {
} }
@Override @Override
public void startPeerDiscovery(){ public void startPeerDiscovery() {
worldManager.startPeerDiscovery(); worldManager.startPeerDiscovery();
} }
@ -179,10 +182,10 @@ public class EthereumImpl implements Ethereum {
} }
@Override @Override
public PeerClient getDefaultPeer(){ public PeerClient getDefaultPeer() {
PeerClient peer = worldManager.getActivePeer(); PeerClient peer = worldManager.getActivePeer();
if (peer == null){ if (peer == null) {
peer = new PeerClient(); peer = new PeerClient();
worldManager.setActivePeer(peer); worldManager.setActivePeer(peer);
@ -200,12 +203,12 @@ public class EthereumImpl implements Ethereum {
BigInteger gasPrice, BigInteger gasPrice,
BigInteger gas, BigInteger gas,
byte[] recieveAddress, byte[] recieveAddress,
BigInteger value, byte[] data ){ BigInteger value, byte[] data) {
byte[] nonceBytes = ByteUtil.bigIntegerToBytes(nonce); byte[] nonceBytes = ByteUtil.bigIntegerToBytes(nonce);
byte[] gasPriceBytes = ByteUtil.bigIntegerToBytes(gasPrice); byte[] gasPriceBytes = ByteUtil.bigIntegerToBytes(gasPrice);
byte[] gasBytes = ByteUtil.bigIntegerToBytes(gas); byte[] gasBytes = ByteUtil.bigIntegerToBytes(gas);
byte[] valueBytes = ByteUtil.bigIntegerToBytes(value); byte[] valueBytes = ByteUtil.bigIntegerToBytes(value);
Transaction tx = new Transaction(nonceBytes, gasPriceBytes, gasBytes, Transaction tx = new Transaction(nonceBytes, gasPriceBytes, gasBytes,
recieveAddress, valueBytes, data); recieveAddress, valueBytes, data);
@ -215,7 +218,7 @@ public class EthereumImpl implements Ethereum {
@Override @Override
public Future<Transaction> submitTransaction(Transaction transaction){ public Future<Transaction> submitTransaction(Transaction transaction) {
TransactionTask transactionTask = new TransactionTask(transaction, worldManager); TransactionTask transactionTask = new TransactionTask(transaction, worldManager);
Future<Transaction> future = TransactionExecutor.instance.submitTransaction(transactionTask); Future<Transaction> future = TransactionExecutor.instance.submitTransaction(transactionTask);
@ -225,13 +228,13 @@ public class EthereumImpl implements Ethereum {
@Override @Override
public Wallet getWallet(){ public Wallet getWallet() {
return worldManager.getWallet(); return worldManager.getWallet();
} }
@Override @Override
public Repository getRepository(){ public Repository getRepository() {
return worldManager.getRepository(); return worldManager.getRepository();
} }

View File

@ -143,7 +143,7 @@ public interface Repository {
* @param gasUsed the amount of gas used in the block until that point * @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 txNumber is the number of the transaction for which the dump has to be made
* @param txHash is the hash of the given transaction. * @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); 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 * Return to one of the previous snapshots
* by moving the root. * by moving the root.
*
* @param root - new root * @param root - new root
*/ */
public void syncToRoot(byte[] root); public void syncToRoot(byte[] root);
/** /**
* Check to see if the current repository has an open connection to the database * Check to see if the current repository has an open connection to the database
*
* @return <tt>true</tt> if connection to database is open * @return <tt>true</tt> if connection to database is open
*/ */
public boolean isClosed(); public boolean isClosed();
@ -198,7 +200,7 @@ public interface Repository {
public byte[] getRoot(); public byte[] getRoot();
void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts, void loadAccount(byte[] addr, HashMap<ByteArrayWrapper, AccountState> cacheAccounts,
HashMap<ByteArrayWrapper, ContractDetails> cacheDetails); HashMap<ByteArrayWrapper, ContractDetails> cacheDetails);
} }

View File

@ -15,36 +15,34 @@ import com.fasterxml.jackson.databind.ObjectMapper;
* customize ethereum state dumps. * customize ethereum state dumps.
* *
* @author Alon Muroch * @author Alon Muroch
*
*/ */
public class EtherObjectMapper extends ObjectMapper { public class EtherObjectMapper extends ObjectMapper {
@Override @Override
public String writeValueAsString(Object value) public String writeValueAsString(Object value)
throws JsonProcessingException { throws JsonProcessingException {
// alas, we have to pull the recycler directly here... // alas, we have to pull the recycler directly here...
SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler()); SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
try { try {
JsonGenerator ge = _jsonFactory.createGenerator(sw); JsonGenerator ge = _jsonFactory.createGenerator(sw);
// set ethereum custom pretty printer // set ethereum custom pretty printer
EtherPrettyPrinter pp = new EtherPrettyPrinter(); EtherPrettyPrinter pp = new EtherPrettyPrinter();
ge.setPrettyPrinter(pp); ge.setPrettyPrinter(pp);
_configAndWriteValue(ge, value); _configAndWriteValue(ge, value);
} catch (JsonProcessingException e) { // to support [JACKSON-758] } catch (JsonProcessingException e) { // to support [JACKSON-758]
throw e; throw e;
} catch (IOException e) { // shouldn't really happen, but is declared as possibility so: } catch (IOException e) { // shouldn't really happen, but is declared as possibility so:
throw JsonMappingException.fromUnexpectedIOE(e); throw JsonMappingException.fromUnexpectedIOE(e);
}
return sw.getAndClear();
} }
return sw.getAndClear();
}
/** /**
* An extended {@link com.fasterxml.jackson.core.util.DefaultPrettyPrinter} class to customize * An extended {@link com.fasterxml.jackson.core.util.DefaultPrettyPrinter} class to customize
* an ethereum {@link com.fasterxml.jackson.core.PrettyPrinter Pretty Printer} Generator * an ethereum {@link com.fasterxml.jackson.core.PrettyPrinter Pretty Printer} Generator
* *
* @author Alon Muroch * @author Alon Muroch
*
*/ */
public class EtherPrettyPrinter extends DefaultPrettyPrinter { public class EtherPrettyPrinter extends DefaultPrettyPrinter {
@ -55,11 +53,11 @@ public class EtherObjectMapper extends ObjectMapper {
@Override @Override
public void writeObjectFieldValueSeparator(JsonGenerator jg) public void writeObjectFieldValueSeparator(JsonGenerator jg)
throws IOException, JsonGenerationException { throws IOException, JsonGenerationException {
/** /**
* Custom object separator (Default is " : ") to make it easier to compare state dumps with other * Custom object separator (Default is " : ") to make it easier to compare state dumps with other
* ethereum client implementations * ethereum client implementations
*/ */
jg.writeRaw(": "); jg.writeRaw(": ");
} }
} }
} }

View File

@ -17,7 +17,7 @@ import java.util.*;
/** /**
* JSON Helper class to format data into ObjectNodes * JSON Helper class to format data into ObjectNodes
* to match PyEthereum blockstate output * to match PyEthereum blockstate output
* *
* Dump format: * Dump format:
* { * {
@ -80,8 +80,8 @@ public class JSONHelper {
ObjectNode statesNode = blockNode.objectNode(); ObjectNode statesNode = blockNode.objectNode();
for (ByteArrayWrapper key : keys) { for (ByteArrayWrapper key : keys) {
byte[] keyBytes = key.getData(); byte[] keyBytes = key.getData();
AccountState accountState = repository.getAccountState(keyBytes); AccountState accountState = repository.getAccountState(keyBytes);
ContractDetails details = repository.getContractDetails(keyBytes); ContractDetails details = repository.getContractDetails(keyBytes);
JSONHelper.dumpState(statesNode, Hex.toHexString(keyBytes), accountState, details); JSONHelper.dumpState(statesNode, Hex.toHexString(keyBytes), accountState, details);
} }
blockNode.put("state", statesNode); blockNode.put("state", statesNode);

View File

@ -31,29 +31,29 @@ public class AccountState {
public AccountState(byte[] address, JSONObject accountState) { public AccountState(byte[] address, JSONObject accountState) {
this.address = address; this.address = address;
String balance = accountState.get("balance").toString(); String balance = accountState.get("balance").toString();
String code = (String)accountState.get("code"); String code = (String) accountState.get("code");
String nonce = accountState.get("nonce").toString(); String nonce = accountState.get("nonce").toString();
JSONObject store = (JSONObject)accountState.get("storage"); JSONObject store = (JSONObject) accountState.get("storage");
this.balance = new BigInteger(balance).toByteArray(); this.balance = new BigInteger(balance).toByteArray();
if (code != null && code.length() > 2) if (code != null && code.length() > 2)
this.code = Hex.decode(code.substring(2)); this.code = Hex.decode(code.substring(2));
else else
this.code = ByteUtil.EMPTY_BYTE_ARRAY; this.code = ByteUtil.EMPTY_BYTE_ARRAY;
this.nonce = new BigInteger(nonce).toByteArray(); this.nonce = new BigInteger(nonce).toByteArray();
int size = store.keySet().size(); int size = store.keySet().size();
Object[] keys = store.keySet().toArray(); Object[] keys = store.keySet().toArray();
for (int i = 0; i < size; ++i) { for (int i = 0; i < size; ++i) {
String keyS = keys[i].toString(); 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); byte[] value = Utils.parseData(valS);
storage.put(new DataWord(key), new DataWord(value)); storage.put(new DataWord(key), new DataWord(value));
} }
@ -89,12 +89,12 @@ public class AccountState {
return storage; 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<>(); List<String> results = new ArrayList<>();
BigInteger expectedBalance = new BigInteger(1, this.getBalance()); 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", String formatedString = String.format("Account: %s: has unexpected balance, expected balance: %s found balance: %s",
Hex.toHexString(this.address), expectedBalance.toString(), state.getBalance().toString()); Hex.toHexString(this.address), expectedBalance.toString(), state.getBalance().toString());
results.add(formatedString); results.add(formatedString);
@ -105,13 +105,13 @@ public class AccountState {
state.getNonce(); state.getNonce();
this.getNonce(); this.getNonce();
String formatedString = String.format("Account: %s: has unexpected nonce, expected nonce: %s found nonce: %s", 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); results.add(formatedString);
} }
if (!Arrays.equals(details.getCode(),this.getCode())) { if (!Arrays.equals(details.getCode(),this.getCode())) {
String formatedString = String.format("Account: %s: has unexpected nonce, expected nonce: %s found nonce: %s", 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); results.add(formatedString);
} }
@ -121,7 +121,7 @@ public class AccountState {
Set<DataWord> expectedKeys = this.getStorage().keySet(); Set<DataWord> expectedKeys = this.getStorage().keySet();
Set<DataWord> checked = new HashSet<>(); Set<DataWord> checked = new HashSet<>();
for (DataWord key : keys){ for (DataWord key : keys) {
DataWord value = details.getStorage().get(key); DataWord value = details.getStorage().get(key);
DataWord expectedValue = this.getStorage().get(key); DataWord expectedValue = this.getStorage().get(key);
@ -137,7 +137,7 @@ public class AccountState {
continue; 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", String formatedString = String.format("Account: %s: has unexpected value, for key: %s , expectedValue: %s real value: %s",
Hex.toHexString(this.address), key.toString(), Hex.toHexString(this.address), key.toString(),
@ -149,8 +149,8 @@ public class AccountState {
checked.add(key); checked.add(key);
} }
for (DataWord key : expectedKeys){ for (DataWord key : expectedKeys) {
if (!checked.contains(key)){ if (!checked.contains(key)) {
String formatedString = String.format("Account: %s: doesn't exist expected storage key: %s", String formatedString = String.format("Account: %s: doesn't exist expected storage key: %s",
Hex.toHexString(this.address), key.toString()); Hex.toHexString(this.address), key.toString());
results.add(formatedString); results.add(formatedString);

View File

@ -30,19 +30,19 @@ public class CallCreate {
public CallCreate(JSONObject callCreateJSON) { public CallCreate(JSONObject callCreateJSON) {
String data = callCreateJSON.get("data").toString(); String data = callCreateJSON.get("data").toString();
String destination = callCreateJSON.get("destination").toString(); String destination = callCreateJSON.get("destination").toString();
String gasLimit = callCreateJSON.get("gasLimit").toString(); String gasLimit = callCreateJSON.get("gasLimit").toString();
String value = callCreateJSON.get("value").toString(); String value = callCreateJSON.get("value").toString();
if (data != null && data.length() > 2) if (data != null && data.length() > 2)
this.data = Hex.decode(data.substring(2)); this.data = Hex.decode(data.substring(2));
else else
this.data = ByteUtil.EMPTY_BYTE_ARRAY; this.data = ByteUtil.EMPTY_BYTE_ARRAY;
this.destination = Hex.decode(destination); this.destination = Hex.decode(destination);
this.gasLimit = ByteUtil.bigIntegerToBytes(new BigInteger(gasLimit)); this.gasLimit = ByteUtil.bigIntegerToBytes(new BigInteger(gasLimit));
this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value)); this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));
} }
public byte[] getData() { public byte[] getData() {
@ -64,10 +64,10 @@ public class CallCreate {
@Override @Override
public String toString() { public String toString() {
return "CallCreate{" + return "CallCreate{" +
"data=" + Hex.toHexString(data) + "data=" + Hex.toHexString(data) +
", destination=" + Hex.toHexString(destination) + ", destination=" + Hex.toHexString(destination) +
", gasLimit=" + Hex.toHexString(gasLimit) + ", gasLimit=" + Hex.toHexString(gasLimit) +
", value=" + Hex.toHexString(value) + ", value=" + Hex.toHexString(value) +
'}'; '}';
} }
} }

View File

@ -33,19 +33,19 @@ public class Env {
*/ */
public Env(JSONObject env) { public Env(JSONObject env) {
String coinbase = env.get("currentCoinbase").toString(); String coinbase = env.get("currentCoinbase").toString();
String difficulty = env.get("currentDifficulty").toString(); String difficulty = env.get("currentDifficulty").toString();
String timestamp = env.get("currentTimestamp").toString(); String timestamp = env.get("currentTimestamp").toString();
String number = env.get("currentNumber").toString(); String number = env.get("currentNumber").toString();
String gasLimit = env.get("currentGasLimit").toString(); String gasLimit = env.get("currentGasLimit").toString();
String prevHash = env.get("previousHash").toString(); String prevHash = env.get("previousHash").toString();
this.currentCoinbase = Hex.decode(coinbase); this.currentCoinbase = Hex.decode(coinbase);
this.currentDifficlty = new BigInteger(difficulty).toByteArray(); this.currentDifficlty = new BigInteger(difficulty).toByteArray();
this.currentGasLimit = new BigInteger(gasLimit).toByteArray(); this.currentGasLimit = new BigInteger(gasLimit).toByteArray();
this.currentNumber = new BigInteger(number).toByteArray(); this.currentNumber = new BigInteger(number).toByteArray();
this.currentTimestamp = new BigInteger(timestamp).toByteArray(); this.currentTimestamp = new BigInteger(timestamp).toByteArray();
this.previousHash = Hex.decode(prevHash); this.previousHash = Hex.decode(prevHash);
} }

View File

@ -42,36 +42,36 @@ public class Exec {
*/ */
public Exec(JSONObject exec) { public Exec(JSONObject exec) {
String address = exec.get("address").toString(); String address = exec.get("address").toString();
String caller = exec.get("caller").toString(); String caller = exec.get("caller").toString();
String code = exec.get("code").toString(); String code = exec.get("code").toString();
String data = exec.get("data").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 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.address = Hex.decode(address);
this.caller = Hex.decode(caller); this.caller = Hex.decode(caller);
if (code != null && code.length() > 2) if (code != null && code.length() > 2)
this.code = Hex.decode(code.substring(2)); this.code = Hex.decode(code.substring(2));
else else
this.code = ByteUtil.EMPTY_BYTE_ARRAY; this.code = ByteUtil.EMPTY_BYTE_ARRAY;
if (data != null && data.length() > 2) if (data != null && data.length() > 2)
this.data = Hex.decode(data.substring(2)); this.data = Hex.decode(data.substring(2));
else else
this.data = ByteUtil.EMPTY_BYTE_ARRAY; 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.gasPrice = ByteUtil.bigIntegerToBytes(new BigInteger(gasPrice));
this.origin = Hex.decode(origin); this.origin = Hex.decode(origin);
this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value)); this.value = ByteUtil.bigIntegerToBytes(new BigInteger(value));
} }
@ -86,6 +86,7 @@ public class Exec {
public byte[] getData() { public byte[] getData() {
return data; return data;
} }
public byte[] getCode() { public byte[] getCode() {
return code; return code;
} }

View File

@ -21,7 +21,7 @@ public class Helper {
private static Logger logger = LoggerFactory.getLogger("misc"); private static Logger logger = LoggerFactory.getLogger("misc");
public static byte[] parseDataArray(JSONArray valArray){ public static byte[] parseDataArray(JSONArray valArray) {
// value can be: // value can be:
// 1. 324234 number // 1. 324234 number
@ -29,34 +29,45 @@ public class Helper {
// 3. "239472398472" - big number // 3. "239472398472" - big number
ByteArrayOutputStream bos = new ByteArrayOutputStream(); 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); Object val = valArray.get(i);
if (val instanceof String){ if (val instanceof String) {
// Hex num // Hex num
boolean hexVal = Pattern.matches("0[xX][0-9a-fA-F]+", val.toString()); boolean hexVal = Pattern.matches("0[xX][0-9a-fA-F]+", val.toString());
if (hexVal){ if (hexVal) {
String number = ((String) val).substring(2); String number = ((String) val).substring(2);
if (number.length() % 2 == 1) number = "0" + number; if (number.length() % 2 == 1) number = "0" + number;
byte[] data = Hex.decode(number); byte[] data = Hex.decode(number);
try {bos.write(data);} catch (IOException e) { logger.error("should not happen", e);} try {
} else{ bos.write(data);
} catch (IOException e) {
logger.error("should not happen", e);
}
} else {
// BigInt num // BigInt num
boolean isNumeric = Pattern.matches("[0-9a-fA-F]+", val.toString()); boolean isNumeric = Pattern.matches("[0-9a-fA-F]+", val.toString());
if (!isNumeric) throw new Error("Wrong test case JSON format"); if (!isNumeric) throw new Error("Wrong test case JSON format");
else{ else {
BigInteger value = new BigInteger(val.toString()); BigInteger value = new BigInteger(val.toString());
try {bos.write(value.toByteArray());} catch (IOException e) try {
{ logger.error("should not happen", e);} bos.write(value.toByteArray());
} catch (IOException e) {
logger.error("should not happen", e);
}
} }
} }
} else if (val instanceof Long) { } else if (val instanceof Long) {
// Simple long // Simple long
byte[] data = ByteUtil.bigIntegerToBytes(BigInteger.valueOf((Long)val)); byte[] data = ByteUtil.bigIntegerToBytes(BigInteger.valueOf((Long) val));
try {bos.write(data);} catch (IOException e) {logger.error("should not happen", e);} try {
bos.write(data);
} catch (IOException e) {
logger.error("should not happen", e);
}
} else { } else {
throw new Error("Wrong test case JSON format"); throw new Error("Wrong test case JSON format");
} }

View File

@ -16,7 +16,7 @@ public class JSONReader {
public static String loadJSON(String filename) { public static String loadJSON(String filename) {
String json = ""; String json = "";
if(!SystemProperties.CONFIG.vmTestLoadLocal()) if (!SystemProperties.CONFIG.vmTestLoadLocal())
json = getFromUrl("https://raw.githubusercontent.com/ethereum/tests/develop/" + filename); json = getFromUrl("https://raw.githubusercontent.com/ethereum/tests/develop/" + filename);
return json == "" ? json = getFromLocal(filename) : json; return json == "" ? json = getFromLocal(filename) : json;
} }
@ -24,8 +24,9 @@ public class JSONReader {
public static String getFromLocal(String filename) { public static String getFromLocal(String filename) {
System.out.println("Loading local file: " + filename); System.out.println("Loading local file: " + filename);
try { try {
if(System.getProperty("ETHEREUM_TEST_PATH") == null) { 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"); System.out.println("ETHEREUM_TEST_PATH is not passed as a VM argument, please make sure you pass it " +
"with the correct path");
return ""; return "";
} }
System.out.println("From: " + System.getProperty("ETHEREUM_TEST_PATH")); System.out.println("From: " + System.getProperty("ETHEREUM_TEST_PATH"));

View File

@ -18,17 +18,17 @@ public class Logs {
public Logs(JSONArray jLogs) { 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); JSONObject jLog = (JSONObject) jLogs.get(i);
byte[] address = Hex.decode((String)jLog.get("address")); byte[] address = Hex.decode((String) jLog.get("address"));
byte[] data = Hex.decode(((String)jLog.get("data")).substring(2)); byte[] data = Hex.decode(((String) jLog.get("data")).substring(2));
List<DataWord> topics = new ArrayList<>(); List<DataWord> topics = new ArrayList<>();
JSONArray jTopics = (JSONArray)jLog.get("topics"); JSONArray jTopics = (JSONArray) jLog.get("topics");
for(Object t: jTopics.toArray()) { for (Object t : jTopics.toArray()) {
byte[] topic = Hex.decode(((String)t)); byte[] topic = Hex.decode(((String) t));
topics.add(new DataWord(topic)); topics.add(new DataWord(topic));
} }
@ -38,24 +38,24 @@ public class Logs {
} }
public Iterator<LogInfo> getIterator(){ public Iterator<LogInfo> getIterator() {
return logs.iterator(); return logs.iterator();
} }
public List<String> compareToReal(List<LogInfo> logs){ public List<String> compareToReal(List<LogInfo> logs) {
List<String> results = new ArrayList<>(); List<String> results = new ArrayList<>();
int i = 0; int i = 0;
for (LogInfo postLog : this.logs){ for (LogInfo postLog : this.logs) {
LogInfo realLog = logs.get(i); LogInfo realLog = logs.get(i);
String postAddress = Hex.toHexString(postLog.getAddress()); String postAddress = Hex.toHexString(postLog.getAddress());
String realAddress = Hex.toHexString(realLog.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", String formatedString = String.format("Log: %s: has unexpected address, expected address: %s found address: %s",
i, postAddress, realAddress); i, postAddress, realAddress);
@ -65,7 +65,7 @@ public class Logs {
String postData = Hex.toHexString(postLog.getData()); String postData = Hex.toHexString(postLog.getData());
String realData = Hex.toHexString(realLog.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", String formatedString = String.format("Log: %s: has unexpected data, expected data: %s found data: %s",
i, postData, realData); i, postData, realData);
@ -86,11 +86,11 @@ public class Logs {
List<DataWord> realTopics = realLog.getTopics(); List<DataWord> realTopics = realLog.getTopics();
int j = 0; int j = 0;
for (DataWord postTopic : postTopics){ for (DataWord postTopic : postTopics) {
DataWord realTopic = realTopics.get(j); 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", String formatedString = String.format("Log: %s: has unexpected topic: %s, expected topic: %s found topic: %s",
i, j, postTopic, realTopic); i, j, postTopic, realTopic);

View File

@ -21,8 +21,8 @@ public class StateTestCase {
private String name = ""; private String name = "";
private Env env; private Env env;
private Logs logs; private Logs logs;
private byte[] out; private byte[] out;
// "pre": { ... }, // "pre": { ... },
@ -39,44 +39,44 @@ public class StateTestCase {
this.name = name; this.name = name;
} }
public StateTestCase(JSONObject testCaseJSONObj) throws ParseException{ public StateTestCase(JSONObject testCaseJSONObj) throws ParseException {
try { try {
JSONObject envJSON = (JSONObject)testCaseJSONObj.get("env"); JSONObject envJSON = (JSONObject) testCaseJSONObj.get("env");
JSONArray logsJSON = (JSONArray)testCaseJSONObj.get("logs"); JSONArray logsJSON = (JSONArray) testCaseJSONObj.get("logs");
String outStr = testCaseJSONObj.get("out").toString(); String outStr = testCaseJSONObj.get("out").toString();
JSONObject txJSON = (JSONObject)testCaseJSONObj.get("transaction"); JSONObject txJSON = (JSONObject) testCaseJSONObj.get("transaction");
JSONObject preJSON = (JSONObject)testCaseJSONObj.get("pre"); JSONObject preJSON = (JSONObject) testCaseJSONObj.get("pre");
JSONObject postJSON = (JSONObject)testCaseJSONObj.get("post"); JSONObject postJSON = (JSONObject) testCaseJSONObj.get("post");
this.env = new Env(envJSON); this.env = new Env(envJSON);
this.logs = new Logs(logsJSON); this.logs = new Logs(logsJSON);
this.out = Utils.parseData(outStr); this.out = Utils.parseData(outStr);
this.transaction = new Transaction(txJSON); this.transaction = new Transaction(txJSON);
for (Object key : preJSON.keySet()){ for (Object key : preJSON.keySet()) {
byte[] keyBytes = Hex.decode(key.toString()); byte[] keyBytes = Hex.decode(key.toString());
AccountState accountState = AccountState accountState =
new AccountState(keyBytes, (JSONObject) preJSON.get(key)); new AccountState(keyBytes, (JSONObject) preJSON.get(key));
pre.put(new ByteArrayWrapper(keyBytes), accountState); pre.put(new ByteArrayWrapper(keyBytes), accountState);
} }
for (Object key : postJSON.keySet()){ for (Object key : postJSON.keySet()) {
byte[] keyBytes = Hex.decode(key.toString()); byte[] keyBytes = Hex.decode(key.toString());
AccountState accountState = AccountState accountState =
new AccountState(keyBytes, (JSONObject) postJSON.get(key)); new AccountState(keyBytes, (JSONObject) postJSON.get(key));
post.put(new ByteArrayWrapper(keyBytes), accountState); post.put(new ByteArrayWrapper(keyBytes), accountState);
} }
} catch (Throwable e) { } catch (Throwable e) {
throw new ParseException(0, e); throw new ParseException(0, e);
} }
} }

View File

@ -21,7 +21,7 @@ public class StateTestSuite {
public StateTestSuite(JSONObject testCaseJSONObj) throws ParseException { public StateTestSuite(JSONObject testCaseJSONObj) throws ParseException {
for (Object key: testCaseJSONObj.keySet()){ for (Object key : testCaseJSONObj.keySet()) {
Object testCaseJSON = testCaseJSONObj.get(key); 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); StateTestCase testCase = testCases.get(name);
if (testCase == null) throw new NullPointerException("Test cases doesn't exist: " + 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(); return testCases.values();
} }
} }

View File

@ -45,73 +45,74 @@ public class TestCase {
// "callcreates": { ... } // "callcreates": { ... }
private List<CallCreate> callCreateList = new ArrayList<>(); 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(testCaseJSONObj);
this.name = name; this.name = name;
} }
public TestCase(JSONObject testCaseJSONObj) throws ParseException{ public TestCase(JSONObject testCaseJSONObj) throws ParseException {
try { try {
JSONObject envJSON = (JSONObject)testCaseJSONObj.get("env"); JSONObject envJSON = (JSONObject) testCaseJSONObj.get("env");
JSONObject execJSON = (JSONObject)testCaseJSONObj.get("exec"); JSONObject execJSON = (JSONObject) testCaseJSONObj.get("exec");
JSONObject preJSON = (JSONObject)testCaseJSONObj.get("pre"); JSONObject preJSON = (JSONObject) testCaseJSONObj.get("pre");
JSONObject postJSON = new JSONObject(); JSONObject postJSON = new JSONObject();
if(testCaseJSONObj.containsKey("post")) // in cases where there is no post dictionary (when testing for exceptions for example) if (testCaseJSONObj.containsKey("post")) // in cases where there is no post dictionary (when testing for
postJSON = (JSONObject)testCaseJSONObj.get("post"); // exceptions for example)
JSONArray callCreates = new JSONArray(); postJSON = (JSONObject) testCaseJSONObj.get("post");
if(testCaseJSONObj.containsKey("callcreates")) JSONArray callCreates = new JSONArray();
callCreates = (JSONArray)testCaseJSONObj.get("callcreates"); if (testCaseJSONObj.containsKey("callcreates"))
callCreates = (JSONArray) testCaseJSONObj.get("callcreates");
JSONArray logsJSON = new JSONArray(); JSONArray logsJSON = new JSONArray();
if(testCaseJSONObj.containsKey("logs")) if (testCaseJSONObj.containsKey("logs"))
logsJSON = (JSONArray)testCaseJSONObj.get("logs"); logsJSON = (JSONArray) testCaseJSONObj.get("logs");
logs = new Logs(logsJSON); logs = new Logs(logsJSON);
String gasString = "0"; String gasString = "0";
if(testCaseJSONObj.containsKey("gas")) if (testCaseJSONObj.containsKey("gas"))
gasString = testCaseJSONObj.get("gas").toString(); gasString = testCaseJSONObj.get("gas").toString();
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString)); this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString));
String outString = null; String outString = null;
if(testCaseJSONObj.containsKey("out")) if (testCaseJSONObj.containsKey("out"))
outString = testCaseJSONObj.get("out").toString(); outString = testCaseJSONObj.get("out").toString();
if (outString != null && outString.length() > 2) if (outString != null && outString.length() > 2)
this.out = Hex.decode(outString.substring(2)); this.out = Hex.decode(outString.substring(2));
else else
this.out = ByteUtil.EMPTY_BYTE_ARRAY; this.out = ByteUtil.EMPTY_BYTE_ARRAY;
for (Object key : preJSON.keySet()){ for (Object key : preJSON.keySet()) {
byte[] keyBytes = Hex.decode(key.toString()); byte[] keyBytes = Hex.decode(key.toString());
AccountState accountState = AccountState accountState =
new AccountState(keyBytes, (JSONObject) preJSON.get(key)); new AccountState(keyBytes, (JSONObject) preJSON.get(key));
pre.put(new ByteArrayWrapper(keyBytes), accountState); pre.put(new ByteArrayWrapper(keyBytes), accountState);
} }
for (Object key : postJSON.keySet()){ for (Object key : postJSON.keySet()) {
byte[] keyBytes = Hex.decode(key.toString()); byte[] keyBytes = Hex.decode(key.toString());
AccountState accountState = AccountState accountState =
new AccountState(keyBytes, (JSONObject) postJSON.get(key)); new AccountState(keyBytes, (JSONObject) postJSON.get(key));
post.put(new ByteArrayWrapper(keyBytes), accountState); 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.callCreateList.add(cc);
} }
this.env = new Env(envJSON); this.env = new Env(envJSON);
this.exec = new Exec(execJSON); this.exec = new Exec(execJSON);
} catch (Throwable e) { } catch (Throwable e) {
throw new ParseException(0, e); throw new ParseException(0, e);
} }
} }
@ -147,7 +148,7 @@ public class TestCase {
return callCreateList; return callCreateList;
} }
public String getName(){ public String getName() {
return name; return name;
} }

View File

@ -15,11 +15,11 @@ import java.math.BigInteger;
* Created on: 19/12/2014 12:22 * Created on: 19/12/2014 12:22
*/ */
public class TestProgramInvokeFactory implements ProgramInvokeFactory{ public class TestProgramInvokeFactory implements ProgramInvokeFactory {
Env env; Env env;
TestProgramInvokeFactory(Env env){ TestProgramInvokeFactory(Env env) {
this.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 ***/ /*** ADDRESS op ***/
// YP: Get address of currently executing account. // 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 ***/ /*** ORIGIN op ***/
// YP: This is the sender of original transaction; it is never a contract. // YP: This is the sender of original transaction; it is never a contract.
byte[] origin = tx.getSender(); byte[] origin = tx.getSender();
/*** CALLER op ***/ /*** CALLER op ***/
// YP: This is the address of the account that is directly responsible for this execution. // 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()); long number = ByteUtil.byteArrayToLong(env.getCurrentNumber());
/*** DIFFICULTY op ***/ /*** DIFFICULTY op ***/
byte[] difficulty = env.getCurrentDifficlty(); byte[] difficulty = env.getCurrentDifficlty();
/*** GASLIMIT op ***/ /*** GASLIMIT op ***/
long gaslimit = ByteUtil.byteArrayToLong( env.getCurrentGasLimit() ); long gaslimit = ByteUtil.byteArrayToLong(env.getCurrentGasLimit());
return new ProgramInvokeImpl(address, origin, caller, balance, return new ProgramInvokeImpl(address, origin, caller, balance,
gasPrice, gas, callValue, data, lastHash, coinbase, gasPrice, gas, callValue, data, lastHash, coinbase,

View File

@ -53,7 +53,7 @@ public class TestRunner {
List<String> results = null; List<String> results = null;
logger.info("\n***"); logger.info("\n***");
logger.info(" Running test case: [" + testCase.getName() + "]") ; logger.info(" Running test case: [" + testCase.getName() + "]");
logger.info("***\n"); logger.info("***\n");
results = new ArrayList<>(); results = new ArrayList<>();
@ -62,7 +62,7 @@ public class TestRunner {
logger.info("loaded repository"); 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()); logger.info("transaction: {}", tx.toString());
byte[] secretKey = testCase.getTransaction().secretKey; byte[] secretKey = testCase.getTransaction().secretKey;
@ -91,9 +91,9 @@ public class TestRunner {
List<String> logResults = testCase.getLogs().compareToReal(logs); List<String> logResults = testCase.getLogs().compareToReal(logs);
results.addAll(logResults); results.addAll(logResults);
Set<ByteArrayWrapper> fullAddressSet = repository.getFullAddressSet(); Set<ByteArrayWrapper> fullAddressSet = repository.getFullAddressSet();
int repoSize = 0; int repoSize = 0;
for (ByteArrayWrapper addrWrapped : fullAddressSet){ for (ByteArrayWrapper addrWrapped : fullAddressSet) {
byte[] addr = addrWrapped.getData(); byte[] addr = addrWrapped.getData();
@ -101,11 +101,11 @@ public class TestRunner {
ContractDetails contractDetails = repository.getContractDetails(addr); ContractDetails contractDetails = repository.getContractDetails(addr);
logger.info("{} \n{} \n{}", Hex.toHexString(addr), logger.info("{} \n{} \n{}", Hex.toHexString(addr),
accountState.toString(), contractDetails.toString() ); accountState.toString(), contractDetails.toString());
logger.info(""); logger.info("");
AccountState expectedAccountState = testCase.getPost().get(wrap(addr)); 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)); String formatedString = String.format("Unexpected account state: address: %s", Hex.toHexString(addr));
results.add(formatedString); results.add(formatedString);
continue; continue;
@ -119,7 +119,7 @@ public class TestRunner {
int postRepoSize = testCase.getPost().size(); int postRepoSize = testCase.getPost().size();
if (postRepoSize > repoSize){ if (postRepoSize > repoSize) {
results.add("ERROR: Post repository contains more accounts than executed repository "); results.add("ERROR: Post repository contains more accounts than executed repository ");
} }
@ -129,7 +129,7 @@ public class TestRunner {
public List<String> runTestCase(TestCase testCase) { public List<String> runTestCase(TestCase testCase) {
logger.info("\n***"); logger.info("\n***");
logger.info(" Running test case: [" + testCase.getName() + "]") ; logger.info(" Running test case: [" + testCase.getName() + "]");
logger.info("***\n"); logger.info("***\n");
List<String> results = new ArrayList<>(); List<String> results = new ArrayList<>();
@ -141,29 +141,29 @@ public class TestRunner {
/* 2. Create ProgramInvoke - Env/Exec */ /* 2. Create ProgramInvoke - Env/Exec */
Env env = testCase.getEnv(); Env env = testCase.getEnv();
Exec exec = testCase.getExec(); Exec exec = testCase.getExec();
Logs logs = testCase.getLogs(); Logs logs = testCase.getLogs();
byte[] address = exec.getAddress(); byte[] address = exec.getAddress();
byte[] origin = exec.getOrigin(); byte[] origin = exec.getOrigin();
byte[] caller = exec.getCaller(); byte[] caller = exec.getCaller();
byte[] balance = ByteUtil.bigIntegerToBytes(repository.getBalance(exec.getAddress())); byte[] balance = ByteUtil.bigIntegerToBytes(repository.getBalance(exec.getAddress()));
byte[] gasPrice = exec.getGasPrice(); byte[] gasPrice = exec.getGasPrice();
byte[] gas = exec.getGas(); byte[] gas = exec.getGas();
byte[] callValue = exec.getValue(); byte[] callValue = exec.getValue();
byte[] msgData = exec.getData(); byte[] msgData = exec.getData();
byte[] lastHash = env.getPreviousHash(); byte[] lastHash = env.getPreviousHash();
byte[] coinbase = env.getCurrentCoinbase(); byte[] coinbase = env.getCurrentCoinbase();
long timestamp = new BigInteger(env.getCurrentTimestamp()).longValue(); long timestamp = new BigInteger(env.getCurrentTimestamp()).longValue();
long number = new BigInteger(env.getCurrentNumber()).longValue(); long number = new BigInteger(env.getCurrentNumber()).longValue();
byte[] difficulty = env.getCurrentDifficlty(); byte[] difficulty = env.getCurrentDifficlty();
long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue(); long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue();
// Origin and caller need to exist in order to be able to execute // 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); repository.createAccount(origin);
if(repository.getAccountState(caller) == null) if (repository.getAccountState(caller) == null)
repository.createAccount(caller); repository.createAccount(caller);
ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance, ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance,
@ -177,27 +177,24 @@ public class TestRunner {
boolean vmDidThrowAnEception = false; boolean vmDidThrowAnEception = false;
RuntimeException e = null; RuntimeException e = null;
try { try {
while(!program.isStopped()) while (!program.isStopped())
vm.step(program); vm.step(program);
} } catch (RuntimeException ex) {
catch (RuntimeException ex) {
vmDidThrowAnEception = true; vmDidThrowAnEception = true;
e = ex; e = ex;
} }
program.saveProgramTraceToFile(testCase.getName()); program.saveProgramTraceToFile(testCase.getName());
if(testCase.getPost().size() == 0) { if (testCase.getPost().size() == 0) {
if(vmDidThrowAnEception != true) { if (vmDidThrowAnEception != true) {
String output = String output =
String.format("VM was expected to throw an exception"); String.format("VM was expected to throw an exception");
logger.info(output); logger.info(output);
results.add(output); results.add(output);
} } else
else
logger.info("VM did throw an exception: " + e.toString()); logger.info("VM did throw an exception: " + e.toString());
} } else {
else { if (vmDidThrowAnEception) {
if(vmDidThrowAnEception) {
String output = String output =
String.format("VM threw an unexpected exception: " + e.toString()); String.format("VM threw an unexpected exception: " + e.toString());
logger.info(output); logger.info(output);
@ -213,9 +210,9 @@ public class TestRunner {
AccountState accountState = testCase.getPost().get(key); AccountState accountState = testCase.getPost().get(key);
long expectedNonce = accountState.getNonceLong(); long expectedNonce = accountState.getNonceLong();
BigInteger expectedBalance = accountState.getBigIntegerBalance(); BigInteger expectedBalance = accountState.getBigIntegerBalance();
byte[] expectedCode = accountState.getCode(); byte[] expectedCode = accountState.getCode();
boolean accountExist = (null != repository.getAccountState(key.getData())); boolean accountExist = (null != repository.getAccountState(key.getData()));
if (!accountExist) { if (!accountExist) {
@ -283,17 +280,17 @@ public class TestRunner {
continue; continue;
} }
Map<DataWord, DataWord> testStorage = contractDetails.getStorage(); Map<DataWord, DataWord> testStorage = contractDetails.getStorage();
DataWord actualValue = testStorage.get(new DataWord(storageKey.getData())); DataWord actualValue = testStorage.get(new DataWord(storageKey.getData()));
if (actualValue == null || if (actualValue == null ||
!Arrays.equals(expectedStValue, actualValue.getNoLeadZeroesData())) { !Arrays.equals(expectedStValue, actualValue.getNoLeadZeroesData())) {
String output = String output =
String.format("Storage value different: key [ %s ], expectedValue: [ %s ], actualValue: [ %s ]", String.format("Storage value different: key [ %s ], expectedValue: [ %s ], actualValue: [ %s ]",
Hex.toHexString(storageKey.getData()), Hex.toHexString(storageKey.getData()),
Hex.toHexString(expectedStValue), Hex.toHexString(expectedStValue),
actualValue == null ? "" : Hex.toHexString(actualValue.getNoLeadZeroesData())); actualValue == null ? "" : Hex.toHexString(actualValue.getNoLeadZeroesData()));
logger.info(output); logger.info(output);
results.add(output); results.add(output);
} }
@ -304,36 +301,35 @@ public class TestRunner {
Iterator<LogInfo> postLogs = logs.getIterator(); Iterator<LogInfo> postLogs = logs.getIterator();
int i = 0; int i = 0;
while(postLogs.hasNext()) { while (postLogs.hasNext()) {
LogInfo expectedLogInfo = postLogs.next(); LogInfo expectedLogInfo = postLogs.next();
LogInfo foundLogInfo = null; LogInfo foundLogInfo = null;
if (logResult.size() > i) if (logResult.size() > i)
foundLogInfo = logResult.get(i); foundLogInfo = logResult.get(i);
if(foundLogInfo == null) { if (foundLogInfo == null) {
String output = String output =
String.format("Expected log [ %s ]", expectedLogInfo.toString()); String.format("Expected log [ %s ]", expectedLogInfo.toString());
logger.info(output); logger.info(output);
results.add(output); results.add(output);
} } else {
else { if (!Arrays.equals(expectedLogInfo.getAddress(), foundLogInfo.getAddress())) {
if(!Arrays.equals(expectedLogInfo.getAddress(), foundLogInfo.getAddress())) {
String output = String output =
String.format("Expected address [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getAddress()), Hex.toHexString(foundLogInfo.getAddress())); String.format("Expected address [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getAddress()), Hex.toHexString(foundLogInfo.getAddress()));
logger.info(output); logger.info(output);
results.add(output); results.add(output);
} }
if(!Arrays.equals(expectedLogInfo.getData(), foundLogInfo.getData())) { if (!Arrays.equals(expectedLogInfo.getData(), foundLogInfo.getData())) {
String output = String output =
String.format("Expected data [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getData()), Hex.toHexString(foundLogInfo.getData())); String.format("Expected data [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getData()), Hex.toHexString(foundLogInfo.getData()));
logger.info(output); logger.info(output);
results.add(output); results.add(output);
} }
if(!expectedLogInfo.getBloom().equals(foundLogInfo.getBloom())) { if (!expectedLogInfo.getBloom().equals(foundLogInfo.getBloom())) {
String output = String output =
String.format("Expected bloom [ %s ], found [ %s ]", String.format("Expected bloom [ %s ], found [ %s ]",
Hex.toHexString(expectedLogInfo.getBloom().getData()), Hex.toHexString(expectedLogInfo.getBloom().getData()),
@ -342,18 +338,18 @@ public class TestRunner {
results.add(output); results.add(output);
} }
if(expectedLogInfo.getTopics().size() != foundLogInfo.getTopics().size()) { if (expectedLogInfo.getTopics().size() != foundLogInfo.getTopics().size()) {
String output = 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); logger.info(output);
results.add(output); results.add(output);
} } else {
else { int j = 0;
int j=0; for (DataWord topic : expectedLogInfo.getTopics()) {
for(DataWord topic: expectedLogInfo.getTopics()) {
byte[] foundTopic = foundLogInfo.getTopics().get(j).getData(); byte[] foundTopic = foundLogInfo.getTopics().get(j).getData();
if(!Arrays.equals(topic.getData(), foundTopic)) { if (!Arrays.equals(topic.getData(), foundTopic)) {
String output = String output =
String.format("Expected topic [ %s ], found [ %s ]", Hex.toHexString(topic.getData()), Hex.toHexString(foundTopic)); String.format("Expected topic [ %s ], found [ %s ]", Hex.toHexString(topic.getData()), Hex.toHexString(foundTopic));
logger.info(output); logger.info(output);
@ -373,7 +369,7 @@ public class TestRunner {
// TODO: -> basically the deleted by suicide should be deleted // TODO: -> basically the deleted by suicide should be deleted
// TODO: -> and no unexpected created // TODO: -> and no unexpected created
List<org.ethereum.vm.CallCreate> resultCallCreates = List<org.ethereum.vm.CallCreate> resultCallCreates =
program.getResult().getCallCreateList(); program.getResult().getCallCreateList();
// assert call creates // 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[] nonceBytes = ByteUtil.longToBytes(tx.nonce);
byte[] gasPriceBytes = ByteUtil.longToBytes(tx.gasPrice); byte[] gasPriceBytes = ByteUtil.longToBytes(tx.gasPrice);
byte[] gasBytes = ByteUtil.longToBytes(tx.gasLimit); byte[] gasBytes = ByteUtil.longToBytes(tx.gasLimit);
byte[] valueBytes = ByteUtil.longToBytes(tx.value); byte[] valueBytes = ByteUtil.longToBytes(tx.value);
byte[] toAddr = tx.getTo(); byte[] toAddr = tx.getTo();
byte[] data = tx.getData(); byte[] data = tx.getData();
org.ethereum.core.Transaction transaction = new org.ethereum.core.Transaction( org.ethereum.core.Transaction transaction = new org.ethereum.core.Transaction(
nonceBytes, gasPriceBytes, gasBytes, nonceBytes, gasPriceBytes, gasBytes,
@ -508,7 +504,7 @@ public class TestRunner {
return transaction; return transaction;
} }
public RepositoryDummy loadRepository(Map<ByteArrayWrapper, AccountState> pre){ public RepositoryDummy loadRepository(Map<ByteArrayWrapper, AccountState> pre) {
RepositoryDummy track = new RepositoryDummy(); RepositoryDummy track = new RepositoryDummy();
@ -524,7 +520,7 @@ public class TestRunner {
track.saveCode(addr, accountState.getCode()); 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)); track.addStorageRow(addr, storageKey, accountState.getStorage().get(storageKey));
} }
} }

View File

@ -18,7 +18,7 @@ public class TestSuite {
public TestSuite(JSONObject testCaseJSONObj) throws ParseException { public TestSuite(JSONObject testCaseJSONObj) throws ParseException {
for (Object key: testCaseJSONObj.keySet()){ for (Object key : testCaseJSONObj.keySet()) {
Object testCaseJSON = testCaseJSONObj.get(key); Object testCaseJSON = testCaseJSONObj.get(key);
TestCase testCase = new TestCase(key.toString(), (JSONObject) testCaseJSON); 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(); return testList.iterator();
} }
} }

View File

@ -19,12 +19,12 @@ import static org.ethereum.util.ByteUtil.toHexString;
public class Transaction { public class Transaction {
byte[] data; byte[] data;
long gasLimit; long gasLimit;
long gasPrice; long gasPrice;
long nonce; long nonce;
byte[] secretKey; byte[] secretKey;
byte[] to; byte[] to;
long value; long value;
/* e.g. /* e.g.
"transaction" : { "transaction" : {
@ -40,22 +40,22 @@ public class Transaction {
public Transaction(JSONObject callCreateJSON) { public Transaction(JSONObject callCreateJSON) {
String dataStr = callCreateJSON.get("data").toString(); String dataStr = callCreateJSON.get("data").toString();
String gasLimitStr = callCreateJSON.get("gasLimit").toString(); String gasLimitStr = callCreateJSON.get("gasLimit").toString();
String gasPriceStr = callCreateJSON.get("gasPrice").toString(); String gasPriceStr = callCreateJSON.get("gasPrice").toString();
String nonceStr = callCreateJSON.get("nonce").toString(); String nonceStr = callCreateJSON.get("nonce").toString();
String secretKeyStr = callCreateJSON.get("secretKey").toString(); String secretKeyStr = callCreateJSON.get("secretKey").toString();
String toStr = callCreateJSON.get("to").toString(); String toStr = callCreateJSON.get("to").toString();
String valueStr = callCreateJSON.get("value").toString(); String valueStr = callCreateJSON.get("value").toString();
this.data = Utils.parseData(dataStr); this.data = Utils.parseData(dataStr);
this.gasLimit = Utils.parseLong(gasLimitStr); this.gasLimit = Utils.parseLong(gasLimitStr);
this.gasPrice = Utils.parseLong(gasPriceStr); this.gasPrice = Utils.parseLong(gasPriceStr);
this.nonce = Utils.parseLong(nonceStr); this.nonce = Utils.parseLong(nonceStr);
this.secretKey = Utils.parseData(secretKeyStr); this.secretKey = Utils.parseData(secretKeyStr);
this.to = Utils.parseData(toStr); this.to = Utils.parseData(toStr);
this.value = Utils.parseLong(valueStr); this.value = Utils.parseLong(valueStr);
} }
public byte[] getData() { public byte[] getData() {

View File

@ -14,14 +14,14 @@ import org.spongycastle.util.encoders.Hex;
public class Utils { 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 == null) return ByteUtil.EMPTY_BYTE_ARRAY;
if (data.startsWith("0x")) data = data.substring(2); if (data.startsWith("0x")) data = data.substring(2);
return Hex.decode(data); return Hex.decode(data);
} }
public static long parseLong(String data){ public static long parseLong(String data) {
return data.equals("") ? 0 : Long.parseLong(data); return data.equals("") ? 0 : Long.parseLong(data);
} }
} }

View File

@ -16,11 +16,18 @@ import java.util.Set;
public interface EthereumListener { public interface EthereumListener {
public void trace(String output); public void trace(String output);
public void onBlock(Block block); public void onBlock(Block block);
public void onRecvMessage(Message message); public void onRecvMessage(Message message);
public void onSendMessage(Message message); public void onSendMessage(Message message);
public void onPeerDisconnect(String host, long port); public void onPeerDisconnect(String host, long port);
public void onPendingTransactionsReceived(Set<Transaction> transactions); public void onPendingTransactionsReceived(Set<Transaction> transactions);
public void onSyncDone(); public void onSyncDone();
public void onNoConnections(); public void onNoConnections();
} }

View File

@ -42,7 +42,7 @@ public class EthereumListenerAdapter implements EthereumListener {
} }
@Override @Override
public void onNoConnections(){ public void onNoConnections() {
} }
} }

View File

@ -13,8 +13,8 @@ import java.util.Set;
* @author: Roman Mandeleil * @author: Roman Mandeleil
* Created on: 12/11/2014 08:34 * Created on: 12/11/2014 08:34
*/ */
@Component(value="EthereumListener") @Component(value = "EthereumListener")
public class EthereumListenerWrapper implements EthereumListener{ public class EthereumListenerWrapper implements EthereumListener {
EthereumListener listener; EthereumListener listener;
@ -64,12 +64,12 @@ public class EthereumListenerWrapper implements EthereumListener{
@Override @Override
public void onNoConnections(){ public void onNoConnections() {
if (listener != null) if (listener != null)
listener.onNoConnections(); listener.onNoConnections();
} }
public void addListener(EthereumListener listener){ public void addListener(EthereumListener listener) {
if (listener != null) if (listener != null)
this.listener = listener; this.listener = listener;
} }

View File

@ -31,7 +31,7 @@ public class AdminInfo {
return consensus; return consensus;
} }
public void lostConsensus(){ public void lostConsensus() {
consensus = false; consensus = false;
} }
} }

View File

@ -75,7 +75,7 @@ public class WorldManager {
public void addListener(EthereumListener listener) { public void addListener(EthereumListener listener) {
logger.info("Ethereum listener added"); logger.info("Ethereum listener added");
((EthereumListenerWrapper)this.listener).addListener(listener); ((EthereumListenerWrapper) this.listener).addListener(listener);
} }
public void startPeerDiscovery() { public void startPeerDiscovery() {
@ -88,7 +88,7 @@ public class WorldManager {
peerDiscovery.stop(); peerDiscovery.stop();
} }
public void addPendingTransactions(Set<Transaction> transactions){ public void addPendingTransactions(Set<Transaction> transactions) {
logger.info("Pending transaction list added: size: [{}]", transactions.size()); logger.info("Pending transaction list added: size: [{}]", transactions.size());
if (listener != null) if (listener != null)
@ -96,15 +96,15 @@ public class WorldManager {
pendingTransactions.addAll(transactions); 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())); logger.info("Clear transaction, hash: [{}]", Hex.toHexString(tx.getHash()));
pendingTransactions.remove(tx); pendingTransactions.remove(tx);
} }
} }
public ChannelManager getChannelManager(){ public ChannelManager getChannelManager() {
return channelManager; return channelManager;
} }
@ -116,7 +116,7 @@ public class WorldManager {
return listener; return listener;
} }
public void setWallet(Wallet wallet) { public void setWallet(Wallet wallet) {
this.wallet = wallet; this.wallet = wallet;
} }
@ -144,7 +144,7 @@ public class WorldManager {
return pendingTransactions; return pendingTransactions;
} }
public boolean isBlockchainLoading(){ public boolean isBlockchainLoading() {
return blockchain.getQueue().size() > 2; 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 // update world state by dummy hash
byte[] rootHash = Hex.decode(CONFIG.rootHashStart()); byte[] rootHash = Hex.decode(CONFIG.rootHashStart());
logger.info("Loading root hash from property file: [{}]", CONFIG.rootHashStart()); logger.info("Loading root hash from property file: [{}]", CONFIG.rootHashStart());
this.repository.syncToRoot(rootHash); this.repository.syncToRoot(rootHash);
} else{ } else {
// Update world state to latest loaded block from db // Update world state to latest loaded block from db
this.repository.syncToRoot(blockchain.getBestBlock().getStateRoot()); this.repository.syncToRoot(blockchain.getBestBlock().getStateRoot());
@ -202,7 +202,7 @@ public class WorldManager {
*/ */
} }
public void reset(){ public void reset() {
logger.info("Resetting blockchain "); logger.info("Resetting blockchain ");
repository.reset(); repository.reset();
blockchain.reset(); blockchain.reset();

View File

@ -77,9 +77,9 @@ public class Miner {
byte[] testNonce = new byte[32]; byte[] testNonce = new byte[32];
byte[] concat; 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)); System.out.println("mining: " + new BigInteger(1, testNonce));
} }
@ -87,7 +87,7 @@ public class Miner {
sleep(); sleep();
concat = Arrays.concatenate(hash, testNonce); concat = Arrays.concatenate(hash, testNonce);
byte[] result = SHA3Helper.sha3(concat); 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); newBlock.setNonce(testNonce);
return true; return true;
} }
@ -95,11 +95,11 @@ public class Miner {
return false; // couldn't find a valid nonce return false; // couldn't find a valid nonce
} }
public void stop(){ public void stop() {
stop = true; stop = true;
} }
private void sleep(){ private void sleep() {
try { try {
// Thread.sleep(1); // Thread.sleep(1);
Thread.sleep(10); Thread.sleep(10);

View File

@ -27,17 +27,25 @@ public class BlockQueue {
private static final Logger logger = LoggerFactory.getLogger("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<>(); 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<>(); 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; private BigInteger highestTotalDifficulty;
/** Last block in the queue to be processed */ /**
* Last block in the queue to be processed
*/
private Block lastBlock; private Block lastBlock;
private Timer timer = new Timer("BlockQueueTimer"); private Timer timer = new Timer("BlockQueueTimer");
@ -61,7 +69,7 @@ public class BlockQueue {
return; return;
logger.info("BlockQueue size: {}", blockReceivedQueue.size()); logger.info("BlockQueue size: {}", blockReceivedQueue.size());
while(!blockReceivedQueue.isEmpty()){ while (!blockReceivedQueue.isEmpty()) {
Block block = blockReceivedQueue.poll(); Block block = blockReceivedQueue.poll();
logger.info("Processing block index: {}", block.getNumber()); logger.info("Processing block index: {}", block.getNumber());
@ -85,22 +93,23 @@ public class BlockQueue {
blockReceivedQueue.addAll(blockList); blockReceivedQueue.addAll(blockList);
lastBlock = blockList.get(blockList.size() - 1); 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(), blockReceivedQueue.size(),
lastBlock.getNumber()); lastBlock.getNumber());
} }
/** /**
* adding single block to the queue usually * 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 * @param block - new block
*/ */
public void addBlock(Block block){ public void addBlock(Block block) {
blockReceivedQueue.add(block); blockReceivedQueue.add(block);
lastBlock = 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(), blockReceivedQueue.size(),
lastBlock.getNumber()); lastBlock.getNumber());
} }
@ -143,19 +152,19 @@ public class BlockQueue {
public void addHash(byte[] hash) { public void addHash(byte[] hash) {
blockHashQueue.addLast(hash); blockHashQueue.addLast(hash);
if (logger.isTraceEnabled()){ if (logger.isTraceEnabled()) {
logger.trace("Adding hash to a hashQueue: [{}]" , Hex.toHexString(hash)); 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()); ListIterator iterator = hashes.listIterator(hashes.size());
while(iterator.hasPrevious()) while (iterator.hasPrevious())
blockHashQueue.addLast((byte[])iterator.previous()); blockHashQueue.addLast((byte[]) iterator.previous());
} }
public void addNewBlockHash(byte[] hash){ public void addNewBlockHash(byte[] hash) {
blockHashQueue.addFirst(hash); blockHashQueue.addFirst(hash);
} }
@ -168,14 +177,14 @@ public class BlockQueue {
List<byte[]> hashes = new ArrayList<>(); List<byte[]> hashes = new ArrayList<>();
while (!blockHashQueue.isEmpty() && hashes.size() < CONFIG.maxBlocksAsk()) { while (!blockHashQueue.isEmpty() && hashes.size() < CONFIG.maxBlocksAsk()) {
hashes.add(blockHashQueue.removeLast()); hashes.add(blockHashQueue.removeLast());
} }
return hashes; return hashes;
} }
// a bit ugly but really gives // a bit ugly but really gives
// good result // good result
public void logHashQueueSize(){ public void logHashQueueSize() {
logger.info("Block hashes list size: [{}]", blockHashQueue.size()); logger.info("Block hashes list size: [{}]", blockHashQueue.size());
} }
@ -213,11 +222,11 @@ public class BlockQueue {
return blockReceivedQueue.size(); return blockReceivedQueue.size();
} }
public boolean isHashesEmpty(){ public boolean isHashesEmpty() {
return blockHashQueue.size() == 0; return blockHashQueue.size() == 0;
} }
public void clear(){ public void clear() {
this.blockHashQueue.clear(); this.blockHashQueue.clear();
this.blockReceivedQueue.clear(); this.blockReceivedQueue.clear();
} }

View File

@ -16,16 +16,16 @@ import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue; 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 * PING by PONG
* GET_PEERS by PEERS * GET_PEERS by PEERS
* GET_TRANSACTIONS by TRANSACTIONS * GET_TRANSACTIONS by TRANSACTIONS
* GET_BLOCK_HASHES by BLOCK_HASHES * GET_BLOCK_HASHES by BLOCK_HASHES
* GET_BLOCKS by BLOCKS * GET_BLOCKS by BLOCKS
* *
* The following messages will not be answered: * The following messages will not be answered:
* PONG, PEERS, HELLO, STATUS, TRANSACTIONS, BLOCKS * PONG, PEERS, HELLO, STATUS, TRANSACTIONS, BLOCKS
* *
* @author Roman Mandeleil * @author Roman Mandeleil
@ -44,9 +44,10 @@ public class MessageQueue {
WorldManager worldManager; WorldManager worldManager;
boolean hasPing = false; boolean hasPing = false;
public MessageQueue(){} public MessageQueue() {
}
public void activate(ChannelHandlerContext ctx){ public void activate(ChannelHandlerContext ctx) {
this.ctx = ctx; this.ctx = ctx;
timer.scheduleAtFixedRate(new TimerTask() { timer.scheduleAtFixedRate(new TimerTask() {
public void run() { public void run() {
@ -117,7 +118,7 @@ public class MessageQueue {
} }
} }
public void close(){ public void close() {
timer.cancel(); timer.cancel();
timer.purge(); timer.purge();
} }

View File

@ -30,7 +30,7 @@ public class Capability implements Comparable<Capability> {
if (this == obj) return true; if (this == obj) return true;
if (!(obj instanceof Capability)) return false; if (!(obj instanceof Capability)) return false;
Capability other = (Capability)obj; Capability other = (Capability) obj;
if (this.name == null) if (this.name == null)
return other.name == null; return other.name == null;
else else

View File

@ -22,6 +22,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
/** /**
* This class creates the connection to an remote address using the Netty framework * This class creates the connection to an remote address using the Netty framework
*
* @see <a href="http://netty.io">http://netty.io</a> * @see <a href="http://netty.io">http://netty.io</a>
*/ */
@Component @Component

View File

@ -18,7 +18,9 @@ import org.ethereum.util.Utils;
*/ */
public class BlockHashesMessage extends EthMessage { 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; private List<byte[]> blockHashes;
public BlockHashesMessage(byte[] payload) { public BlockHashesMessage(byte[] payload) {
@ -69,7 +71,7 @@ public class BlockHashesMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.BLOCK_HASHES; return EthMessageCodes.BLOCK_HASHES;
} }

View File

@ -23,7 +23,7 @@ public class BlocksMessage extends EthMessage {
super(encoded); super(encoded);
} }
public BlocksMessage(List<Block> blocks){ public BlocksMessage(List<Block> blocks) {
this.blocks = blocks; this.blocks = blocks;
parsed = true; parsed = true;
} }
@ -45,7 +45,7 @@ public class BlocksMessage extends EthMessage {
List<byte[]> encodedElements = new Vector<>(); List<byte[]> encodedElements = new Vector<>();
encodedElements.add(RLP.encodeByte(BLOCKS.asByte())); encodedElements.add(RLP.encodeByte(BLOCKS.asByte()));
for (Block block : blocks){ for (Block block : blocks) {
encodedElements.add(block.getEncoded()); encodedElements.add(block.getEncoded());
} }
@ -68,7 +68,7 @@ public class BlocksMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.BLOCKS; return EthMessageCodes.BLOCKS;
} }

View File

@ -73,7 +73,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
private List<byte[]> sentHashes; private List<byte[]> sentHashes;
private Block lastBlock = Genesis.getInstance(); private Block lastBlock = Genesis.getInstance();
public EthHandler(){ public EthHandler() {
this.peerDiscoveryMode = false; this.peerDiscoveryMode = false;
} }
@ -82,7 +82,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
this.msgQueue = msgQueue; this.msgQueue = msgQueue;
} }
public void activate(){ public void activate() {
logger.info("ETH protocol activated"); logger.info("ETH protocol activated");
worldManager.getListener().trace("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; return active;
} }
@ -121,7 +121,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
break; break;
case TRANSACTIONS: case TRANSACTIONS:
msgQueue.receivedMessage(msg); msgQueue.receivedMessage(msg);
processTransactions((TransactionsMessage)msg); processTransactions((TransactionsMessage) msg);
// List<Transaction> txList = transactionsMessage.getTransactions(); // List<Transaction> txList = transactionsMessage.getTransactions();
// for(Transaction tx : txList) // for(Transaction tx : txList)
// WorldManager.getInstance().getBlockchain().applyTransaction(null, // WorldManager.getInstance().getBlockchain().applyTransaction(null,
@ -138,7 +138,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
break; break;
case GET_BLOCKS: case GET_BLOCKS:
msgQueue.receivedMessage(msg); msgQueue.receivedMessage(msg);
processGetBlocks( (GetBlocksMessage) msg ); processGetBlocks((GetBlocksMessage) msg);
break; break;
case BLOCKS: case BLOCKS:
msgQueue.receivedMessage(msg); msgQueue.receivedMessage(msg);
@ -146,7 +146,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
break; break;
case NEW_BLOCK: case NEW_BLOCK:
msgQueue.receivedMessage(msg); msgQueue.receivedMessage(msg);
procesNewBlock((NewBlockMessage)msg); procesNewBlock((NewBlockMessage) msg);
default: default:
break; break;
} }
@ -157,7 +157,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
Set<Transaction> txSet = msg.getTransactions(); Set<Transaction> txSet = msg.getTransactions();
worldManager.addPendingTransactions(txSet); worldManager.addPendingTransactions(txSet);
for (Transaction tx : txSet){ for (Transaction tx : txSet) {
worldManager.getWallet().addTransaction(tx); worldManager.getWallet().addTransaction(tx);
} }
} }
@ -210,11 +210,11 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
BigInteger peerTotalDifficulty = new BigInteger(1, msg.getTotalDifficulty()); BigInteger peerTotalDifficulty = new BigInteger(1, msg.getTotalDifficulty());
BigInteger highestKnownTotalDifficulty = blockchain.getTotalDifficulty(); BigInteger highestKnownTotalDifficulty = blockchain.getTotalDifficulty();
boolean synced= boolean synced =
FastByteComparisons.compareTo(msg.getBestHash(), 0, 32, blockchain.getBestBlockHash(), 0, 32) == 0; FastByteComparisons.compareTo(msg.getBestHash(), 0, 32, blockchain.getBestBlockHash(), 0, 32) == 0;
if ( !synced && (highestKnownTotalDifficulty == null || if (!synced && (highestKnownTotalDifficulty == null ||
peerTotalDifficulty.compareTo(highestKnownTotalDifficulty) > 0)) { peerTotalDifficulty.compareTo(highestKnownTotalDifficulty) > 0)) {
logger.info(" Their chain is better: total difficulty : {} vs {}", logger.info(" Their chain is better: total difficulty : {} vs {}",
peerTotalDifficulty.toString(), peerTotalDifficulty.toString(),
@ -225,7 +225,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
chainQueue.setBestHash(msg.getBestHash()); chainQueue.setBestHash(msg.getBestHash());
syncStatus = SyncSatus.HASH_RETRIEVING; syncStatus = SyncSatus.HASH_RETRIEVING;
sendGetBlockHashes(); sendGetBlockHashes();
} else{ } else {
logger.info("The peer sync process fully complete"); logger.info("The peer sync process fully complete");
syncStatus = SyncSatus.SYNC_DONE; syncStatus = SyncSatus.SYNC_DONE;
} }
@ -249,10 +249,9 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
byte[] foundHash, latestHash = blockchain.getBestBlockHash(); byte[] foundHash, latestHash = blockchain.getBestBlockHash();
while (hashIterator.hasNext()) { while (hashIterator.hasNext()) {
foundHash = hashIterator.next(); 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 chainQueue.addHash(foundHash); // store unknown hashes in queue until known hash is found
} } else {
else {
logger.trace("Catch up with the hashes until: {[]}", foundHash); logger.trace("Catch up with the hashes until: {[]}", foundHash);
// if known hash is found, ignore the rest // if known hash is found, ignore the rest
@ -270,10 +269,10 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
List<Block> blockList = blocksMessage.getBlocks(); List<Block> blockList = blocksMessage.getBlocks();
if (!blockList.isEmpty()) if (!blockList.isEmpty())
lastBlock = blockList.get(blockList.size()-1); lastBlock = blockList.get(blockList.size() - 1);
// check if you got less blocks than you asked // 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) for (int i = 0; i < blockList.size(); ++i)
sentHashes.remove(0); sentHashes.remove(0);
@ -287,14 +286,14 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
syncStatus = SyncSatus.SYNC_DONE; syncStatus = SyncSatus.SYNC_DONE;
blockchain.getQueue().addBlocks(blockList); blockchain.getQueue().addBlocks(blockList);
blockchain.getQueue().logHashQueueSize(); blockchain.getQueue().logHashQueueSize();
} else{ } else {
if (blockList.isEmpty()) return; if (blockList.isEmpty()) return;
blockchain.getQueue().addBlocks(blockList); blockchain.getQueue().addBlocks(blockList);
blockchain.getQueue().logHashQueueSize(); blockchain.getQueue().logHashQueueSize();
sendGetBlocks(); sendGetBlocks();
} }
for (Block block : blockList){ for (Block block : blockList) {
totalDifficulty.add(block.getCumulativeDifficulty()); totalDifficulty.add(block.getCumulativeDifficulty());
} }
} }
@ -302,9 +301,10 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
/** /**
* Processing NEW_BLOCK announce message * Processing NEW_BLOCK announce message
*
* @param newBlockMessage - new block message * @param newBlockMessage - new block message
*/ */
public void procesNewBlock(NewBlockMessage newBlockMessage){ public void procesNewBlock(NewBlockMessage newBlockMessage) {
Block newBlock = newBlockMessage.getBlock(); Block newBlock = newBlockMessage.getBlock();
this.lastBlock = newBlock; 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 // 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; // 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: [{}]", logger.debug("Sync status BLOCK_RETREIVING add to the end of hash list: block.index: [{}]",
newBlock.getNumber()); newBlock.getNumber());
blockchain.getQueue().addNewBlockHash(newBlock.getHash()); blockchain.getQueue().addNewBlockHash(newBlock.getHash());
@ -338,7 +338,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
totalDifficulty = new BigInteger(1, newBlockMessage.getDifficulty()); totalDifficulty = new BigInteger(1, newBlockMessage.getDifficulty());
} }
private void sendStatus(){ private void sendStatus() {
byte protocolVersion = EthHandler.VERSION, networkId = EthHandler.NETWORK_ID; byte protocolVersion = EthHandler.VERSION, networkId = EthHandler.NETWORK_ID;
BigInteger totalDifficulty = blockchain.getTotalDifficulty(); BigInteger totalDifficulty = blockchain.getTotalDifficulty();
byte[] bestHash = blockchain.getBestBlockHash(); byte[] bestHash = blockchain.getBestBlockHash();
@ -357,7 +357,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
msgQueue.sendMessage(msg); msgQueue.sendMessage(msg);
} }
public void sendNewBlock(Block block){ public void sendNewBlock(Block block) {
NewBlockMessage msg = new NewBlockMessage(block, block.getDifficulty()); NewBlockMessage msg = new NewBlockMessage(block, block.getDifficulty());
msgQueue.sendMessage(msg); msgQueue.sendMessage(msg);
} }
@ -375,7 +375,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
// Parallel download blocks based on hashQueue // Parallel download blocks based on hashQueue
private void sendGetBlocks() { private void sendGetBlocks() {
BlockQueue queue = blockchain.getQueue(); BlockQueue queue = blockchain.getQueue();
if (queue.size() > CONFIG.maxBlocksQueued()){ if (queue.size() > CONFIG.maxBlocksQueued()) {
logger.info("postpone asking for blocks: queue: {}", queue.size()); logger.info("postpone asking for blocks: queue: {}", queue.size());
getBlocksTimer.schedule(new TimerTask() { getBlocksTimer.schedule(new TimerTask() {
@ -420,8 +420,8 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
List<byte[]> hashes = msg.getBlockHashes(); List<byte[]> hashes = msg.getBlockHashes();
Vector<Block> blocks = new Vector<>(); Vector<Block> blocks = new Vector<>();
for (byte[] hash : hashes){ for (byte[] hash : hashes) {
Block block = blockchain.getBlockByHash(hash); Block block = blockchain.getBlockByHash(hash);
blocks.add(block); blocks.add(block);
} }
@ -468,37 +468,37 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
stopGetTxTimer(); stopGetTxTimer();
} }
public void setSyncStatus(SyncSatus syncStatus){ public void setSyncStatus(SyncSatus syncStatus) {
this.syncStatus = syncStatus; this.syncStatus = syncStatus;
} }
public SyncSatus getSyncStatus(){ public SyncSatus getSyncStatus() {
return syncStatus; return syncStatus;
} }
public void setPeerId(String peerId){ public void setPeerId(String peerId) {
this.peerId = peerId; this.peerId = peerId;
} }
public enum SyncSatus{ public enum SyncSatus {
INIT, INIT,
HASH_RETRIEVING, HASH_RETRIEVING,
BLOCK_RETRIEVING, BLOCK_RETRIEVING,
SYNC_DONE; SYNC_DONE;
} }
public void setBestHash(byte[] hash){ public void setBestHash(byte[] hash) {
blockchain.getQueue().addHash(hash); blockchain.getQueue().addHash(hash);
} }
public void doSync(){ public void doSync() {
logger.info("Sync force activated"); logger.info("Sync force activated");
syncStatus = SyncSatus.HASH_RETRIEVING; syncStatus = SyncSatus.HASH_RETRIEVING;
setBestHash(lastBlock.getHash()); setBestHash(lastBlock.getHash());
sendGetBlockHashes(); sendGetBlockHashes();
} }
public StatusMessage getHandshakeStatusMessage(){ public StatusMessage getHandshakeStatusMessage() {
return handshakeStatusMessage; return handshakeStatusMessage;
} }

View File

@ -5,7 +5,8 @@ import org.ethereum.net.message.Message;
public abstract class EthMessage extends Message { public abstract class EthMessage extends Message {
public EthMessage() {} public EthMessage() {
}
public EthMessage(byte[] encoded) { public EthMessage(byte[] encoded) {
super(encoded); super(encoded);

View File

@ -15,50 +15,65 @@ public enum EthMessageCodes {
/* Ethereum protocol */ /* 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 * 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), 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), 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 * 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) * 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), 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, * Requests a BlockHashes message of at most maxBlocks entries,
* of block hashes from the blockchain, starting at the parent of block hash. * of block hashes from the blockchain, starting at the parent of block hash.
* Does not require the peer to give maxBlocks hashes - * Does not require the peer to give maxBlocks hashes -
* they could give somewhat fewer. */ * they could give somewhat fewer.
*/
GET_BLOCK_HASHES(0x03), 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 * 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), 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> * 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 * <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), 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. * Specify (a) block(s) that the peer should know about.
* The items in the list (following the first item, 0x13) * 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), BLOCKS(0x06),
/** /**
* [+0x07 [blockHeader, transactionList, uncleList], totalDifficulty] <br> * [+0x07 [blockHeader, transactionList, uncleList], totalDifficulty] <br>
* Specify a single block that the peer should know about. The composite item * 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 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), NEW_BLOCK(0x07),
/** /**
@ -70,6 +85,7 @@ public enum EthMessageCodes {
private int cmd; private int cmd;
private static final Map<Integer, EthMessageCodes> intToTypeMap = new HashMap<>(); private static final Map<Integer, EthMessageCodes> intToTypeMap = new HashMap<>();
static { static {
for (EthMessageCodes type : EthMessageCodes.values()) { for (EthMessageCodes type : EthMessageCodes.values()) {
intToTypeMap.put(type.cmd, type); intToTypeMap.put(type.cmd, type);
@ -85,14 +101,15 @@ public enum EthMessageCodes {
return type; return type;
} }
public static boolean inRange(byte code){ public static boolean inRange(byte code) {
return code >= STATUS.asByte() && code <= PACKET_COUNT.asByte(); return code >= STATUS.asByte() && code <= PACKET_COUNT.asByte();
} }
public static void setOffset(byte offset){ public static void setOffset(byte offset) {
EthMessageCodes.OFFSET = offset; EthMessageCodes.OFFSET = offset;
} }
public byte asByte() { public byte asByte() {
return (byte) (cmd + OFFSET); return (byte) (cmd + OFFSET);
} }
} }

View File

@ -14,11 +14,15 @@ import org.spongycastle.util.encoders.Hex;
*/ */
public class GetBlockHashesMessage extends EthMessage { 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; 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; private int maxBlocks;
public GetBlockHashesMessage(byte[] encoded) { public GetBlockHashesMessage(byte[] encoded) {
@ -51,7 +55,7 @@ public class GetBlockHashesMessage extends EthMessage {
@Override @Override
public byte[] getEncoded() { public byte[] getEncoded() {
if(encoded == null) encode(); if (encoded == null) encode();
return encoded; return encoded;
} }
@ -72,7 +76,7 @@ public class GetBlockHashesMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.GET_BLOCK_HASHES; return EthMessageCodes.GET_BLOCK_HASHES;
} }

View File

@ -17,7 +17,9 @@ import static org.ethereum.net.eth.EthMessageCodes.GET_BLOCKS;
*/ */
public class GetBlocksMessage extends EthMessage { 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; private List<byte[]> blockHashes;
public GetBlocksMessage(byte[] encoded) { public GetBlocksMessage(byte[] encoded) {
@ -67,7 +69,7 @@ public class GetBlocksMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.GET_BLOCKS; return EthMessageCodes.GET_BLOCKS;
} }

View File

@ -11,7 +11,9 @@ import org.spongycastle.util.encoders.Hex;
*/ */
public class GetTransactionsMessage extends EthMessage { 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"); private final static byte[] FIXED_PAYLOAD = Hex.decode("C116");
public byte[] getEncoded() { public byte[] getEncoded() {
@ -24,7 +26,7 @@ public class GetTransactionsMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.GET_TRANSACTIONS; return EthMessageCodes.GET_TRANSACTIONS;
} }

View File

@ -19,16 +19,16 @@ public class NewBlockMessage extends EthMessage {
super(encoded); super(encoded);
} }
public NewBlockMessage(Block block, byte[] difficulty){ public NewBlockMessage(Block block, byte[] difficulty) {
this.block = block; this.block = block;
this.difficulty = difficulty; this.difficulty = difficulty;
encode(); encode();
} }
private void encode(){ private void encode() {
byte[] command = RLP.encodeByte( this.getCommand().asByte()); byte[] command = RLP.encodeByte(this.getCommand().asByte());
byte[] block = this.block.getEncoded(); byte[] block = this.block.getEncoded();
byte[] diff = RLP.encodeElement(this.difficulty); byte[] diff = RLP.encodeElement(this.difficulty);
this.encoded = RLP.encodeList(command, block, diff); this.encoded = RLP.encodeList(command, block, diff);
parsed = true; parsed = true;
@ -39,17 +39,17 @@ public class NewBlockMessage extends EthMessage {
RLPList blockRLP = ((RLPList) paramsList.get(1)); RLPList blockRLP = ((RLPList) paramsList.get(1));
block = new Block(blockRLP.getRLPData()); block = new Block(blockRLP.getRLPData());
difficulty = paramsList.get(2).getRLPData(); difficulty = paramsList.get(2).getRLPData();
parsed = true; parsed = true;
} }
public Block getBlock(){ public Block getBlock() {
if (!parsed) parse(); if (!parsed) parse();
return block; return block;
} }
public byte[] getDifficulty(){ public byte[] getDifficulty() {
if (!parsed) parse(); if (!parsed) parse();
return difficulty; return difficulty;
} }
@ -60,7 +60,7 @@ public class NewBlockMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.NEW_BLOCK; return EthMessageCodes.NEW_BLOCK;
} }

View File

@ -5,7 +5,6 @@ import org.ethereum.util.RLP;
/** /**
* Wrapper around an Ethereum Ping message on the network * Wrapper around an Ethereum Ping message on the network
*
*/ */
public class PacketCountMessage extends EthMessage { public class PacketCountMessage extends EthMessage {
@ -23,7 +22,7 @@ public class PacketCountMessage extends EthMessage {
} }
private void encode() { 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 @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.PACKET_COUNT; return EthMessageCodes.PACKET_COUNT;
} }

View File

@ -18,11 +18,17 @@ public class StatusMessage extends EthMessage {
private byte protocolVersion; private byte protocolVersion;
private byte networkId; 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; 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; private byte[] bestHash;
/** The hash of the Genesis block */ /**
* The hash of the Genesis block
*/
private byte[] genesisHash; private byte[] genesisHash;
public StatusMessage(byte[] encoded) { public StatusMessage(byte[] encoded) {
@ -30,7 +36,7 @@ public class StatusMessage extends EthMessage {
} }
public StatusMessage(byte protocolVersion, byte networkId, public StatusMessage(byte protocolVersion, byte networkId,
byte[] totalDifficulty, byte[] bestHash, byte[] genesisHash) { byte[] totalDifficulty, byte[] bestHash, byte[] genesisHash) {
this.protocolVersion = protocolVersion; this.protocolVersion = protocolVersion;
this.networkId = networkId; this.networkId = networkId;
this.totalDifficulty = totalDifficulty; this.totalDifficulty = totalDifficulty;
@ -42,23 +48,23 @@ public class StatusMessage extends EthMessage {
private void parse() { private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0); RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
this.protocolVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0]; this.protocolVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0];
byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getRLPData(); byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0]; this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0];
this.totalDifficulty = ((RLPItem) paramsList.get(3)).getRLPData(); this.totalDifficulty = ((RLPItem) paramsList.get(3)).getRLPData();
this.bestHash = ((RLPItem) paramsList.get(4)).getRLPData(); this.bestHash = ((RLPItem) paramsList.get(4)).getRLPData();
this.genesisHash = ((RLPItem) paramsList.get(5)).getRLPData(); this.genesisHash = ((RLPItem) paramsList.get(5)).getRLPData();
parsed = true; parsed = true;
} }
private void encode() { private void encode() {
byte[] command = RLP.encodeByte(STATUS.asByte()); byte[] command = RLP.encodeByte(STATUS.asByte());
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion); byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
byte[] networkId = RLP.encodeByte(this.networkId); byte[] networkId = RLP.encodeByte(this.networkId);
byte[] totalDifficulty = RLP.encodeElement(this.totalDifficulty); byte[] totalDifficulty = RLP.encodeElement(this.totalDifficulty);
byte[] bestHash = RLP.encodeElement(this.bestHash); byte[] bestHash = RLP.encodeElement(this.bestHash);
byte[] genesisHash = RLP.encodeElement(this.genesisHash); byte[] genesisHash = RLP.encodeElement(this.genesisHash);
this.encoded = RLP.encodeList(command, protocolVersion, networkId, this.encoded = RLP.encodeList(command, protocolVersion, networkId,
totalDifficulty, bestHash, genesisHash); totalDifficulty, bestHash, genesisHash);
@ -101,7 +107,7 @@ public class StatusMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return STATUS; return STATUS;
} }

View File

@ -72,7 +72,7 @@ public class TransactionsMessage extends EthMessage {
} }
@Override @Override
public EthMessageCodes getCommand(){ public EthMessageCodes getCommand() {
return EthMessageCodes.TRANSACTIONS; return EthMessageCodes.TRANSACTIONS;
} }
@ -82,11 +82,11 @@ public class TransactionsMessage extends EthMessage {
} }
public String toString() { public String toString() {
if(!parsed) parse(); if (!parsed) parse();
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (Transaction transaction : transactions) for (Transaction transaction : transactions)
sb.append("\n ").append(transaction); sb.append("\n ").append(transaction);
return "[" + this.getCommand().name() + " num:" return "[" + this.getCommand().name() + " num:"
+ transactions.size() + " " + sb.toString() + "]"; + transactions.size() + " " + sb.toString() + "]";
} }
} }

View File

@ -9,10 +9,11 @@ package org.ethereum.net.message;
public abstract class Message { public abstract class Message {
protected boolean parsed; protected boolean parsed;
protected byte[] encoded; protected byte[] encoded;
protected byte code; protected byte code;
public Message() {} public Message() {
}
public Message(byte[] encoded) { public Message(byte[] encoded) {
this.encoded = encoded; this.encoded = encoded;

View File

@ -13,7 +13,7 @@ public class MessageFactory {
public static Message createMessage(byte[] encoded) { public static Message createMessage(byte[] encoded) {
byte code = RLP.getCommandCode(encoded); byte code = RLP.getCommandCode(encoded);
if (P2pMessageCodes.inRange(code)){ if (P2pMessageCodes.inRange(code)) {
P2pMessageCodes receivedCommand = P2pMessageCodes.fromByte(code); P2pMessageCodes receivedCommand = P2pMessageCodes.fromByte(code);
switch (receivedCommand) { switch (receivedCommand) {

View File

@ -9,39 +9,60 @@ import java.util.Map;
*/ */
public enum ReasonCode { public enum ReasonCode {
/** [0x00] Disconnect request by other peer */ /**
* [0x00] Disconnect request by other peer
*/
REQUESTED(0x00), REQUESTED(0x00),
/** [0x01] */ /**
* [0x01]
*/
TCP_ERROR(0x01), TCP_ERROR(0x01),
/** [0x02] Packets can not be parsed */ /**
* [0x02] Packets can not be parsed
*/
BAD_PROTOCOL(0x02), 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), USELESS_PEER(0x03),
/** [0x04] Already too many connections with other peers */ /**
* [0x04] Already too many connections with other peers
*/
TOO_MANY_PEERS(0x04), 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), 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), INCOMPATIBLE_PROTOCOL(0x06),
/** [0x07] Peer identifies itself with the wrong networkId */ /**
* [0x07] Peer identifies itself with the wrong networkId
*/
INCOMPATIBLE_NETWORK(0x07), INCOMPATIBLE_NETWORK(0x07),
/** [0x08] Peer quit voluntarily */ /**
* [0x08] Peer quit voluntarily
*/
PEER_QUITING(0x08), PEER_QUITING(0x08),
/** [0xFF] Reason not specified */ /**
* [0xFF] Reason not specified
*/
UNKNOWN(0xFF); UNKNOWN(0xFF);
private int reason; private int reason;
private static final Map<Integer, ReasonCode> intToTypeMap = new HashMap<>(); private static final Map<Integer, ReasonCode> intToTypeMap = new HashMap<>();
static { static {
for (ReasonCode type : ReasonCode.values()) { for (ReasonCode type : ReasonCode.values()) {
intToTypeMap.put(type.reason, type); intToTypeMap.put(type.reason, type);

View File

@ -2,7 +2,8 @@ package org.ethereum.net.message;
public abstract class ShhMessage extends Message { public abstract class ShhMessage extends Message {
public ShhMessage() {} public ShhMessage() {
}
public ShhMessage(byte[] encoded) { public ShhMessage(byte[] encoded) {
super(encoded); super(encoded);

View File

@ -27,10 +27,10 @@ public class StaticMessages {
public static final String PEER_ID = Hex.toHexString(HashUtil.randomPeerId()); public static final String PEER_ID = Hex.toHexString(HashUtil.randomPeerId());
public final static PingMessage PING_MESSAGE = new PingMessage(); public final static PingMessage PING_MESSAGE = new PingMessage();
public final static PongMessage PONG_MESSAGE = new PongMessage(); public final static PongMessage PONG_MESSAGE = new PongMessage();
public final static HelloMessage HELLO_MESSAGE = generateHelloMessage(); public final static HelloMessage HELLO_MESSAGE = generateHelloMessage();
public final static GetPeersMessage GET_PEERS_MESSAGE = new GetPeersMessage(); public final static GetPeersMessage GET_PEERS_MESSAGE = new GetPeersMessage();
public final static GetTransactionsMessage GET_TRANSACTIONS_MESSAGE = new GetTransactionsMessage(); public final static GetTransactionsMessage GET_TRANSACTIONS_MESSAGE = new GetTransactionsMessage();
public static final byte[] SYNC_TOKEN = Hex.decode("22400891"); public static final byte[] SYNC_TOKEN = Hex.decode("22400891");

View File

@ -52,7 +52,7 @@ public class DisconnectMessage extends P2pMessage {
} }
@Override @Override
public P2pMessageCodes getCommand(){ public P2pMessageCodes getCommand() {
return P2pMessageCodes.DISCONNECT; return P2pMessageCodes.DISCONNECT;
} }

View File

@ -9,7 +9,9 @@ import org.spongycastle.util.encoders.Hex;
*/ */
public class GetPeersMessage extends P2pMessage { 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"); private final static byte[] FIXED_PAYLOAD = Hex.decode("C104");
@Override @Override
@ -18,7 +20,7 @@ public class GetPeersMessage extends P2pMessage {
} }
@Override @Override
public P2pMessageCodes getCommand(){ public P2pMessageCodes getCommand() {
return P2pMessageCodes.GET_PEERS; return P2pMessageCodes.GET_PEERS;
} }

View File

@ -20,16 +20,26 @@ import java.util.List;
*/ */
public class HelloMessage extends P2pMessage { public class HelloMessage extends P2pMessage {
/** The implemented version of the P2P protocol. */ /**
* The implemented version of the P2P protocol.
*/
private byte p2pVersion; private byte p2pVersion;
/** The underlying client. A user-readable string. */ /**
* The underlying client. A user-readable string.
*/
private String clientId; 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; 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; private int listenPort;
/** The identity and public key of the peer */ /**
* The identity and public key of the peer
*/
private String peerId; private String peerId;
public HelloMessage(byte[] encoded) { public HelloMessage(byte[] encoded) {
@ -62,8 +72,8 @@ public class HelloMessage extends P2pMessage {
this.capabilities = new ArrayList<>(); this.capabilities = new ArrayList<>();
for (int i = 0; i < capabilityList.size(); i++) { for (int i = 0; i < capabilityList.size(); i++) {
RLPElement capId = ((RLPList)capabilityList.get(i)).get(0); RLPElement capId = ((RLPList) capabilityList.get(i)).get(0);
RLPElement capVersion = ((RLPList)capabilityList.get(i)).get(1); RLPElement capVersion = ((RLPList) capabilityList.get(i)).get(1);
String name = new String(capId.getRLPData()); String name = new String(capId.getRLPData());
byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0]; byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0];
@ -89,7 +99,7 @@ public class HelloMessage extends P2pMessage {
Capability capability = this.capabilities.get(i); Capability capability = this.capabilities.get(i);
capabilities[i] = RLP.encodeList( capabilities[i] = RLP.encodeList(
RLP.encodeElement(capability.getName().getBytes()), RLP.encodeElement(capability.getName().getBytes()),
RLP.encodeElement(new byte[] {capability.getVersion() })); RLP.encodeElement(new byte[]{capability.getVersion()}));
} }
byte[] capabilityList = RLP.encodeList(capabilities); byte[] capabilityList = RLP.encodeList(capabilities);
byte[] peerPort = RLP.encodeInt(this.listenPort); byte[] peerPort = RLP.encodeInt(this.listenPort);
@ -131,7 +141,7 @@ public class HelloMessage extends P2pMessage {
} }
@Override @Override
public P2pMessageCodes getCommand(){ public P2pMessageCodes getCommand() {
return P2pMessageCodes.HELLO; return P2pMessageCodes.HELLO;
} }

View File

@ -92,7 +92,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
startTimers(); startTimers();
} }
public void activate(){ public void activate() {
// logger.info("Incoming connection from: {}", ch.remoteAddress().toString()); // logger.info("Incoming connection from: {}", ch.remoteAddress().toString());
@ -100,7 +100,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
worldManager.getListener().trace("P2P protocol activated"); worldManager.getListener().trace("P2P protocol activated");
} }
public boolean isActive(){ public boolean isActive() {
return active; return active;
} }
@ -112,7 +112,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
if (P2pMessageCodes.inRange(msg.getCommand().asByte())) if (P2pMessageCodes.inRange(msg.getCommand().asByte()))
logger.info("P2PHandler invoke: [{}]", msg.getCommand()); 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()) { switch (msg.getCommand()) {
case HELLO: case HELLO:
@ -139,7 +139,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
processPeers(ctx, (PeersMessage) msg); processPeers(ctx, (PeersMessage) msg);
if (peerDiscoveryMode && if (peerDiscoveryMode &&
!handshakeHelloMessage.getCapabilities().contains(Capability.ETH)){ !handshakeHelloMessage.getCapabilities().contains(Capability.ETH)) {
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.REQUESTED)); msgQueue.sendMessage(new DisconnectMessage(ReasonCode.REQUESTED));
killTimers(); killTimers();
ctx.close().sync(); ctx.close().sync();
@ -172,21 +172,21 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
worldManager.getPeerDiscovery().addPeers(peersMessage.getPeers()); worldManager.getPeerDiscovery().addPeers(peersMessage.getPeers());
} }
private void sendGetPeers(){ private void sendGetPeers() {
msgQueue.sendMessage( StaticMessages.GET_PEERS_MESSAGE ); msgQueue.sendMessage(StaticMessages.GET_PEERS_MESSAGE);
} }
private void sendPeers() { private void sendPeers() {
Set<PeerInfo> peers = worldManager.getPeerDiscovery().getPeers(); 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"); logger.info("No new peers discovered don't answer for GetPeers");
return; return;
} }
Set<Peer> peerSet = new HashSet<>(); Set<Peer> peerSet = new HashSet<>();
for (PeerInfo peer : peers){ for (PeerInfo peer : peers) {
new Peer(peer.getAddress(), peer.getPort(), peer.getPeerId()); new Peer(peer.getAddress(), peer.getPort(), peer.getPeerId());
} }
@ -205,20 +205,19 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
List<Capability> capInCommon = new ArrayList<>(); List<Capability> capInCommon = new ArrayList<>();
for (Capability capability : msg.getCapabilities()) { for (Capability capability : msg.getCapabilities()) {
if (HELLO_MESSAGE.getCapabilities().contains(capability)) { if (HELLO_MESSAGE.getCapabilities().contains(capability)) {
if (capability.getName().equals(Capability.ETH)){ if (capability.getName().equals(Capability.ETH)) {
// Activate EthHandler for this peer // Activate EthHandler for this peer
EthHandler ethHandler = EthHandler ethHandler =
(EthHandler)ctx.pipeline().get(Capability.ETH); (EthHandler) ctx.pipeline().get(Capability.ETH);
ethHandler.setPeerId(msg.getPeerId()); ethHandler.setPeerId(msg.getPeerId());
ethHandler.activate(); ethHandler.activate();
} } else if (capability.getName().equals(Capability.SHH)) {
else if (capability.getName().equals(Capability.SHH)){
// Activate ShhHandler for this peer // Activate ShhHandler for this peer
ShhHandler shhHandler = ShhHandler shhHandler =
(ShhHandler)ctx.pipeline().get(Capability.SHH); (ShhHandler) ctx.pipeline().get(Capability.SHH);
shhHandler.activate(); shhHandler.activate();
} }
capInCommon.add(capability); capInCommon.add(capability);
@ -239,15 +238,16 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
/** /**
* submit transaction to the network * submit transaction to the network
*
* @param tx - fresh transaction object * @param tx - fresh transaction object
*/ */
public void sendTransaction(Transaction tx ){ public void sendTransaction(Transaction tx) {
TransactionsMessage msg = new TransactionsMessage(tx); TransactionsMessage msg = new TransactionsMessage(tx);
msgQueue.sendMessage(msg); msgQueue.sendMessage(msg);
} }
public void sendNewBlock(Block block ){ public void sendNewBlock(Block block) {
NewBlockMessage msg = new NewBlockMessage(block, block.getDifficulty()); NewBlockMessage msg = new NewBlockMessage(block, block.getDifficulty());
msgQueue.sendMessage(msg); msgQueue.sendMessage(msg);
@ -296,7 +296,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
*/ */
} }
public void killTimers(){ public void killTimers() {
timer.cancel(); timer.cancel();
timer.purge(); timer.purge();
msgQueue.close(); msgQueue.close();

View File

@ -5,7 +5,8 @@ import org.ethereum.net.p2p.P2pMessageCodes;
public abstract class P2pMessage extends Message { public abstract class P2pMessage extends Message {
public P2pMessage() {} public P2pMessage() {
}
public P2pMessage(byte[] encoded) { public P2pMessage(byte[] encoded) {
super(encoded); super(encoded);

View File

@ -8,6 +8,7 @@ import java.util.Map;
* <br> * <br>
* The codes for these commands are the first byte in every packet. * The codes for these commands are the first byte in every packet.
* ÐΞV * ÐΞV
*
* @see <a href="https://github.com/ethereum/wiki/wiki/%C3%90%CE%9EVp2p-Wire-Protocol"> * @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> * https://github.com/ethereum/wiki/wiki/ÐΞVp2p-Wire-Protocol</a>
*/ */
@ -15,33 +16,45 @@ public enum P2pMessageCodes {
/* P2P protocol */ /* 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. * 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), 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, * if received, a peer should disconnect immediately. When sending,
* well-behaved hosts give their peers a fighting chance (read: wait 2 seconds) * 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), 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), PING(0x02),
/** [0x03] <br>Reply to peer's Ping packet. */ /**
* [0x03] <br>Reply to peer's Ping packet.
*/
PONG(0x03), 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), 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' * 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. * that should be interpreted as the IP address A.B.C.D.
* Port is a 2-byte array that should be interpreted as a * 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 * 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), PEERS(0x05),
@ -54,6 +67,7 @@ public enum P2pMessageCodes {
private int cmd; private int cmd;
private static final Map<Integer, P2pMessageCodes> intToTypeMap = new HashMap<>(); private static final Map<Integer, P2pMessageCodes> intToTypeMap = new HashMap<>();
static { static {
for (P2pMessageCodes type : P2pMessageCodes.values()) { for (P2pMessageCodes type : P2pMessageCodes.values()) {
intToTypeMap.put(type.cmd, type); intToTypeMap.put(type.cmd, type);
@ -69,7 +83,7 @@ public enum P2pMessageCodes {
return type; return type;
} }
public static boolean inRange(byte code){ public static boolean inRange(byte code) {
if (code >= HELLO.asByte() && code <= USER.asByte()) if (code >= HELLO.asByte() && code <= USER.asByte())
return true; return true;

View File

@ -47,7 +47,7 @@ public class Peer {
byte[] port = RLP.encodeInt(this.port); byte[] port = RLP.encodeInt(this.port);
byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId)); byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId));
byte[][] encodedCaps = new byte[this.capabilities.size()][]; 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.encodeString(this.capabilities.get(i).getName());
encodedCaps[i] = RLP.encodeByte(this.capabilities.get(i).getVersion()); encodedCaps[i] = RLP.encodeByte(this.capabilities.get(i).getVersion());
} }

View File

@ -48,7 +48,7 @@ public class PeersMessage extends P2pMessage {
int peerPort = ByteUtil.byteArrayToInt(portBytes); int peerPort = ByteUtil.byteArrayToInt(portBytes);
InetAddress address = InetAddress.getByAddress(ipBytes); 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); Peer peer = new Peer(address, peerPort, peerId);
peers.add(peer); peers.add(peer);
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
@ -80,7 +80,7 @@ public class PeersMessage extends P2pMessage {
} }
@Override @Override
public P2pMessageCodes getCommand(){ public P2pMessageCodes getCommand() {
return P2pMessageCodes.PEERS; return P2pMessageCodes.PEERS;
} }

View File

@ -9,7 +9,9 @@ import org.spongycastle.util.encoders.Hex;
*/ */
public class PingMessage extends P2pMessage { 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"); private static byte[] FIXED_PAYLOAD = Hex.decode("C102");
public byte[] getEncoded() { public byte[] getEncoded() {
@ -22,7 +24,7 @@ public class PingMessage extends P2pMessage {
} }
@Override @Override
public P2pMessageCodes getCommand(){ public P2pMessageCodes getCommand() {
return P2pMessageCodes.PING; return P2pMessageCodes.PING;
} }

View File

@ -10,7 +10,9 @@ import org.spongycastle.util.encoders.Hex;
*/ */
public class PongMessage extends P2pMessage { 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"); private static byte[] FIXED_PAYLOAD = Hex.decode("C103");
@Override @Override
@ -24,7 +26,7 @@ public class PongMessage extends P2pMessage {
} }
@Override @Override
public P2pMessageCodes getCommand(){ public P2pMessageCodes getCommand() {
return P2pMessageCodes.PONG; return P2pMessageCodes.PONG;
} }

View File

@ -30,6 +30,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
/** /**
* This class creates the connection to an remote address using the Netty framework * This class creates the connection to an remote address using the Netty framework
*
* @see <a href="http://netty.io">http://netty.io</a> * @see <a href="http://netty.io">http://netty.io</a>
*/ */
@Component @Component
@ -93,7 +94,7 @@ public class DiscoveryChannel {
b.handler( b.handler(
new ChannelInitializer<NioSocketChannel>(){ new ChannelInitializer<NioSocketChannel>() {
@Override @Override
protected void initChannel(NioSocketChannel ch) throws Exception { protected void initChannel(NioSocketChannel ch) throws Exception {
@ -128,7 +129,7 @@ public class DiscoveryChannel {
} finally { } finally {
workerGroup.shutdownGracefully(); workerGroup.shutdownGracefully();
if (!peerDiscoveryMode){ if (!peerDiscoveryMode) {
// EthereumListener listener = WorldManager.getInstance().getListener(); // EthereumListener listener = WorldManager.getInstance().getListener();
// listener.onPeerDisconnect(host, port); // listener.onPeerDisconnect(host, port);
} }
@ -136,12 +137,11 @@ public class DiscoveryChannel {
} }
} }
public HelloMessage getHelloHandshake(){ public HelloMessage getHelloHandshake() {
return p2pHandler.getHandshakeHelloMessage(); return p2pHandler.getHandshakeHelloMessage();
} }
public StatusMessage getStatusHandshake() public StatusMessage getStatusHandshake() {
{
return ethHandler.getHandshakeStatusMessage(); return ethHandler.getHandshakeStatusMessage();
} }
} }

View File

@ -93,7 +93,7 @@ public class PeerDiscovery {
for (final Peer newPeer : newPeers) { for (final Peer newPeer : newPeers) {
PeerInfo peerInfo = PeerInfo peerInfo =
new PeerInfo(newPeer.getAddress(), newPeer.getPort(), newPeer.getPeerId()); new PeerInfo(newPeer.getAddress(), newPeer.getPort(), newPeer.getPeerId());
if (started.get() && !peers.contains(peerInfo )){ if (started.get() && !peers.contains(peerInfo)) {
startWorker(peerInfo); startWorker(peerInfo);
} }
peers.add(peerInfo); peers.add(peerInfo);
@ -103,8 +103,8 @@ public class PeerDiscovery {
public void addPeers(Collection<PeerInfo> newPeers) { public void addPeers(Collection<PeerInfo> newPeers) {
synchronized (peers) { synchronized (peers) {
peers.addAll(newPeers); peers.addAll(newPeers);
} }
} }
private void startWorker(PeerInfo peerInfo) { private void startWorker(PeerInfo peerInfo) {
@ -115,12 +115,12 @@ public class PeerDiscovery {
executorPool.execute(workerThread); 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<>(); final List<PeerInfo> peers = new ArrayList<>();
for (String ip : ipList){ for (String ip : ipList) {
String[] addr = ip.trim().split(":"); String[] addr = ip.trim().split(":");
String ip_trim = addr[0]; String ip_trim = addr[0];
String port_trim = addr[1]; String port_trim = addr[1];

View File

@ -20,7 +20,7 @@ public class PeerInfo {
private String peerId; private String peerId;
private List<Capability> capabilities; private List<Capability> capabilities;
private HelloMessage handshakeHelloMessage; private HelloMessage handshakeHelloMessage;
private StatusMessage statusMessage; private StatusMessage statusMessage;
private transient boolean isOnline = false; private transient boolean isOnline = false;
@ -77,7 +77,7 @@ public class PeerInfo {
.append(" port=").append(getPort()) .append(" port=").append(getPort())
.append(" peerId=").append(getPeerId()).append("] \n") .append(" peerId=").append(getPeerId()).append("] \n")
.append(this.handshakeHelloMessage == null ? "" : handshakeHelloMessage + "\n") .append(this.handshakeHelloMessage == null ? "" : handshakeHelloMessage + "\n")
.append(this.statusMessage == null ? "" : statusMessage + "\n"); .append(this.statusMessage == null ? "" : statusMessage + "\n");
return sb.toString(); return sb.toString();
} }

View File

@ -30,7 +30,7 @@ public class WorkerThread implements Runnable {
public WorkerThread() { public WorkerThread() {
} }
public void init(PeerInfo peer, ThreadPoolExecutor poolExecutor){ public void init(PeerInfo peer, ThreadPoolExecutor poolExecutor) {
this.peerInfo = peer; this.peerInfo = peer;
this.poolExecutor = poolExecutor; this.poolExecutor = poolExecutor;
} }
@ -54,7 +54,7 @@ public class WorkerThread implements Runnable {
peerInfo.setOnline(true); peerInfo.setOnline(true);
peerInfo.setHandshakeHelloMessage(discoveryChannel.getHelloHandshake()); peerInfo.setHandshakeHelloMessage(discoveryChannel.getHelloHandshake());
peerInfo.setStatusMessage( discoveryChannel.getStatusHandshake() ); peerInfo.setStatusMessage(discoveryChannel.getStatusHandshake());
logger.info("Peer is online: [{}] ", peerInfo); 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 { try {
Thread.sleep(milliseconds); Thread.sleep(milliseconds);

View File

@ -52,7 +52,7 @@ public class Channel {
public Channel() { public Channel() {
} }
public void init(){ public void init() {
p2pHandler.setMsgQueue(msgQueue); p2pHandler.setMsgQueue(msgQueue);
ethHandler.setMsgQueue(msgQueue); ethHandler.setMsgQueue(msgQueue);
shhHandler.setMsgQueue(msgQueue); shhHandler.setMsgQueue(msgQueue);
@ -80,27 +80,27 @@ public class Channel {
return messageEncoder; return messageEncoder;
} }
public void sendTransaction(Transaction tx){ public void sendTransaction(Transaction tx) {
ethHandler.sendTransaction(tx); ethHandler.sendTransaction(tx);
} }
public void sendNewBlock(Block block){ public void sendNewBlock(Block block) {
// 1. check by best block send or not to send // 1. check by best block send or not to send
ethHandler.sendNewBlock(block); ethHandler.sendNewBlock(block);
} }
public boolean isSync(){ public boolean isSync() {
return ethHandler.getSyncStatus() == EthHandler.SyncSatus.SYNC_DONE; return ethHandler.getSyncStatus() == EthHandler.SyncSatus.SYNC_DONE;
} }
public BigInteger getTotalDifficulty(){ public BigInteger getTotalDifficulty() {
return ethHandler.getTotalDifficulty(); return ethHandler.getTotalDifficulty();
} }
public void ethSync(){ public void ethSync() {
ethHandler.doSync(); ethHandler.doSync();
} }

View File

@ -36,63 +36,63 @@ public class ChannelManager {
@PostConstruct @PostConstruct
public void init(){ public void init() {
scheduleChannelCollector(); scheduleChannelCollector();
} }
public void recvTransaction(){ public void recvTransaction() {
// ??? // ???
} }
public void recvBlock(){ // todo: public void recvBlock() { // todo:
// 1. Check in the cache if the hash exist // 1. Check in the cache if the hash exist
// 2. Exist: go and send it to the queue // 2. Exist: go and send it to the queue
} }
public void sendTransaction(Transaction tx){ public void sendTransaction(Transaction tx) {
for (Channel channel : channels){ for (Channel channel : channels) {
channel.sendTransaction(tx); channel.sendTransaction(tx);
} }
} }
public void sendNewBlock(Block block){ public void sendNewBlock(Block block) {
// 1. Go over all channels and send the block // 1. Go over all channels and send the block
for (Channel channel : channels){ for (Channel channel : channels) {
channel.sendNewBlock(block); channel.sendNewBlock(block);
} }
} }
public void addChannel(Channel channel){ public void addChannel(Channel channel) {
synchronized (channels){ synchronized (channels) {
channels.add(channel); channels.add(channel);
} }
} }
public boolean isAllSync(){ public boolean isAllSync() {
boolean result = true; boolean result = true;
for (Channel channel : channels){ for (Channel channel : channels) {
result &= channel.isSync(); result &= channel.isSync();
} }
return result; return result;
} }
public void scheduleChannelCollector(){ public void scheduleChannelCollector() {
inactivesCollector.scheduleAtFixedRate(new TimerTask() { inactivesCollector.scheduleAtFixedRate(new TimerTask() {
public void run() { public void run() {
Iterator<Channel> iter = channels.iterator(); Iterator<Channel> iter = channels.iterator();
while(iter.hasNext()){ while (iter.hasNext()) {
Channel channel = iter.next(); Channel channel = iter.next();
if(!channel.p2pHandler.isActive()){ if (!channel.p2pHandler.isActive()) {
iter.remove(); iter.remove();
logger.info("Channel removed: {}", channel.p2pHandler.getHandshakeHelloMessage()); logger.info("Channel removed: {}", channel.p2pHandler.getHandshakeHelloMessage());
} }
} }
if (channels.size() == 0){ if (channels.size() == 0) {
worldManager.getListener().onNoConnections(); worldManager.getListener().onNoConnections();
} }
} }
@ -102,10 +102,10 @@ public class ChannelManager {
public void ethSync() { public void ethSync() {
Channel bestChannel = channels.get(0); Channel bestChannel = channels.get(0);
for (Channel channel : channels){ for (Channel channel : channels) {
if (bestChannel.getTotalDifficulty(). if (bestChannel.getTotalDifficulty().
compareTo(channel.getTotalDifficulty()) < 0 ){ compareTo(channel.getTotalDifficulty()) < 0) {
bestChannel = channel; bestChannel = channel;
} }
} }

View File

@ -14,8 +14,6 @@ import org.springframework.stereotype.Component;
* Process the messages between peers with 'shh' capability on the network. * Process the messages between peers with 'shh' capability on the network.
* *
* Peers with 'shh' capability can send/receive: * Peers with 'shh' capability can send/receive:
*
*
*/ */
@Component @Component
@Scope("prototype") @Scope("prototype")
@ -31,7 +29,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
@Autowired @Autowired
WorldManager worldManager; WorldManager worldManager;
public ShhHandler(){ public ShhHandler() {
} }
public ShhHandler(MessageQueue msgQueue) { public ShhHandler(MessageQueue msgQueue) {
@ -46,7 +44,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
if (ShhMessageCodes.inRange(msg.getCommand().asByte())) if (ShhMessageCodes.inRange(msg.getCommand().asByte()))
logger.info("ShhHandler invoke: [{}]", msg.getCommand()); 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()) { switch (msg.getCommand()) {
case STATUS: case STATUS:
@ -77,7 +75,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
logger.debug("handlerRemoved: ... "); logger.debug("handlerRemoved: ... ");
} }
public void activate(){ public void activate() {
logger.info("SHH protocol activated"); logger.info("SHH protocol activated");
worldManager.getListener().trace("SHH protocol activated"); worldManager.getListener().trace("SHH protocol activated");
this.active = true; this.active = true;

View File

@ -4,7 +4,8 @@ import org.ethereum.net.message.Message;
public abstract class ShhMessage extends Message { public abstract class ShhMessage extends Message {
public ShhMessage() {} public ShhMessage() {
}
public ShhMessage(byte[] encoded) { public ShhMessage(byte[] encoded) {
super(encoded); super(encoded);

View File

@ -15,25 +15,36 @@ public enum ShhMessageCodes {
/* Whisper Protocol */ /* Whisper Protocol */
/** [+0x00] */ /**
* [+0x00]
*/
STATUS(0x00), STATUS(0x00),
/** [+0x01] */ /**
* [+0x01]
*/
MESSAGE(0x01), MESSAGE(0x01),
/** [+0x02] */ /**
* [+0x02]
*/
ADD_FILTER(0x02), ADD_FILTER(0x02),
/** [+0x03] */ /**
* [+0x03]
*/
REMOVE_FILTER(0x03), REMOVE_FILTER(0x03),
/** [+0x04] */ /**
* [+0x04]
*/
PACKET_COUNT(0x04); PACKET_COUNT(0x04);
static byte OFFSET = 0; static byte OFFSET = 0;
private int cmd; private int cmd;
private static final Map<Integer, ShhMessageCodes> intToTypeMap = new HashMap<>(); private static final Map<Integer, ShhMessageCodes> intToTypeMap = new HashMap<>();
static { static {
for (ShhMessageCodes type : ShhMessageCodes.values()) { for (ShhMessageCodes type : ShhMessageCodes.values()) {
intToTypeMap.put(type.cmd, type); intToTypeMap.put(type.cmd, type);
@ -49,11 +60,11 @@ public enum ShhMessageCodes {
return type; return type;
} }
public static void setOffset(byte offset){ public static void setOffset(byte offset) {
ShhMessageCodes.OFFSET = offset; ShhMessageCodes.OFFSET = offset;
} }
public static boolean inRange(byte code){ public static boolean inRange(byte code) {
if (code >= STATUS.asByte() && code <= PACKET_COUNT.asByte()) if (code >= STATUS.asByte() && code <= PACKET_COUNT.asByte())
return true; return true;
@ -62,6 +73,6 @@ public enum ShhMessageCodes {
} }
public byte asByte() { public byte asByte() {
return (byte) (cmd + OFFSET); return (byte) (cmd + OFFSET);
} }
} }

View File

@ -15,6 +15,7 @@ public class TransactionExecutor {
static { static {
instance = new TransactionExecutor(); instance = new TransactionExecutor();
} }
public static TransactionExecutor instance; public static TransactionExecutor instance;
private ExecutorService executor = Executors.newFixedThreadPool(1); private ExecutorService executor = Executors.newFixedThreadPool(1);

View File

@ -62,10 +62,10 @@ public class MessageDecoder extends ByteToMessageDecoder {
long syncToken = in.readUnsignedInt(); long syncToken = in.readUnsignedInt();
if (!((syncToken >> 24 & 0xFF) == 0x22 && if (!((syncToken >> 24 & 0xFF) == 0x22 &&
(syncToken >> 16 & 0xFF) == 0x40 && (syncToken >> 16 & 0xFF) == 0x40 &&
(syncToken >> 8 & 0xFF) == 0x08 && (syncToken >> 8 & 0xFF) == 0x08 &&
(syncToken & 0xFF) == 0x91 )) { (syncToken & 0xFF) == 0x91)) {
// TODO: Drop frame and continue. // TODO: Drop frame and continue.
// A collision can happen (although rare) // A collision can happen (although rare)

View File

@ -24,7 +24,7 @@ import org.springframework.stereotype.Component;
public class MessageEncoder extends MessageToByteEncoder<Message> { public class MessageEncoder extends MessageToByteEncoder<Message> {
private static final Logger loggerWire = LoggerFactory.getLogger("wire"); 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 @Autowired
WorldManager worldManager; WorldManager worldManager;

View File

@ -6,6 +6,7 @@ import org.apache.maven.plugin.MojoFailureException;
/** /**
* www.ethereumJ.com * www.ethereumJ.com
*
* @author: Roman Mandeleil * @author: Roman Mandeleil
* Created on: 25/04/14 17:06 * 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 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 tool = new Tool(options);
tool.outputDirectory = userDir + "\\src\\main\\java\\org\\ethereum\\serpent\\"; tool.outputDirectory = userDir + "\\src\\main\\java\\org\\ethereum\\serpent\\";
tool.processGrammarsOnCommandLine(); tool.processGrammarsOnCommandLine();

Some files were not shown because too many files have changed in this diff Show More