Convert tabs to spaces

Prior to this change, 78% of lines in .java files with leading
whitespace used four-space indentation, while 22% used tabs.
This commit is contained in:
Chris Beams 2014-12-26 09:31:43 +01:00
parent c7cb5231fe
commit 0827fb5c8f
No known key found for this signature in database
GPG Key ID: 3D214F8F5BC5ED73
162 changed files with 7573 additions and 7573 deletions

View File

@ -1,12 +1,12 @@
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.ethereum</groupId>
<artifactId>ethereumj</artifactId>
<packaging>jar</packaging>
<version>0.7.14</version>
<name>EthereumJ</name>
<url>http://www.ethereumj.org</url>
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.ethereum</groupId>
<artifactId>ethereumj</artifactId>
<packaging>jar</packaging>
<version>0.7.14</version>
<name>EthereumJ</name>
<url>http://www.ethereumj.org</url>
<!--
* Install jar with sources to the local maven repository
@ -17,64 +17,64 @@
-->
<developers>
<developer>
<name>Roman Mandeleil</name>
</developer>
<developer>
<name>Nick Savers</name>
</developer>
</developers>
<developers>
<developer>
<name>Roman Mandeleil</name>
</developer>
<developer>
<name>Nick Savers</name>
</developer>
</developers>
<scm>
<connection>scm:git:git://github.com/ethereum/ethereumj.git</connection>
<developerConnection>scm:git:ssh://git@github.com/ethereum/ethereumj.git</developerConnection>
<url>https://github.com/ethereum/ethereumj</url>
</scm>
<scm>
<connection>scm:git:git://github.com/ethereum/ethereumj.git</connection>
<developerConnection>scm:git:ssh://git@github.com/ethereum/ethereumj.git</developerConnection>
<url>https://github.com/ethereum/ethereumj</url>
</scm>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Third-party dependencies -->
<junit.version>4.11</junit.version>
<slf4j.version>1.7.7</slf4j.version>
<leveldb.version>0.7</leveldb.version>
<spongycastle.version>1.51.0.0</spongycastle.version>
<generated.sourceDirectory>gen</generated.sourceDirectory>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- Third-party dependencies -->
<junit.version>4.11</junit.version>
<slf4j.version>1.7.7</slf4j.version>
<leveldb.version>0.7</leveldb.version>
<spongycastle.version>1.51.0.0</spongycastle.version>
<generated.sourceDirectory>gen</generated.sourceDirectory>
<github.global.server>github</github.global.server>
</properties>
</properties>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.23.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Spongy Castle for SHA3 and SECP256K1 -->
<dependency>
<groupId>com.madgag.spongycastle</groupId>
<artifactId>core</artifactId>
<version>${spongycastle.version}</version>
</dependency>
<dependency>
<groupId>org.iq80.leveldb</groupId>
<artifactId>leveldb</artifactId>
<version>${leveldb.version}</version>
</dependency>
<!-- Added Cedarsoft for DeepEquals function -->
<dependency>
<groupId>com.cedarsoftware</groupId>
<artifactId>java-util</artifactId>
<version>1.8.0</version>
</dependency>
<!-- For Serpent compile -->
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.23.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- Spongy Castle for SHA3 and SECP256K1 -->
<dependency>
<groupId>com.madgag.spongycastle</groupId>
<artifactId>core</artifactId>
<version>${spongycastle.version}</version>
</dependency>
<dependency>
<groupId>org.iq80.leveldb</groupId>
<artifactId>leveldb</artifactId>
<version>${leveldb.version}</version>
</dependency>
<!-- Added Cedarsoft for DeepEquals function -->
<dependency>
<groupId>com.cedarsoftware</groupId>
<artifactId>java-util</artifactId>
<version>1.8.0</version>
</dependency>
<!-- For Serpent compile -->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
@ -228,10 +228,10 @@
</dependencies>
<build>
<build>
<plugins>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
@ -322,30 +322,30 @@
</plugin>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>2.2.0</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.1.201405082137</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>org/ethereum/gui/**/*.class</exclude>
<exclude>org/ethereum/**/*Test.class</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.eluder.coveralls</groupId>
<artifactId>coveralls-maven-plugin</artifactId>
<version>2.2.0</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.1.201405082137</version>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
</executions>
<configuration>
<excludes>
<exclude>org/ethereum/gui/**/*.class</exclude>
<exclude>org/ethereum/**/*Test.class</exclude>
</excludes>
</configuration>
</plugin>
<!--
<plugin>
@ -401,8 +401,8 @@
</plugins>
<pluginManagement>
</plugins>
<pluginManagement>
<plugins>
<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
<plugin>
@ -418,7 +418,7 @@
<artifactId>maven-dependency-plugin</artifactId>
<versionRange>[2.0,)</versionRange>
<goals>
<goal>copy-dependencies</goal>
<goal>copy-dependencies</goal>
<goal>unpack</goal>
</goals>
</pluginExecutionFilter>
@ -427,17 +427,17 @@
</action>
</pluginExecution>
<pluginExecution>
<pluginExecutionFilter>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<versionRange>[0.7.1.201405082137,)</versionRange>
<goals>
<goal>prepare-agent</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
<pluginExecutionFilter>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<versionRange>[0.7.1.201405082137,)</versionRange>
<goals>
<goal>prepare-agent</goal>
</goals>
</pluginExecutionFilter>
<action>
<ignore></ignore>
</action>
</pluginExecution>
</pluginExecutions>
</lifecycleMappingMetadata>
@ -445,6 +445,6 @@
</plugin>
</plugins>
</pluginManagement>
</build>
</build>
</project>

View File

@ -18,31 +18,31 @@ import org.springframework.stereotype.Component;
*/
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 String DEFAULT_DISCOVERY_PEER_LIST = "poc-7.ethdev.com:30303";
private static String DEFAULT_ACTIVE_PEER_IP = "poc-7.ethdev.com";
private static int DEFAULT_ACTIVE_PORT = 30303;
private static String DEFAULT_SAMPLES_DIR = "samples";
private static String DEFAULT_COINBASE_SECRET = "monkey";
private static int DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT = 5;
private static Boolean DEFAULT_DB_RESET = false;
private static Boolean DEFAULT_DUMP_FULL = false;
private static Boolean DEFAULT_RECORD_BLOCKS = false;
private static String DEFAULT_DUMP_DIR = "dmp";
private static String DEFAULT_DUMP_STYLE = "standard+";
private static Integer DEFAULT_VMTRACE_BLOCK = 0;
private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir");
private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true;
private static Boolean DEFAULT_PLAY_VM = true;
private static Boolean DEFAULT_BLOCKCHAIN_ONLY = false;
private static int DEFAULT_TRACE_STARTBLOCK = -1;
private static int DEFAULT_MAX_HASHES_ASK = -1; // unlimited
private static int DEFAULT_MAX_BLOCKS_ASK = 10;
private static int DEFAULT_MAX_BLOCKS_QUEUED = 300;
private static String DEFAULT_PROJECT_VERSION = "";
private static String DEFAULT_HELLO_PHRASE = "Dev";
private static int DEFAULT_TX_APPROVE_TIMEOUT = 10;
private static String DEFAULT_DISCOVERY_PEER_LIST = "poc-7.ethdev.com:30303";
private static String DEFAULT_ACTIVE_PEER_IP = "poc-7.ethdev.com";
private static int DEFAULT_ACTIVE_PORT = 30303;
private static String DEFAULT_SAMPLES_DIR = "samples";
private static String DEFAULT_COINBASE_SECRET = "monkey";
private static int DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT = 5;
private static Boolean DEFAULT_DB_RESET = false;
private static Boolean DEFAULT_DUMP_FULL = false;
private static Boolean DEFAULT_RECORD_BLOCKS = false;
private static String DEFAULT_DUMP_DIR = "dmp";
private static String DEFAULT_DUMP_STYLE = "standard+";
private static Integer DEFAULT_VMTRACE_BLOCK = 0;
private static String DEFAULT_DATABASE_DIR = System.getProperty("user.dir");
private static Boolean DEFAULT_DUMP_CLEAN_ON_RESTART = true;
private static Boolean DEFAULT_PLAY_VM = true;
private static Boolean DEFAULT_BLOCKCHAIN_ONLY = false;
private static int DEFAULT_TRACE_STARTBLOCK = -1;
private static int DEFAULT_MAX_HASHES_ASK = -1; // unlimited
private static int DEFAULT_MAX_BLOCKS_ASK = 10;
private static int DEFAULT_MAX_BLOCKS_QUEUED = 300;
private static String DEFAULT_PROJECT_VERSION = "";
private static String DEFAULT_HELLO_PHRASE = "Dev";
private static Boolean DEFAULT_VM_TRACE = false;
private static String DEFAULT_VM_TRACE_DIR = "dmp";
private static int DEFAULT_PEER_LISTEN_PORT = 30303;
@ -52,117 +52,117 @@ public class SystemProperties {
private static List<String> DEFAULT_PROTOCOL_LIST = Arrays.asList("eth", "shh");
public static SystemProperties CONFIG = new SystemProperties();
private Properties prop = new Properties();
private InputStream input = null;
public static SystemProperties CONFIG = new SystemProperties();
private Properties prop = new Properties();
private InputStream input = null;
public SystemProperties() {
public SystemProperties() {
try {
String userDir = System.getProperty("user.dir");
String fileName = userDir + "/config/system.properties";
File file = new File(fileName);
try {
String userDir = System.getProperty("user.dir");
String fileName = userDir + "/config/system.properties";
File file = new File(fileName);
if (file.exists()) {
if (file.exists()) {
logger.info("config loaded from {}", fileName);
input = new FileInputStream(file);
} else {
fileName = "system.properties";
input = SystemProperties.class.getClassLoader()
.getResourceAsStream(fileName);
if (input == null) {
logger.error("Sorry, unable to find {}", fileName);
return;
}
}
// load a properties file from class path, inside static method
prop.load(input);
input = new FileInputStream(file);
} else {
fileName = "system.properties";
input = SystemProperties.class.getClassLoader()
.getResourceAsStream(fileName);
if (input == null) {
logger.error("Sorry, unable to find {}", fileName);
return;
}
}
// load a properties file from class path, inside static method
prop.load(input);
} catch (IOException ex) {
logger.error(ex.getMessage(), ex);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
}
} catch (IOException ex) {
logger.error(ex.getMessage(), ex);
} finally {
if (input != null) {
try {
input.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
}
public boolean peerDiscovery() {
if (prop.isEmpty()) return true;
return Boolean.parseBoolean(prop.getProperty("peer.discovery"));
}
public boolean peerDiscovery() {
if (prop.isEmpty()) return true;
return Boolean.parseBoolean(prop.getProperty("peer.discovery"));
}
public int peerDiscoveryWorkers() {
if (prop.isEmpty()) return 2;
return Integer.parseInt(prop.getProperty("peer.discovery.workers"));
}
public int peerDiscoveryWorkers() {
if (prop.isEmpty()) return 2;
return Integer.parseInt(prop.getProperty("peer.discovery.workers"));
}
public int peerConnectionTimeout() {
if (prop.isEmpty()) return 10000;
return Integer.parseInt(prop.getProperty("peer.connection.timeout")) * 1000;
}
public int peerConnectionTimeout() {
if (prop.isEmpty()) return 10000;
return Integer.parseInt(prop.getProperty("peer.connection.timeout")) * 1000;
}
public int transactionApproveTimeout() {
if (prop.isEmpty()) return DEFAULT_TX_APPROVE_TIMEOUT;
return Integer.parseInt(prop.getProperty("transaction.approve.timeout"));
}
public int transactionApproveTimeout() {
if (prop.isEmpty()) return DEFAULT_TX_APPROVE_TIMEOUT;
return Integer.parseInt(prop.getProperty("transaction.approve.timeout"));
}
public String peerDiscoveryIPList() {
if (prop.isEmpty()) return DEFAULT_DISCOVERY_PEER_LIST;
return prop.getProperty("peer.discovery.ip.list");
}
public String peerDiscoveryIPList() {
if (prop.isEmpty()) return DEFAULT_DISCOVERY_PEER_LIST;
return prop.getProperty("peer.discovery.ip.list");
}
public boolean databaseReset() {
if (prop.isEmpty()) return DEFAULT_DB_RESET;
return Boolean.parseBoolean(prop.getProperty("database.reset"));
}
public boolean databaseReset() {
if (prop.isEmpty()) return DEFAULT_DB_RESET;
return Boolean.parseBoolean(prop.getProperty("database.reset"));
}
public void setDatabaseReset(Boolean reset){
prop.setProperty("database.reset", reset.toString());
}
public String activePeerIP() {
if (prop.isEmpty()) return DEFAULT_ACTIVE_PEER_IP;
return prop.getProperty("peer.active.ip");
}
public String activePeerIP() {
if (prop.isEmpty()) return DEFAULT_ACTIVE_PEER_IP;
return prop.getProperty("peer.active.ip");
}
public void setActivePeerIP(String host){
prop.setProperty("peer.active.ip", host.toString());
}
public int activePeerPort() {
if (prop.isEmpty()) return DEFAULT_ACTIVE_PORT;
return Integer.parseInt(prop.getProperty("peer.active.port"));
}
public int activePeerPort() {
if (prop.isEmpty()) return DEFAULT_ACTIVE_PORT;
return Integer.parseInt(prop.getProperty("peer.active.port"));
}
public void setActivePeerPort(Integer port){
prop.setProperty("peer.active.port", port.toString());
}
public String samplesDir() {
if (prop.isEmpty()) return DEFAULT_SAMPLES_DIR;
return prop.getProperty("samples.dir");
}
public String samplesDir() {
if (prop.isEmpty()) return DEFAULT_SAMPLES_DIR;
return prop.getProperty("samples.dir");
}
public String coinbaseSecret() {
if (prop.isEmpty()) return DEFAULT_COINBASE_SECRET;
return prop.getProperty("coinbase.secret");
}
public String coinbaseSecret() {
if (prop.isEmpty()) return DEFAULT_COINBASE_SECRET;
return prop.getProperty("coinbase.secret");
}
public Integer peerChannelReadTimeout() {
if (prop.isEmpty()) return DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT;
return Integer.parseInt(prop.getProperty("peer.channel.read.timeout"));
}
public Integer peerChannelReadTimeout() {
if (prop.isEmpty()) return DEFAULT_ACTIVE_PEER_CHANNEL_TIMEOUT;
return Integer.parseInt(prop.getProperty("peer.channel.read.timeout"));
}
public Integer traceStartBlock() {
if (prop.isEmpty()) return DEFAULT_TRACE_STARTBLOCK;
return Integer.parseInt(prop.getProperty("trace.startblock"));
}
public Integer traceStartBlock() {
if (prop.isEmpty()) return DEFAULT_TRACE_STARTBLOCK;
return Integer.parseInt(prop.getProperty("trace.startblock"));
}
public Boolean recordBlocks() {
if (prop.isEmpty()) return DEFAULT_RECORD_BLOCKS;
@ -170,82 +170,82 @@ public class SystemProperties {
}
public Boolean dumpFull() {
if (prop.isEmpty()) return DEFAULT_DUMP_FULL;
return Boolean.parseBoolean(prop.getProperty("dump.full"));
}
public Boolean dumpFull() {
if (prop.isEmpty()) return DEFAULT_DUMP_FULL;
return Boolean.parseBoolean(prop.getProperty("dump.full"));
}
public String dumpDir() {
if (prop.isEmpty()) return DEFAULT_DUMP_DIR;
return prop.getProperty("dump.dir");
}
public String dumpDir() {
if (prop.isEmpty()) return DEFAULT_DUMP_DIR;
return prop.getProperty("dump.dir");
}
public String dumpStyle() {
if (prop.isEmpty()) return DEFAULT_DUMP_STYLE;
return prop.getProperty("dump.style");
}
public String dumpStyle() {
if (prop.isEmpty()) return DEFAULT_DUMP_STYLE;
return prop.getProperty("dump.style");
}
public Integer dumpBlock() {
if (prop.isEmpty()) return DEFAULT_VMTRACE_BLOCK;
return Integer.parseInt(prop.getProperty("dump.block"));
}
public Integer dumpBlock() {
if (prop.isEmpty()) return DEFAULT_VMTRACE_BLOCK;
return Integer.parseInt(prop.getProperty("dump.block"));
}
public String databaseDir() {
if (prop.isEmpty()) return DEFAULT_DATABASE_DIR;
return prop.getProperty("database.dir");
}
public String databaseDir() {
if (prop.isEmpty()) return DEFAULT_DATABASE_DIR;
return prop.getProperty("database.dir");
}
public void setDataBaseDir(String dataBaseDir){
prop.setProperty("database.dir", dataBaseDir);
}
public Boolean dumpCleanOnRestart() {
if (prop.isEmpty()) return DEFAULT_DUMP_CLEAN_ON_RESTART;
return Boolean.parseBoolean(prop.getProperty("dump.clean.on.restart"));
}
public Boolean dumpCleanOnRestart() {
if (prop.isEmpty()) return DEFAULT_DUMP_CLEAN_ON_RESTART;
return Boolean.parseBoolean(prop.getProperty("dump.clean.on.restart"));
}
public Boolean playVM() {
if (prop.isEmpty()) return DEFAULT_PLAY_VM;
return Boolean.parseBoolean(prop.getProperty("play.vm"));
}
public Boolean playVM() {
if (prop.isEmpty()) return DEFAULT_PLAY_VM;
return Boolean.parseBoolean(prop.getProperty("play.vm"));
}
public Boolean blockChainOnly() {
if (prop.isEmpty()) return DEFAULT_BLOCKCHAIN_ONLY;
return Boolean.parseBoolean(prop.getProperty("blockchain.only"));
}
public Boolean blockChainOnly() {
if (prop.isEmpty()) return DEFAULT_BLOCKCHAIN_ONLY;
return Boolean.parseBoolean(prop.getProperty("blockchain.only"));
}
public Integer maxHashesAsk() {
if (prop.isEmpty()) return DEFAULT_MAX_HASHES_ASK;
return Integer.parseInt(prop.getProperty("max.hashes.ask"));
}
public Integer maxHashesAsk() {
if (prop.isEmpty()) return DEFAULT_MAX_HASHES_ASK;
return Integer.parseInt(prop.getProperty("max.hashes.ask"));
}
public Integer maxBlocksAsk() {
if (prop.isEmpty()) return DEFAULT_MAX_BLOCKS_ASK;
return Integer.parseInt(prop.getProperty("max.blocks.ask"));
}
public Integer maxBlocksAsk() {
if (prop.isEmpty()) return DEFAULT_MAX_BLOCKS_ASK;
return Integer.parseInt(prop.getProperty("max.blocks.ask"));
}
public Integer maxBlocksQueued() {
if (prop.isEmpty()) return DEFAULT_MAX_BLOCKS_QUEUED;
return Integer.parseInt(prop.getProperty("max.blocks.queued"));
}
public Integer maxBlocksQueued() {
if (prop.isEmpty()) return DEFAULT_MAX_BLOCKS_QUEUED;
return Integer.parseInt(prop.getProperty("max.blocks.queued"));
}
public String projectVersion() {
if (prop.isEmpty()) return DEFAULT_PROJECT_VERSION;
return prop.getProperty("project.version");
}
public String projectVersion() {
if (prop.isEmpty()) return DEFAULT_PROJECT_VERSION;
return prop.getProperty("project.version");
}
public String helloPhrase() {
if (prop.isEmpty()) return DEFAULT_HELLO_PHRASE;
return prop.getProperty("hello.phrase");
}
public String helloPhrase() {
if (prop.isEmpty()) return DEFAULT_HELLO_PHRASE;
return prop.getProperty("hello.phrase");
}
public String rootHashStart() {
if (prop.isEmpty()) return null;
String hash = prop.getProperty("root.hash.start");
if (hash == null || hash.equals("-1"))
return null;
return hash;
}
public String rootHashStart() {
if (prop.isEmpty()) return null;
String hash = prop.getProperty("root.hash.start");
if (hash == null || hash.equals("-1"))
return null;
return hash;
}
public List<String> peerCapabilities(){
if (prop.isEmpty()) return DEFAULT_PROTOCOL_LIST;
@ -272,28 +272,28 @@ public class SystemProperties {
prop.setProperty("peer.listen.port", port.toString());
}
public void print() {
Enumeration<?> e = prop.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String value = prop.getProperty(key);
if (!key.equals("null"))
logger.info("Key: " + key + ", Value: " + value);
}
}
/*
*
* Testing
*
*/
public boolean vmTestLoadLocal() {
public void print() {
Enumeration<?> e = prop.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String value = prop.getProperty(key);
if (!key.equals("null"))
logger.info("Key: " + key + ", Value: " + value);
}
}
/*
*
* Testing
*
*/
public boolean vmTestLoadLocal() {
if (prop.isEmpty() || !prop.containsKey("GitHubTests.VMTest.loadLocal")) return DEFAULT_VMTEST_LOAD_LOCAL;
return Boolean.parseBoolean(prop.getProperty("GitHubTests.VMTest.loadLocal"));
}
public static void main(String args[]) {
SystemProperties systemProperties = new SystemProperties();
systemProperties.print();
}
public static void main(String args[]) {
SystemProperties systemProperties = new SystemProperties();
systemProperties.print();
}
}

View File

@ -18,8 +18,8 @@ import org.springframework.stereotype.Component;
@Scope("prototype")
public class Account {
private ECKey ecKey;
private byte[] address;
private ECKey ecKey;
private byte[] address;
private Set<Transaction> pendingTransactions =
Collections.synchronizedSet(new HashSet<Transaction>());
@ -27,18 +27,18 @@ public class Account {
@Autowired
WorldManager worldManager;
public Account() {
}
public Account() {
}
public void init(){
this.ecKey = new ECKey(Utils.getRandom());
address = this.ecKey.getAddress();
}
public void init(ECKey ecKey) {
this.ecKey = ecKey;
public void init(ECKey ecKey) {
this.ecKey = ecKey;
address = this.ecKey.getAddress();
}
}
public BigInteger getNonce(){
AccountState accountState =
@ -82,16 +82,16 @@ public class Account {
return ecKey;
}
public byte[] getAddress() {
return address;
}
public byte[] getAddress() {
return address;
}
public void setAddress(byte[] address) {
this.address = address;
}
public void setAddress(byte[] address) {
this.address = address;
}
public Set<Transaction> getPendingTransactins() {
return this.pendingTransactions;
return this.pendingTransactions;
}
public void addPendingTransaction(Transaction transaction){

View File

@ -57,13 +57,13 @@ public class AccountState {
public AccountState(byte[] rlpData) {
this.rlpEncoded = rlpData;
RLPList items = (RLPList) RLP.decode2(rlpEncoded).get(0);
this.nonce = items.get(0).getRLPData() == null ? BigInteger.ZERO
: new BigInteger(1, items.get(0).getRLPData());
this.balance = items.get(1).getRLPData() == null ? BigInteger.ZERO
: new BigInteger(1, items.get(1).getRLPData());
this.stateRoot = items.get(2).getRLPData();
this.codeHash = items.get(3).getRLPData();
RLPList items = (RLPList) RLP.decode2(rlpEncoded).get(0);
this.nonce = items.get(0).getRLPData() == null ? BigInteger.ZERO
: new BigInteger(1, items.get(0).getRLPData());
this.balance = items.get(1).getRLPData() == null ? BigInteger.ZERO
: new BigInteger(1, items.get(1).getRLPData());
this.stateRoot = items.get(2).getRLPData();
this.codeHash = items.get(3).getRLPData();
}
public BigInteger getNonce() {
@ -110,21 +110,21 @@ public class AccountState {
return this.balance;
}
public void subFromBalance(BigInteger value) {
public void subFromBalance(BigInteger value) {
if (value.signum() != 0) rlpEncoded = null;
this.balance = balance.subtract(value);
setDirty(true);
}
}
public byte[] getEncoded() {
if(rlpEncoded == null) {
byte[] nonce = RLP.encodeBigInteger(this.nonce);
byte[] balance = RLP.encodeBigInteger(this.balance);
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
byte[] codeHash = RLP.encodeElement(this.codeHash);
this.rlpEncoded = RLP.encodeList(nonce, balance, stateRoot, codeHash);
}
return rlpEncoded;
if(rlpEncoded == null) {
byte[] nonce = RLP.encodeBigInteger(this.nonce);
byte[] balance = RLP.encodeBigInteger(this.balance);
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
byte[] codeHash = RLP.encodeElement(this.codeHash);
this.rlpEncoded = RLP.encodeList(nonce, balance, stateRoot, codeHash);
}
return rlpEncoded;
}
public void setDirty(boolean dirty) {
@ -156,10 +156,10 @@ public class AccountState {
}
public String toString() {
String ret = " Nonce: " + this.getNonce().toString() + "\n" +
" Balance: " + getBalance() + "\n" +
" State Root: " + Hex.toHexString(this.getStateRoot()) + "\n" +
" Code Hash: " + Hex.toHexString(this.getCodeHash());
return ret;
String ret = " Nonce: " + this.getNonce().toString() + "\n" +
" Balance: " + getBalance() + "\n" +
" State Root: " + Hex.toHexString(this.getStateRoot()) + "\n" +
" Code Hash: " + Hex.toHexString(this.getCodeHash());
return ret;
}
}

View File

@ -29,25 +29,25 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
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 UNCLE_REWARD = BLOCK_REWARD.multiply(
BigInteger.valueOf(15)).divide(BigInteger.valueOf(16));
public static BigInteger INCLUSION_REWARD = Block.BLOCK_REWARD
.divide(BigInteger.valueOf(32));
public static BigInteger UNCLE_REWARD = BLOCK_REWARD.multiply(
BigInteger.valueOf(15)).divide(BigInteger.valueOf(16));
public static BigInteger INCLUSION_REWARD = Block.BLOCK_REWARD
.divide(BigInteger.valueOf(32));
private BlockHeader header;
private BlockHeader header;
/* Transactions */
private List<Transaction> transactionsList = new CopyOnWriteArrayList<>();
/* Uncles */
private List<Transaction> transactionsList = new CopyOnWriteArrayList<>();
/* Uncles */
private List<BlockHeader> uncleList = new CopyOnWriteArrayList<>();
/* Private */
private byte[] rlpEncoded;
/* Private */
private byte[] rlpEncoded;
private boolean parsed = false;
private Trie txsState;
@ -55,20 +55,20 @@ public class Block {
/* Constructors */
public Block(byte[] rawData) {
logger.debug("new from [" + Hex.toHexString(rawData) + "]");
logger.debug("new from [" + Hex.toHexString(rawData) + "]");
this.rlpEncoded = rawData;
this.parsed = false;
}
public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] logsBloom,
byte[] difficulty, long number, long gasLimit,
long gasUsed, long timestamp, byte[] extraData, byte[] nonce,
List<Transaction> transactionsList, List<BlockHeader> uncleList) {
this.header = new BlockHeader(parentHash, unclesHash, coinbase, logsBloom,
difficulty, number, gasLimit, gasUsed,
timestamp, extraData, nonce);
public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] logsBloom,
byte[] difficulty, long number, long gasLimit,
long gasUsed, long timestamp, byte[] extraData, byte[] nonce,
List<Transaction> transactionsList, List<BlockHeader> uncleList) {
this.header = new BlockHeader(parentHash, unclesHash, coinbase, logsBloom,
difficulty, number, gasLimit, gasUsed,
timestamp, extraData, nonce);
this.transactionsList = transactionsList;
this.transactionsList = transactionsList;
if (this.transactionsList == null){
this.transactionsList = new CopyOnWriteArrayList<Transaction>();
}
@ -112,24 +112,24 @@ public class Block {
public byte[] getHash() {
if (!parsed) parseRLP();
return HashUtil.sha3(this.header.getEncoded());
return HashUtil.sha3(this.header.getEncoded());
}
public byte[] calcDifficulty() {
if (!parsed) parseRLP();
return this.header.calcDifficulty();
}
public byte[] calcDifficulty() {
if (!parsed) parseRLP();
return this.header.calcDifficulty();
}
public boolean validateNonce() {
if (!parsed) parseRLP();
public boolean validateNonce() {
if (!parsed) parseRLP();
BigInteger max = BigInteger.valueOf(2).pow(256);
byte[] target = BigIntegers.asUnsignedByteArray(32, max.divide(new BigInteger(1, this.getDifficulty())));
byte[] hash = HashUtil.sha3(this.getEncodedWithoutNonce());
byte[] concat = Arrays.concatenate(hash, this.getNonce());
byte[] result = HashUtil.sha3(concat);
return FastByteComparisons.compareTo(result, 0, 32, target, 0, 32) < 0;
}
}
public byte[] getParentHash() {
@ -174,10 +174,10 @@ public class Block {
public BigInteger getCumulativeDifficulty() {
if (!parsed) parseRLP();
BigInteger calcDifficulty = new BigInteger(1, this.header.getDifficulty());
BigInteger calcDifficulty = new BigInteger(1, this.header.getDifficulty());
for (BlockHeader uncle : uncleList) {
calcDifficulty = calcDifficulty.add(new BigInteger(1, uncle.getDifficulty()));
}
}
return calcDifficulty;
}
@ -187,21 +187,21 @@ public class Block {
}
public long getNumber() {
if (!parsed) parseRLP();
return this.header.getNumber();
}
if (!parsed) parseRLP();
return this.header.getNumber();
}
public long getGasLimit() {
if (!parsed) parseRLP();
return this.header.getGasLimit();
}
public long getGasLimit() {
if (!parsed) parseRLP();
return this.header.getGasLimit();
}
public long getGasUsed() {
if (!parsed) parseRLP();
return this.header.getGasUsed();
}
public long getGasUsed() {
if (!parsed) parseRLP();
return this.header.getGasUsed();
}
public byte[] getExtraData() {
public byte[] getExtraData() {
if (!parsed) parseRLP();
return this.header.getExtraData();
}
@ -227,9 +227,9 @@ public class Block {
}
private StringBuffer toStringBuff = new StringBuffer();
// [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root,
// difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp,
// extradata, nonce]
// [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root,
// difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp,
// extradata, nonce]
@Override
public String toString() {
@ -275,14 +275,14 @@ public class Block {
this.txsState = new TrieImpl(null);
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.txsState.update(RLP.encodeInt(i) , transactionRaw.getRLPData());
}
String calculatedRoot = Hex.toHexString(txsState.getRootHash());
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");
}
/**
@ -294,9 +294,9 @@ public class Block {
return Arrays.areEqual(this.getHash(), block.getParentHash());
}
public boolean isGenesis() {
return this.header.isGenesis();
}
public boolean isGenesis() {
return this.header.isGenesis();
}
public boolean isEqual(Block block){
return Arrays.areEqual(this.getHash(), block.getHash());
@ -318,22 +318,22 @@ public class Block {
this.getHeader().setUnclesHash( SHA3Helper.sha3( getUnclesEncoded() ));
rlpEncoded = null;
}
public byte[] getEncoded() {
if(rlpEncoded == null) {
byte[] header = this.header.getEncoded();
byte[] transactions = RLP.encodeList();
byte[] uncles = getUnclesEncoded();
this.rlpEncoded = RLP.encodeList(header, transactions, uncles);
}
return rlpEncoded;
}
public byte[] getEncodedWithoutNonce() {
if (!parsed) parseRLP();
byte[] header = this.header.getEncodedWithoutNonce();
public byte[] getEncoded() {
if(rlpEncoded == null) {
byte[] header = this.header.getEncoded();
byte[] transactions = RLP.encodeList();
byte[] uncles = getUnclesEncoded();
this.rlpEncoded = RLP.encodeList(header, transactions, uncles);
}
return rlpEncoded;
}
public byte[] getEncodedWithoutNonce() {
if (!parsed) parseRLP();
byte[] header = this.header.getEncodedWithoutNonce();
return header;
}
}
public String getShortHash(){
if (!parsed) parseRLP();

View File

@ -15,10 +15,10 @@ import static org.ethereum.util.ByteUtil.toHexString;
* the basic information of a block
*/
public class BlockHeader {
/* The SHA3 256-bit hash of the parent block, in its entirety */
private byte[] parentHash;
private byte[] parentHash;
/* The SHA3 256-bit hash of the uncles list portion of this block */
private byte[] unclesHash;
/* The 160-bit address to which all fees collected from the
@ -70,7 +70,7 @@ public class BlockHeader {
this.txTrieRoot = rlpHeader.get(4).getRLPData();
if(this.txTrieRoot == null)
this.txTrieRoot = EMPTY_TRIE_HASH;
this.txTrieRoot = EMPTY_TRIE_HASH;
this.recieptTrieRoot = rlpHeader.get(5).getRLPData();
if(this.recieptTrieRoot == null)
@ -84,10 +84,10 @@ public class BlockHeader {
byte[] guBytes = rlpHeader.get(10).getRLPData();
byte[] tsBytes = rlpHeader.get(11).getRLPData();
this.number = nrBytes == null ? 0 : (new BigInteger(1, nrBytes)).longValue();
this.number = nrBytes == null ? 0 : (new BigInteger(1, nrBytes)).longValue();
this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue();
this.extraData = rlpHeader.get(12).getRLPData();
@ -95,7 +95,7 @@ public class BlockHeader {
}
public BlockHeader(byte[] parentHash, byte[] unclesHash, byte[] coinbase,
public BlockHeader(byte[] parentHash, byte[] unclesHash, byte[] coinbase,
byte[] logsBloom, byte[] difficulty, long number,
long gasLimit, long gasUsed, long timestamp,
byte[] extraData, byte[] nonce) {
@ -112,62 +112,62 @@ public class BlockHeader {
this.nonce = nonce;
this.stateRoot = HashUtil.EMPTY_TRIE_HASH;
}
/**
* Calculate Difficulty
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (24)
* @return byte array value of the difficulty
*/
public byte[] calcDifficulty() {
if (this.isGenesis())
return Genesis.DIFFICULTY;
else { //todo find the right way to calc difficulty
// Block parent = this.getParent();
// long parentDifficulty = new BigInteger(1, parent.getDifficulty()).longValue();
// long newDifficulty = this.getTimestamp() < parent.getTimestamp() + 5 ? parentDifficulty - (parentDifficulty >> 10) : (parentDifficulty + (parentDifficulty >> 10));
// return BigIntegers.asUnsignedByteArray(BigInteger.valueOf(newDifficulty));
/**
* Calculate Difficulty
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (24)
* @return byte array value of the difficulty
*/
public byte[] calcDifficulty() {
if (this.isGenesis())
return Genesis.DIFFICULTY;
else { //todo find the right way to calc difficulty
// Block parent = this.getParent();
// long parentDifficulty = new BigInteger(1, parent.getDifficulty()).longValue();
// long newDifficulty = this.getTimestamp() < parent.getTimestamp() + 5 ? parentDifficulty - (parentDifficulty >> 10) : (parentDifficulty + (parentDifficulty >> 10));
// return BigIntegers.asUnsignedByteArray(BigInteger.valueOf(newDifficulty));
return this.getDifficulty();
}
}
}
}
public boolean isGenesis() {
return this.getNumber() == Genesis.NUMBER;
}
public boolean isGenesis() {
return this.getNumber() == Genesis.NUMBER;
}
public byte[] getParentHash() {
return parentHash;
}
public void setParentHash(byte[] parentHash) {
this.parentHash = parentHash;
}
public byte[] getUnclesHash() {
return unclesHash;
}
public void setUnclesHash(byte[] unclesHash) {
this.unclesHash = unclesHash;
}
public byte[] getCoinbase() {
return coinbase;
}
public void setCoinbase(byte[] coinbase) {
this.coinbase = coinbase;
}
public byte[] getStateRoot() {
return stateRoot;
}
public void setStateRoot(byte[] stateRoot) {
this.stateRoot = stateRoot;
}
public byte[] getTxTrieRoot() {
return txTrieRoot;
}
public void setTxTrieRoot(byte[] txTrieRoot) {
this.txTrieRoot = txTrieRoot;
}
public byte[] getParentHash() {
return parentHash;
}
public void setParentHash(byte[] parentHash) {
this.parentHash = parentHash;
}
public byte[] getUnclesHash() {
return unclesHash;
}
public void setUnclesHash(byte[] unclesHash) {
this.unclesHash = unclesHash;
}
public byte[] getCoinbase() {
return coinbase;
}
public void setCoinbase(byte[] coinbase) {
this.coinbase = coinbase;
}
public byte[] getStateRoot() {
return stateRoot;
}
public void setStateRoot(byte[] stateRoot) {
this.stateRoot = stateRoot;
}
public byte[] getTxTrieRoot() {
return txTrieRoot;
}
public void setTxTrieRoot(byte[] txTrieRoot) {
this.txTrieRoot = txTrieRoot;
}
public byte[] getRecieptTrieRoot() {
return recieptTrieRoot;
}
@ -176,126 +176,126 @@ public class BlockHeader {
this.recieptTrieRoot = recieptTrieRoot;
}
public byte[] getDifficulty() {
return difficulty;
}
public void setDifficulty(byte[] difficulty) {
this.difficulty = difficulty;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
public long getGasLimit() {
return gasLimit;
}
public void setGasLimit(long gasLimit) {
this.gasLimit = gasLimit;
}
public long getGasUsed() {
return gasUsed;
}
public void setGasUsed(long gasUsed) {
this.gasUsed = gasUsed;
}
public byte[] getExtraData() {
return extraData;
}
public void setExtraData(byte[] extraData) {
this.extraData = extraData;
}
public byte[] getNonce() {
return nonce;
}
public void setNonce(byte[] nonce) {
this.nonce = nonce;
}
public byte[] getEncoded() {
return this.getEncoded(true); // with nonce
}
public byte[] getEncodedWithoutNonce() {
return difficulty;
}
public void setDifficulty(byte[] difficulty) {
this.difficulty = difficulty;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getNumber() {
return number;
}
public void setNumber(long number) {
this.number = number;
}
public long getGasLimit() {
return gasLimit;
}
public void setGasLimit(long gasLimit) {
this.gasLimit = gasLimit;
}
public long getGasUsed() {
return gasUsed;
}
public void setGasUsed(long gasUsed) {
this.gasUsed = gasUsed;
}
public byte[] getExtraData() {
return extraData;
}
public void setExtraData(byte[] extraData) {
this.extraData = extraData;
}
public byte[] getNonce() {
return nonce;
}
public void setNonce(byte[] nonce) {
this.nonce = nonce;
}
public byte[] getEncoded() {
return this.getEncoded(true); // with nonce
}
public byte[] getEncodedWithoutNonce() {
return this.getEncoded(false);
}
public byte[] getEncoded(boolean withNonce) {
byte[] parentHash = RLP.encodeElement(this.parentHash);
}
public byte[] getEncoded(boolean withNonce) {
byte[] parentHash = RLP.encodeElement(this.parentHash);
byte[] unclesHash = RLP.encodeElement(this.unclesHash);
byte[] coinbase = RLP.encodeElement(this.coinbase);
byte[] unclesHash = RLP.encodeElement(this.unclesHash);
byte[] coinbase = RLP.encodeElement(this.coinbase);
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
byte[] stateRoot = RLP.encodeElement(this.stateRoot);
if (txTrieRoot == null) this.txTrieRoot = EMPTY_TRIE_HASH;
byte[] txTrieRoot = RLP.encodeElement(this.txTrieRoot);
byte[] txTrieRoot = RLP.encodeElement(this.txTrieRoot);
if (recieptTrieRoot == null) this.recieptTrieRoot = EMPTY_TRIE_HASH;
byte[] recieptTrieRoot = RLP.encodeElement(this.recieptTrieRoot);
byte[] recieptTrieRoot = RLP.encodeElement(this.recieptTrieRoot);
byte[] logsBloom = RLP.encodeElement(this.logsBloom);
byte[] difficulty = RLP.encodeElement(this.difficulty);
byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number));
byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit));
byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed));
byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp));
byte[] extraData = RLP.encodeElement(this.extraData);
byte[] difficulty = RLP.encodeElement(this.difficulty);
byte[] number = RLP.encodeBigInteger(BigInteger.valueOf(this.number));
byte[] gasLimit = RLP.encodeBigInteger(BigInteger.valueOf(this.gasLimit));
byte[] gasUsed = RLP.encodeBigInteger(BigInteger.valueOf(this.gasUsed));
byte[] timestamp = RLP.encodeBigInteger(BigInteger.valueOf(this.timestamp));
byte[] extraData = RLP.encodeElement(this.extraData);
if(withNonce) {
byte[] nonce = RLP.encodeElement(this.nonce);
return RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
gasLimit, gasUsed, timestamp, extraData, nonce);
byte[] nonce = RLP.encodeElement(this.nonce);
return RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
gasLimit, gasUsed, timestamp, extraData, nonce);
} else {
return RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
gasLimit, gasUsed, timestamp, extraData);
return RLP.encodeList(parentHash, unclesHash, coinbase,
stateRoot, txTrieRoot, recieptTrieRoot, logsBloom, difficulty, number,
gasLimit, gasUsed, timestamp, extraData);
}
}
}
private StringBuffer toStringBuff = new StringBuffer();
public String toString() {
private StringBuffer toStringBuff = new StringBuffer();
public String toString() {
toStringBuff.setLength(0);
toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("\n");
toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("\n");
toStringBuff.append(" coinbase=" + toHexString(coinbase)).append("\n");
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("\n");
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("\n");
toStringBuff.append(" reciptsTrieHash=" + toHexString(recieptTrieRoot)).append("\n");
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("\n");
toStringBuff.append(" number=" + number).append("\n");
toStringBuff.append(" gasLimit=" + gasLimit).append("\n");
toStringBuff.append(" gasUsed=" + gasUsed).append("\n");
toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n");
toStringBuff.append(" extraData=" + toHexString(extraData)).append("\n");
toStringBuff.append(" nonce=" + toHexString(nonce)).append("\n");
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("\n");
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("\n");
toStringBuff.append(" reciptsTrieHash=" + toHexString(recieptTrieRoot)).append("\n");
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("\n");
toStringBuff.append(" number=" + number).append("\n");
toStringBuff.append(" gasLimit=" + gasLimit).append("\n");
toStringBuff.append(" gasUsed=" + gasUsed).append("\n");
toStringBuff.append(" timestamp=" + timestamp + " (" + Utils.longToDateTime(timestamp) + ")").append("\n");
toStringBuff.append(" extraData=" + toHexString(extraData)).append("\n");
toStringBuff.append(" nonce=" + toHexString(nonce)).append("\n");
return toStringBuff.toString();
}
public String toFlatString() {
}
public String toFlatString() {
toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("");
toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("");
toStringBuff.append(" coinbase=" + toHexString(coinbase)).append("");
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("");
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("");
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("");
toStringBuff.append(" number=" + number).append("");
toStringBuff.append(" gasLimit=" + gasLimit).append("");
toStringBuff.append(" gasUsed=" + gasUsed).append("");
toStringBuff.append(" timestamp=" + timestamp).append("");
toStringBuff.append(" extraData=" + toHexString(extraData)).append("");
toStringBuff.append(" nonce=" + toHexString(nonce)).append("");
toStringBuff.append(" stateRoot=" + toHexString(stateRoot)).append("");
toStringBuff.append(" txTrieHash=" + toHexString(txTrieRoot)).append("");
toStringBuff.append(" difficulty=" + toHexString(difficulty)).append("");
toStringBuff.append(" number=" + number).append("");
toStringBuff.append(" gasLimit=" + gasLimit).append("");
toStringBuff.append(" gasUsed=" + gasUsed).append("");
toStringBuff.append(" timestamp=" + timestamp).append("");
toStringBuff.append(" extraData=" + toHexString(extraData)).append("");
toStringBuff.append(" nonce=" + toHexString(nonce)).append("");
return toStringBuff.toString();
}
}
}

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>Let S[0] be the STATE_ROOT of the previous block.</li>
* <li>Let TX be the block's transaction list, with n transactions.
* For all in in 0...n-1, set S[i+1] = APPLY(S[i],TX[i]).
* For all in in 0...n-1, set S[i+1] = APPLY(S[i],TX[i]).
* If any applications returns an error, or if the total gas consumed in the block
* up until this point exceeds the GASLIMIT, return an error.</li>
* <li>Let S_FINAL be S[n], but adding the block reward paid to the miner.</li>
@ -64,14 +64,14 @@ public class BlockchainImpl implements Blockchain {
/* A scalar value equal to the mininum limit of gas expenditure per block */
private static long MIN_GAS_LIMIT = 125000L;
private static final Logger logger = LoggerFactory.getLogger("blockchain");
private static final Logger stateLogger = LoggerFactory.getLogger("state");
// to avoid using minGasPrice=0 from Genesis for the wallet
private static final long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
private static final Logger logger = LoggerFactory.getLogger("blockchain");
private static final Logger stateLogger = LoggerFactory.getLogger("state");
// to avoid using minGasPrice=0 from Genesis for the wallet
private static final long INITIAL_MIN_GAS_PRICE = 10 * SZABO.longValue();
@Autowired
private Repository repository;
private Repository repository;
private Repository track;
@Autowired
@ -115,8 +115,8 @@ public class BlockchainImpl implements Blockchain {
@Override
public Block getBlockByNumber(long blockNr) {
return blockStore.getBlockByNumber(blockNr);
}
return blockStore.getBlockByNumber(blockNr);
}
@Override
public TransactionReceipt getTransactionReceiptByHash(byte[] hash){
@ -193,8 +193,8 @@ public class BlockchainImpl implements Blockchain {
public void add(Block block) {
track = repository.startTracking();
if (block == null)
return;
if (block == null)
return;
// keep chain continuity
if (!Arrays.equals(getBestBlock().getHash(),
@ -300,7 +300,7 @@ public class BlockchainImpl implements Blockchain {
private void processBlock(Block block) {
List<TransactionReceipt> receipts = new ArrayList<>();
if(isValid(block)) {
if(isValid(block)) {
if (!block.isGenesis()) {
if (!CONFIG.blockChainOnly()) {
wallet.addTransactions(block.getTransactionsList());
@ -309,26 +309,26 @@ public class BlockchainImpl implements Blockchain {
}
}
this.storeBlock(block, receipts);
} else {
logger.warn("Invalid block with nr: {}", block.getNumber());
}
} else {
logger.warn("Invalid block with nr: {}", block.getNumber());
}
}
private List<TransactionReceipt> applyBlock(Block block) {
private List<TransactionReceipt> applyBlock(Block block) {
int i = 1;
long totalGasUsed = 0;
int i = 1;
long totalGasUsed = 0;
List<TransactionReceipt> reciepts = new ArrayList<>();
for (Transaction tx : block.getTransactionsList()) {
stateLogger.info("apply block: [{}] tx: [{}] ", block.getNumber(), i);
for (Transaction tx : block.getTransactionsList()) {
stateLogger.info("apply block: [{}] tx: [{}] ", block.getNumber(), i);
TransactionExecutor executor = new TransactionExecutor(tx, block.getCoinbase(), track,
programInvokeFactory, block);
executor.execute();
TransactionReceipt receipt = executor.getReceipt();
totalGasUsed += receipt.getCumulativeGasLong();
totalGasUsed += receipt.getCumulativeGasLong();
track.commit();
receipt.setCumulativeGas(totalGasUsed);
@ -347,42 +347,42 @@ public class BlockchainImpl implements Blockchain {
repository.dumpState(block, totalGasUsed, i++, tx.getHash());
reciepts.add(receipt);
}
}
this.addReward(block);
this.addReward(block);
this.updateTotalDifficulty(block);
track.commit();
if(block.getNumber() >= CONFIG.traceStartBlock())
repository.dumpState(block, totalGasUsed, 0, null);
repository.dumpState(block, totalGasUsed, 0, null);
return reciepts;
}
}
/**
* Add reward to block- and every uncle coinbase
* assuming the entire block is valid.
*
* @param block object containing the header and uncles
*/
private void addReward(Block block) {
/**
* Add reward to block- and every uncle coinbase
* assuming the entire block is valid.
*
* @param block object containing the header and uncles
*/
private void addReward(Block block) {
// Add standard block reward
BigInteger totalBlockReward = Block.BLOCK_REWARD;
// Add extra rewards based on number of uncles
if(block.getUncleList().size() > 0) {
for (BlockHeader uncle : block.getUncleList()) {
track.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD);
}
totalBlockReward = totalBlockReward.add(Block.INCLUSION_REWARD
.multiply(BigInteger.valueOf(block.getUncleList().size())));
}
// Add standard block reward
BigInteger totalBlockReward = Block.BLOCK_REWARD;
// Add extra rewards based on number of uncles
if(block.getUncleList().size() > 0) {
for (BlockHeader uncle : block.getUncleList()) {
track.addBalance(uncle.getCoinbase(), Block.UNCLE_REWARD);
}
totalBlockReward = totalBlockReward.add(Block.INCLUSION_REWARD
.multiply(BigInteger.valueOf(block.getUncleList().size())));
}
track.addBalance(block.getCoinbase(), totalBlockReward);
}
}
@Override
@Override
public void storeBlock(Block block, List<TransactionReceipt> receipts) {
/* Debug check to see if the state is still as expected */
@ -391,7 +391,7 @@ public class BlockchainImpl implements Blockchain {
String worldStateRootHash = Hex.toHexString(repository.getRoot());
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();
// in case of rollback hard move the root
@ -402,12 +402,12 @@ public class BlockchainImpl implements Blockchain {
}
blockStore.saveBlock(block, receipts);
this.setBestBlock(block);
this.setBestBlock(block);
if (logger.isDebugEnabled())
logger.debug("block added to the blockChain: index: [{}]", block.getNumber());
logger.debug("block added to the blockChain: index: [{}]", block.getNumber());
if (block.getNumber() % 100 == 0)
logger.info("*** Last block added [ #{} ]", block.getNumber());
logger.info("*** Last block added [ #{} ]", block.getNumber());
}
@ -426,8 +426,8 @@ public class BlockchainImpl implements Blockchain {
}
@Override
public BlockQueue getQueue() {
@Override
public BlockQueue getQueue() {
return blockQueue;
}
@ -453,15 +453,15 @@ public class BlockchainImpl implements Blockchain {
blockQueue.close();
}
@Override
public BigInteger getTotalDifficulty() {
return totalDifficulty;
}
@Override
public BigInteger getTotalDifficulty() {
return totalDifficulty;
}
@Override
public void updateTotalDifficulty(Block block) {
this.totalDifficulty = totalDifficulty.add(block.getCumulativeDifficulty());
}
@Override
public void updateTotalDifficulty(Block block) {
this.totalDifficulty = totalDifficulty.add(block.getCumulativeDifficulty());
}
@Override
public void setTotalDifficulty(BigInteger totalDifficulty) {

View File

@ -4,60 +4,60 @@ import java.math.BigInteger;
public enum Denomination {
WEI(newBigInt(0)),
ADA(newBigInt(3)),
BABBAGE(newBigInt(6)),
SHANNON(newBigInt(9)),
SZABO(newBigInt(12)),
FINNY(newBigInt(15)),
ETHER(newBigInt(18)),
EINSTEIN(newBigInt(21)),
DOUGLAS(newBigInt(42));
private BigInteger amount;
private Denomination(BigInteger value) {
this.amount = value;
}
WEI(newBigInt(0)),
ADA(newBigInt(3)),
BABBAGE(newBigInt(6)),
SHANNON(newBigInt(9)),
SZABO(newBigInt(12)),
FINNY(newBigInt(15)),
ETHER(newBigInt(18)),
EINSTEIN(newBigInt(21)),
DOUGLAS(newBigInt(42));
private BigInteger amount;
private Denomination(BigInteger value) {
this.amount = value;
}
public BigInteger value() {
return amount;
}
public long longValue() {
return value().longValue();
}
public BigInteger value() {
return amount;
}
public long longValue() {
return value().longValue();
}
private static BigInteger newBigInt(int value) {
return BigInteger.valueOf(10).pow(value);
}
public static String toFriendlyString(BigInteger value) {
if(value.compareTo(DOUGLAS.value()) == 1 || value.compareTo(DOUGLAS.value()) == 0) {
return Float.toString(value.divide(DOUGLAS.value()).floatValue()) + " DOUGLAS";
}
else if(value.compareTo(EINSTEIN.value()) == 1 || value.compareTo(EINSTEIN.value()) == 0) {
return Float.toString(value.divide(EINSTEIN.value()).floatValue()) + " EINSTEIN";
}
else if(value.compareTo(ETHER.value()) == 1 || value.compareTo(ETHER.value()) == 0) {
return Float.toString(value.divide(ETHER.value()).floatValue()) + " ETHER";
}
else if(value.compareTo(FINNY.value()) == 1 || value.compareTo(FINNY.value()) == 0) {
return Float.toString(value.divide(FINNY.value()).floatValue()) + " FINNY";
}
else if(value.compareTo(SZABO.value()) == 1 || value.compareTo(SZABO.value()) == 0) {
return Float.toString(value.divide(SZABO.value()).floatValue()) + " SZABO";
}
else if(value.compareTo(SHANNON.value()) == 1 || value.compareTo(SHANNON.value()) == 0) {
return Float.toString(value.divide(SHANNON.value()).floatValue()) + " SHANNON";
}
else if(value.compareTo(BABBAGE.value()) == 1 || value.compareTo(BABBAGE.value()) == 0) {
return Float.toString(value.divide(BABBAGE.value()).floatValue()) + " BABBAGE";
}
else if(value.compareTo(ADA.value()) == 1 || value.compareTo(ADA.value()) == 0) {
return Float.toString(value.divide(ADA.value()).floatValue()) + " ADA";
}
else
return Float.toString(value.divide(WEI.value()).floatValue()) + " WEI";
}
private static BigInteger newBigInt(int value) {
return BigInteger.valueOf(10).pow(value);
}
public static String toFriendlyString(BigInteger value) {
if(value.compareTo(DOUGLAS.value()) == 1 || value.compareTo(DOUGLAS.value()) == 0) {
return Float.toString(value.divide(DOUGLAS.value()).floatValue()) + " DOUGLAS";
}
else if(value.compareTo(EINSTEIN.value()) == 1 || value.compareTo(EINSTEIN.value()) == 0) {
return Float.toString(value.divide(EINSTEIN.value()).floatValue()) + " EINSTEIN";
}
else if(value.compareTo(ETHER.value()) == 1 || value.compareTo(ETHER.value()) == 0) {
return Float.toString(value.divide(ETHER.value()).floatValue()) + " ETHER";
}
else if(value.compareTo(FINNY.value()) == 1 || value.compareTo(FINNY.value()) == 0) {
return Float.toString(value.divide(FINNY.value()).floatValue()) + " FINNY";
}
else if(value.compareTo(SZABO.value()) == 1 || value.compareTo(SZABO.value()) == 0) {
return Float.toString(value.divide(SZABO.value()).floatValue()) + " SZABO";
}
else if(value.compareTo(SHANNON.value()) == 1 || value.compareTo(SHANNON.value()) == 0) {
return Float.toString(value.divide(SHANNON.value()).floatValue()) + " SHANNON";
}
else if(value.compareTo(BABBAGE.value()) == 1 || value.compareTo(BABBAGE.value()) == 0) {
return Float.toString(value.divide(BABBAGE.value()).floatValue()) + " BABBAGE";
}
else if(value.compareTo(ADA.value()) == 1 || value.compareTo(ADA.value()) == 0) {
return Float.toString(value.divide(ADA.value()).floatValue()) + " ADA";
}
else
return Float.toString(value.divide(WEI.value()).floatValue()) + " WEI";
}
}

View File

@ -28,26 +28,26 @@ import org.spongycastle.util.encoders.Hex;
*/
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[] {
"51ba59315b3a95761d0863b05ccc7a7f54703d99",
"e6716f9544a56c530d868e4bfbacb172315bdead", // # (J)
"b9c015918bdaba24b4ff057a92a3873d6eb201be", // # (V)
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // # (A)
"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // # (M)
"e6716f9544a56c530d868e4bfbacb172315bdead", // # (J)
"b9c015918bdaba24b4ff057a92a3873d6eb201be", // # (V)
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // # (A)
"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // # (M)
"cd2a3d9f938e13cd947ec05abc7fe734df8dd826", // # (R)
"6c386a4b26f73c802f34673f7248bb118f97424a", // # (HH)
"e4157b34ea9615cfbde6b4fda419828124b70c78", // # (CH)
"6c386a4b26f73c802f34673f7248bb118f97424a", // # (HH)
"e4157b34ea9615cfbde6b4fda419828124b70c78", // # (CH)
};
private static byte[] zeroHash256 = new byte[32];
private static byte[] zeroHash160 = new byte[20];
private static byte[] zeroHash512 = new byte[64];
private static byte[] zeroHash256 = new byte[32];
private static byte[] zeroHash160 = new byte[20];
private static byte[] zeroHash512 = new byte[64];
public static byte[] PARENT_HASH = zeroHash256;
public static byte[] UNCLES_HASH = EMPTY_LIST_HASH;
public static byte[] COINBASE = zeroHash160;
public static byte[] PARENT_HASH = zeroHash256;
public static byte[] UNCLES_HASH = EMPTY_LIST_HASH;
public static byte[] COINBASE = zeroHash160;
public static byte[] LOG_BLOOM = zeroHash512;
public static byte[] DIFFICULTY = BigInteger.valueOf(2).pow(17).toByteArray();
public static long NUMBER = 0;
@ -59,30 +59,30 @@ public class Genesis extends Block {
private static Block instance;
private Genesis() {
super(PARENT_HASH, UNCLES_HASH, COINBASE, LOG_BLOOM, DIFFICULTY,
NUMBER, GAS_LIMIT, GAS_USED, TIMESTAMP,
EXTRA_DATA, NONCE, null, null);
Trie state = new TrieImpl(null);
private Genesis() {
super(PARENT_HASH, UNCLES_HASH, COINBASE, LOG_BLOOM, DIFFICULTY,
NUMBER, GAS_LIMIT, GAS_USED, TIMESTAMP,
EXTRA_DATA, NONCE, null, null);
Trie state = new TrieImpl(null);
// The proof-of-concept series include a development pre-mine, making the state root hash
// some value stateRoot. The latest documentation should be consulted for the value of the state root.
for (String address : premine) {
AccountState acctState = new AccountState(BigInteger.ZERO, PREMINE_AMOUNT);
state.update(Hex.decode(address), acctState.getEncoded());
for (String address : premine) {
AccountState acctState = new AccountState(BigInteger.ZERO, PREMINE_AMOUNT);
state.update(Hex.decode(address), acctState.getEncoded());
}
setStateRoot(state.getRootHash());
setStateRoot(state.getRootHash());
}
public static Block getInstance() {
if (instance == null) {
instance = new Genesis();
}
return instance;
}
public final static String[] getPremine() {
return premine;
}
public static Block getInstance() {
if (instance == null) {
instance = new Genesis();
}
return instance;
}
public final static String[] getPremine() {
return premine;
}
}

View File

@ -25,8 +25,8 @@ import static org.ethereum.util.ByteUtil.ZERO_BYTE_ARRAY;
*/
public class Transaction {
private static final Logger logger = LoggerFactory.getLogger(Transaction.class);
private static final Logger logger = LoggerFactory.getLogger(Transaction.class);
/* SHA3 hash of the RLP encoded transaction */
private byte[] hash;
@ -107,9 +107,9 @@ public class Transaction {
this.data = transaction.get(5).getRLPData();
// only parse signature in case tx is signed
if(transaction.get(6).getRLPData() != null) {
byte v = transaction.get(6).getRLPData()[0];
byte[] r = transaction.get(7).getRLPData();
byte[] s = transaction.get(8).getRLPData();
byte v = transaction.get(6).getRLPData()[0];
byte[] r = transaction.get(7).getRLPData();
byte[] s = transaction.get(8).getRLPData();
this.signature = ECDSASignature.fromComponents(r, s, v);
} else {
logger.debug("RLP encoded tx is not signed!");
@ -215,16 +215,16 @@ public class Transaction {
}
public byte[] getSender() {
try {
try {
if (sendAddress == null) {
ECKey key = ECKey.signatureToKey(getRawHash(), getSignature().toBase64());
sendAddress = key.getAddress();
}
return sendAddress;
} catch (SignatureException e) {
logger.error(e.getMessage(), e);
}
return null;
return sendAddress;
} catch (SignatureException e) {
logger.error(e.getMessage(), e);
}
return null;
}
public void sign(byte[] privKeyBytes) throws MissingPrivateKeyException {
@ -262,18 +262,18 @@ public class Transaction {
// parse null as 0 for nonce
byte[] nonce = null;
if ( this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0){
nonce = RLP.encodeElement(null);
nonce = RLP.encodeElement(null);
} else {
nonce = RLP.encodeElement(this.nonce);
nonce = RLP.encodeElement(this.nonce);
}
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
byte[] value = RLP.encodeElement(this.value);
byte[] data = RLP.encodeElement(this.data);
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
byte[] value = RLP.encodeElement(this.value);
byte[] data = RLP.encodeElement(this.data);
rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress,
value, data);
rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress,
value, data);
return rlpRaw;
}
@ -284,15 +284,15 @@ public class Transaction {
// parse null as 0 for nonce
byte[] nonce = null;
if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0){
nonce = RLP.encodeElement(null);
nonce = RLP.encodeElement(null);
} else {
nonce = RLP.encodeElement(this.nonce);
nonce = RLP.encodeElement(this.nonce);
}
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
byte[] value = RLP.encodeElement(this.value);
byte[] data = RLP.encodeElement(this.data);
byte[] gasPrice = RLP.encodeElement(this.gasPrice);
byte[] gasLimit = RLP.encodeElement(this.gasLimit);
byte[] receiveAddress = RLP.encodeElement(this.receiveAddress);
byte[] value = RLP.encodeElement(this.value);
byte[] data = RLP.encodeElement(this.data);
byte[] v, r, s;
@ -301,13 +301,13 @@ public class Transaction {
r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r));
s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s));
} else {
v = RLP.encodeElement(EMPTY_BYTE_ARRAY);
r = RLP.encodeElement(EMPTY_BYTE_ARRAY);
s = RLP.encodeElement(EMPTY_BYTE_ARRAY);
v = RLP.encodeElement(EMPTY_BYTE_ARRAY);
r = RLP.encodeElement(EMPTY_BYTE_ARRAY);
s = RLP.encodeElement(EMPTY_BYTE_ARRAY);
}
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit,
receiveAddress, value, data, v, r, s);
this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit,
receiveAddress, value, data, v, r, s);
this.hash = this.getHash();

View File

@ -62,7 +62,7 @@ public class TransactionExecutor {
// VALIDATE THE SENDER
byte[] senderAddress = tx.getSender();
// AccountState senderAccount = repository.getAccountState(senderAddress);
// AccountState senderAccount = repository.getAccountState(senderAddress);
logger.info("tx.sender: [{}]", Hex.toHexString(tx.getSender()));
// VALIDATE THE NONCE

View File

@ -35,12 +35,12 @@ import java.util.concurrent.ConcurrentHashMap;
@Component
public class Wallet {
private Logger logger = LoggerFactory.getLogger("wallet");
private Logger logger = LoggerFactory.getLogger("wallet");
// TODO: a) the values I need to keep for address state is balance & nonce & ECKey
// TODO: b) keep it to be easy accessed by the toAddress()
// private HashMap<Address, BigInteger> rows = new HashMap<>();
// This map of transaction designed
// to approve the tx by external trusted peer
private Map<String, WalletTransaction> walletTransactions = new ConcurrentHashMap<>();
@ -119,7 +119,7 @@ public class Wallet {
}
/***********************************************************************
* 1) the dialog put a pending transaction on the list
* 1) the dialog put a pending transaction on the list
* 2) the dialog send the transaction to a net
* 3) wherever the transaction got in from the wire it will change to approve state
* 4) only after the approve a) Wallet state changes
@ -130,12 +130,12 @@ public class Wallet {
logger.info("pending transaction placed hash: {}", hash );
WalletTransaction walletTransaction = this.walletTransactions.get(hash);
if (walletTransaction != null)
walletTransaction.incApproved();
else {
walletTransaction = new WalletTransaction(transaction);
this.walletTransactions.put(hash, walletTransaction);
}
if (walletTransaction != null)
walletTransaction.incApproved();
else {
walletTransaction = new WalletTransaction(transaction);
this.walletTransactions.put(hash, walletTransaction);
}
this.applyTransaction(transaction);
@ -143,17 +143,17 @@ public class Wallet {
}
public void addTransactions(List<Transaction> transactions) {
for (Transaction transaction : transactions) {
this.addTransaction(transaction);
}
for (Transaction transaction : transactions) {
this.addTransaction(transaction);
}
}
public void removeTransactions(List<Transaction> transactions) {
for (Transaction tx : transactions) {
if (logger.isDebugEnabled())
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString(tx.getHash()));
this.removeTransaction(tx);
}
for (Transaction tx : transactions) {
if (logger.isDebugEnabled())
logger.debug("pending cleanup: tx.hash: [{}]", Hex.toHexString(tx.getHash()));
this.removeTransaction(tx);
}
}
public void removeTransaction(Transaction transaction) {
@ -179,15 +179,15 @@ public class Wallet {
byte[] receiveAddress = transaction.getReceiveAddress();
if(receiveAddress != null) {
Account receiver = rows.get(Hex.toHexString(receiveAddress));
if (receiver != null) {
receiver.addPendingTransaction(transaction);
logger.info("Pending transaction added to " +
"\n account: [{}], " +
"\n tx: [{}]",
Hex.toHexString(receiver.getAddress()), Hex.toHexString(transaction.getHash()));
}
Account receiver = rows.get(Hex.toHexString(receiveAddress));
if (receiver != null) {
receiver.addPendingTransaction(transaction);
logger.info("Pending transaction added to " +
"\n account: [{}], " +
"\n tx: [{}]",
Hex.toHexString(receiver.getAddress()), Hex.toHexString(transaction.getHash()));
}
}
this.notifyListeners();
}
@ -207,7 +207,7 @@ public class Wallet {
*/
public void load() throws IOException, SAXException, ParserConfigurationException {
/**
/**
<wallet high="8933">
<row id=1>
@ -330,8 +330,8 @@ public class Wallet {
}
private void notifyListeners() {
for (WalletListener listener : listeners)
listener.valueChanged();
for (WalletListener listener : listeners)
listener.valueChanged();
}
public interface WalletListener{

View File

@ -69,8 +69,8 @@ import org.spongycastle.util.encoders.Hex;
* See <a href="https://github.com/bitcoinj/bitcoinj/blob/master/core/src/main/java/com/google/bitcoin/core/ECKey.java">bitcoinj on GitHub</a>
*/
public class ECKey implements Serializable {
private static final Logger logger = LoggerFactory.getLogger(ECKey.class);
private static final Logger logger = LoggerFactory.getLogger(ECKey.class);
/** The parameters of the secp256k1 curve that Ethereum uses. */
public static final ECDomainParameters CURVE;
@ -126,7 +126,7 @@ public class ECKey implements Serializable {
public ECKey(@Nullable BigInteger priv, ECPoint pub) {
this.priv = priv;
if(pub == null)
throw new IllegalArgumentException("Public key may not be null");
throw new IllegalArgumentException("Public key may not be null");
this.pub = pub;
}
@ -237,8 +237,8 @@ public class ECKey implements Serializable {
/** Gets the hash160 form of the public key (as seen in addresses). */
public byte[] getAddress() {
if (pubKeyHash == null) {
byte[] pubBytes = this.pub.getEncoded(false);
pubKeyHash = HashUtil.sha3omit12(Arrays.copyOfRange(pubBytes, 1, pubBytes.length));
byte[] pubBytes = this.pub.getEncoded(false);
pubKeyHash = HashUtil.sha3omit12(Arrays.copyOfRange(pubBytes, 1, pubBytes.length));
}
return pubKeyHash;
}
@ -317,9 +317,9 @@ public class ECKey implements Serializable {
}
public static ECDSASignature fromComponents(byte[] r, byte[] s, byte v) {
ECDSASignature signature = fromComponents(r, s);
signature.v = v;
return signature;
ECDSASignature signature = fromComponents(r, s);
signature.v = v;
return signature;
}
/**
@ -343,11 +343,11 @@ public class ECKey implements Serializable {
}
public String toBase64() {
byte[] sigData = new byte[65]; // 1 header + 32 bytes for R + 32 bytes for S
sigData[0] = v;
System.arraycopy(bigIntegerToBytes(this.r, 32), 0, sigData, 1, 32);
System.arraycopy(bigIntegerToBytes(this.s, 32), 0, sigData, 33, 32);
return new String(Base64.encode(sigData), Charset.forName("UTF-8"));
byte[] sigData = new byte[65]; // 1 header + 32 bytes for R + 32 bytes for S
sigData[0] = v;
System.arraycopy(bigIntegerToBytes(this.r, 32), 0, sigData, 1, 32);
System.arraycopy(bigIntegerToBytes(this.s, 32), 0, sigData, 33, 32);
return new String(Base64.encode(sigData), Charset.forName("UTF-8"));
}
@Override
@ -472,7 +472,7 @@ public class ECKey implements Serializable {
return signer.verifySignature(data, signature.r, signature.s);
} catch (NullPointerException npe) {
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures.
// Those signatures are inherently invalid/attack sigs so we just fail them here rather than crash the thread.
// Those signatures are inherently invalid/attack sigs so we just fail them here rather than crash the thread.
logger.error("Caught NPE inside bouncy castle", npe);
return false;
}

View File

@ -35,10 +35,10 @@ public class HashUtil {
}
public static byte[] sha256(byte[] input) {
return sha256digest.digest(input);
return sha256digest.digest(input);
}
public static byte[] sha3(byte[] input) {
public static byte[] sha3(byte[] input) {
ByteArrayWrapper inputByteArray = new ByteArrayWrapper(input);
byte[] result = sha3Cache.get(inputByteArray);
if(result != null)
@ -46,17 +46,17 @@ public class HashUtil {
result = SHA3Helper.sha3(input);
sha3Cache.put(inputByteArray, result);
return result;
}
}
public static byte[] ripemd160(byte[] message) {
Digest digest = new RIPEMD160Digest();
Digest digest = new RIPEMD160Digest();
if (message != null) {
byte[] resBuf = new byte[digest.getDigestSize()];
digest.update(message, 0, message.length);
digest.doFinal(resBuf, 0);
return resBuf;
}
throw new NullPointerException("Can't hash a NULL value");
byte[] resBuf = new byte[digest.getDigestSize()];
digest.update(message, 0, message.length);
digest.doFinal(resBuf, 0);
return resBuf;
}
throw new NullPointerException("Can't hash a NULL value");
}
@ -64,8 +64,8 @@ public class HashUtil {
* Calculates RIGTMOST160(SHA3(input)). This is used in address calculations.
*/
public static byte[] sha3omit12(byte[] input) {
byte[] hash = sha3(input);
return copyOfRange(hash, 12, hash.length);
byte[] hash = sha3(input);
return copyOfRange(hash, 12, hash.length);
}
/**

View File

@ -6,9 +6,9 @@ import org.spongycastle.crypto.digests.SHA3Digest;
import org.spongycastle.util.encoders.Hex;
public class SHA3Helper {
private static int DEFAULT_SIZE = 256;
private static int DEFAULT_SIZE = 256;
public static String sha3String(String message) {
return sha3String(message, new SHA3Digest(DEFAULT_SIZE), true);
}
@ -75,7 +75,7 @@ public class SHA3Helper {
digest.doFinal(hash, 0);
return hash;
}
public enum Size {
S224(224),

View File

@ -11,38 +11,38 @@ import org.spongycastle.util.encoders.Hex;
*/
public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {
private final byte[] data;
private final byte[] data;
public ByteArrayWrapper(byte[] data) {
if (data == null)
throw new NullPointerException("Data must not be null");
this.data = data;
}
public ByteArrayWrapper(byte[] data) {
if (data == null)
throw new NullPointerException("Data must not be null");
this.data = data;
}
public boolean equals(Object other) {
if (!(other instanceof ByteArrayWrapper))
return false;
byte[] otherData = ((ByteArrayWrapper) other).getData();
return FastByteComparisons.compareTo(
data, 0, data.length,
otherData, 0, otherData.length) == 0;
}
public boolean equals(Object other) {
if (!(other instanceof ByteArrayWrapper))
return false;
byte[] otherData = ((ByteArrayWrapper) other).getData();
return FastByteComparisons.compareTo(
data, 0, data.length,
otherData, 0, otherData.length) == 0;
}
@Override
public int hashCode() {
return Arrays.hashCode(data);
}
@Override
public int hashCode() {
return Arrays.hashCode(data);
}
@Override
public int compareTo(ByteArrayWrapper o) {
return FastByteComparisons.compareTo(
data, 0, data.length,
o.getData(), 0, o.getData().length);
}
public byte[] getData() {
return data;
}
@Override
public int compareTo(ByteArrayWrapper o) {
return FastByteComparisons.compareTo(
data, 0, data.length,
o.getData(), 0, o.getData().length);
}
public byte[] getData() {
return data;
}
@Override
public String toString() {

View File

@ -32,15 +32,15 @@ public class ContractDetails {
public ContractDetails() {
}
public ContractDetails(byte[] rlpCode) {
decode(rlpCode);
}
public ContractDetails(Map<DataWord, DataWord> storage, byte[] code) {
}
public ContractDetails(Map<DataWord, DataWord> storage, byte[] code) {
}
public void put(DataWord key, DataWord value) {
public void put(DataWord key, DataWord value) {
if (value.equals(DataWord.ZERO)) {
@ -64,21 +64,21 @@ public class ContractDetails {
this.setDirty(true);
this.rlpEncoded = null;
}
}
public DataWord get(DataWord key) {
public DataWord get(DataWord key) {
if (storageKeys.size() == 0)
return null;
if (storageKeys.size() == 0)
return null;
int foundIndex = storageKeys.indexOf(key);
if (foundIndex != -1) {
int foundIndex = storageKeys.indexOf(key);
if (foundIndex != -1) {
DataWord value = storageValues.get(foundIndex);
return value.clone();
}
else
return null;
}
else
return null;
}
public byte[] getCode() {
return code;
@ -92,47 +92,47 @@ public class ContractDetails {
public byte[] getStorageHash() {
storageTrie = new TrieImpl(null);
storageTrie = new TrieImpl(null);
// calc the trie for root hash
for (int i = 0; i < storageKeys.size(); ++i){
storageTrie.update(storageKeys.get(i).getData(), RLP
.encodeElement(storageValues.get(i).getNoLeadZeroesData()));
storageTrie.update(storageKeys.get(i).getData(), RLP
.encodeElement(storageValues.get(i).getNoLeadZeroesData()));
}
return storageTrie.getRootHash();
}
public void decode(byte[] rlpCode) {
RLPList data = RLP.decode2(rlpCode);
RLPList rlpList = (RLPList) data.get(0);
public void decode(byte[] rlpCode) {
RLPList data = RLP.decode2(rlpCode);
RLPList rlpList = (RLPList) data.get(0);
RLPList keys = (RLPList) rlpList.get(0);
RLPList values = (RLPList) rlpList.get(1);
RLPElement code = (RLPElement) rlpList.get(2);
RLPList keys = (RLPList) rlpList.get(0);
RLPList values = (RLPList) rlpList.get(1);
RLPElement code = (RLPElement) rlpList.get(2);
if (keys.size() > 0) {
storageKeys = new ArrayList<>();
storageValues = new ArrayList<>();
}
if (keys.size() > 0) {
storageKeys = new ArrayList<>();
storageValues = new ArrayList<>();
}
for (int i = 0; i < keys.size(); ++i) {
RLPItem rlpItem = (RLPItem) keys.get(i);
storageKeys.add(new DataWord(rlpItem.getRLPData()));
}
for (int i = 0; i < keys.size(); ++i) {
RLPItem rlpItem = (RLPItem) keys.get(i);
storageKeys.add(new DataWord(rlpItem.getRLPData()));
}
for (int i = 0; i < values.size(); ++i) {
RLPItem rlpItem = (RLPItem) values.get(i);
storageValues.add(new DataWord(rlpItem.getRLPData()));
}
for (int i = 0; i < values.size(); ++i) {
RLPItem rlpItem = (RLPItem) values.get(i);
storageValues.add(new DataWord(rlpItem.getRLPData()));
}
for (int i = 0; i < keys.size(); ++i) {
DataWord key = storageKeys.get(i);
DataWord value = storageValues.get(i);
for (int i = 0; i < keys.size(); ++i) {
DataWord key = storageKeys.get(i);
DataWord value = storageValues.get(i);
storageTrie.update(key.getData(), RLP.encodeElement(value.getNoLeadZeroesData()));
}
}
this.code = (code.getRLPData() == null) ? ByteUtil.EMPTY_BYTE_ARRAY : code.getRLPData();
this.rlpEncoded = rlpCode;
}
this.code = (code.getRLPData() == null) ? ByteUtil.EMPTY_BYTE_ARRAY : code.getRLPData();
this.rlpEncoded = rlpCode;
}
public void setDirty(boolean dirty) {
this.dirty = dirty;
@ -151,38 +151,38 @@ public class ContractDetails {
}
public byte[] getEncoded() {
public byte[] getEncoded() {
if (rlpEncoded == null) {
if (rlpEncoded == null) {
int size = storageKeys == null ? 0 : storageKeys.size();
int size = storageKeys == null ? 0 : storageKeys.size();
byte[][] keys = new byte[size][];
byte[][] values = new byte[size][];
byte[][] keys = new byte[size][];
byte[][] values = new byte[size][];
for (int i = 0; i < size; ++i) {
DataWord key = storageKeys.get(i);
keys[i] = RLP.encodeElement(key.getData());
}
for (int i = 0; i < size; ++i) {
DataWord value = storageValues.get(i);
values[i] = RLP.encodeElement(value.getNoLeadZeroesData());
}
for (int i = 0; i < size; ++i) {
DataWord key = storageKeys.get(i);
keys[i] = RLP.encodeElement(key.getData());
}
for (int i = 0; i < size; ++i) {
DataWord value = storageValues.get(i);
values[i] = RLP.encodeElement(value.getNoLeadZeroesData());
}
byte[] rlpKeysList = RLP.encodeList(keys);
byte[] rlpValuesList = RLP.encodeList(values);
byte[] rlpCode = RLP.encodeElement(code);
byte[] rlpKeysList = RLP.encodeList(keys);
byte[] rlpValuesList = RLP.encodeList(values);
byte[] rlpCode = RLP.encodeElement(code);
this.rlpEncoded = RLP.encodeList(rlpKeysList, rlpValuesList, rlpCode);
}
return rlpEncoded;
}
this.rlpEncoded = RLP.encodeList(rlpKeysList, rlpValuesList, rlpCode);
}
return rlpEncoded;
}
public Map<DataWord, DataWord> getStorage() {
Map<DataWord, DataWord> storage = new HashMap<>();
for (int i = 0; storageKeys != null && i < storageKeys.size(); ++i) {
storage.put(storageKeys.get(i), storageValues.get(i));
}
for (int i = 0; storageKeys != null && i < storageKeys.size(); ++i) {
storage.put(storageKeys.get(i), storageValues.get(i));
}
return Collections.unmodifiableMap(storage);
}

View File

@ -4,28 +4,28 @@ package org.ethereum.db;
* Ethereum generic database interface
*/
public interface Database {
/**
* Get value from database
*
* @param key for which to retrieve the value
* @return the value for the given key
*/
public byte[] get(byte[] key);
/**
* Insert value into database
*
* @param key for the given value
* @param value to insert
*/
public void put(byte[] key, byte[] value);
/**
* Get value from database
*
* @param key for which to retrieve the value
* @return the value for the given key
*/
public byte[] get(byte[] key);
/**
* Delete key/value pair from database
*
* @param key for which to delete the value
*/
/**
* Insert value into database
*
* @param key for the given value
* @param value to insert
*/
public void put(byte[] key, byte[] value);
/**
* Delete key/value pair from database
*
* @param key for which to delete the value
*/
public void delete(byte[] key);
/**

View File

@ -19,39 +19,39 @@ import org.spongycastle.util.encoders.Hex;
/**
* 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:
* Pure Java: https://github.com/dain/leveldb
* JNI binding: https://github.com/fusesource/leveldbjni
* Pure Java: https://github.com/dain/leveldb
* JNI binding: https://github.com/fusesource/leveldbjni
*/
public class DatabaseImpl implements Database {
private static final Logger logger = LoggerFactory.getLogger("db");
private DB db;
private String name;
public DatabaseImpl(String name) {
// Initialize Database
private static final Logger logger = LoggerFactory.getLogger("db");
private DB db;
private String name;
public DatabaseImpl(String name) {
// Initialize Database
this.name = name;
Options options = new Options();
options.createIfMissing(true);
options.compressionType(CompressionType.NONE);
try {
logger.debug("Opening database");
Options options = new Options();
options.createIfMissing(true);
options.compressionType(CompressionType.NONE);
try {
logger.debug("Opening database");
File dbLocation = new File(System.getProperty("user.dir") + "/" +
SystemProperties.CONFIG.databaseDir() + "/");
File fileLocation = new File(dbLocation, name);
if(SystemProperties.CONFIG.databaseReset()) {
destroyDB(fileLocation);
}
if(SystemProperties.CONFIG.databaseReset()) {
destroyDB(fileLocation);
}
logger.debug("Initializing new or existing database: '{}'", name);
db = factory.open(fileLocation, options);
// logger.debug("Showing database stats");
// String stats = DATABASE.getProperty("leveldb.stats");
// logger.debug(stats);
logger.debug("Initializing new or existing database: '{}'", name);
db = factory.open(fileLocation, options);
// logger.debug("Showing database stats");
// String stats = DATABASE.getProperty("leveldb.stats");
// logger.debug(stats);
if (logger.isTraceEnabled()){
@ -66,52 +66,52 @@ public class DatabaseImpl implements Database {
iter.next();
}
}
} catch (IOException ioe) {
logger.error(ioe.getMessage(), ioe);
throw new RuntimeException("Can't initialize database");
}
}
public void destroyDB(File fileLocation) {
logger.debug("Destroying existing database");
Options options = new Options();
try {
factory.destroy(fileLocation, options);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
@Override
public byte[] get(byte[] key) {
return db.get(key);
}
@Override
public void put(byte[] key, byte[] value) {
} catch (IOException ioe) {
logger.error(ioe.getMessage(), ioe);
throw new RuntimeException("Can't initialize database");
}
}
public void destroyDB(File fileLocation) {
logger.debug("Destroying existing database");
Options options = new Options();
try {
factory.destroy(fileLocation, options);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
@Override
public byte[] get(byte[] key) {
return db.get(key);
}
@Override
public void put(byte[] key, byte[] value) {
if(logger.isDebugEnabled())
logger.debug("put: key: [{}], value: [{}]",
Hex.toHexString(key),
Hex.toHexString(value));
db.put(key, value);
}
@Override
public void delete(byte[] key) {
db.put(key, value);
}
@Override
public void delete(byte[] key) {
if(logger.isDebugEnabled())
logger.debug("delete: key: [{}]");
db.delete(key);
}
public DBIterator iterator() {
return db.iterator();
}
public DB getDb() {
return this.db;
}
db.delete(key);
}
public DBIterator iterator() {
return db.iterator();
}
public DB getDb() {
return this.db;
}
@Override
public void close() {
@ -123,15 +123,15 @@ public class DatabaseImpl implements Database {
}
}
public List<ByteArrayWrapper> dumpKeys() {
DBIterator iterator = getDb().iterator();
ArrayList<ByteArrayWrapper> keys = new ArrayList<>();
public List<ByteArrayWrapper> dumpKeys() {
DBIterator iterator = getDb().iterator();
ArrayList<ByteArrayWrapper> keys = new ArrayList<>();
while (iterator.hasNext()) {
ByteArrayWrapper key = new ByteArrayWrapper(iterator.next().getKey());
keys.add(key);
}
Collections.sort((List<ByteArrayWrapper>) keys);
return keys;
}
while (iterator.hasNext()) {
ByteArrayWrapper key = new ByteArrayWrapper(iterator.next().getKey());
keys.add(key);
}
Collections.sort((List<ByteArrayWrapper>) keys);
return keys;
}
}

View File

@ -43,10 +43,10 @@ public class RepositoryImpl implements Repository {
private static final Logger logger = LoggerFactory.getLogger("repository");
private Trie worldState;
private Trie worldState;
private DatabaseImpl detailsDB = null;
private DatabaseImpl stateDB = null;
private DatabaseImpl detailsDB = null;
private DatabaseImpl stateDB = null;
public RepositoryImpl() {
this(DETAILS_DB, STATE_DB);
@ -54,8 +54,8 @@ public class RepositoryImpl implements Repository {
public RepositoryImpl(String detailsDbName, String stateDbName) {
detailsDB = new DatabaseImpl(detailsDbName);
stateDB = new DatabaseImpl(stateDbName);
worldState = new TrieImpl(stateDB.getDb());
stateDB = new DatabaseImpl(stateDbName);
worldState = new TrieImpl(stateDB.getDb());
}
@ -63,8 +63,8 @@ public class RepositoryImpl implements Repository {
public void reset() {
close();
detailsDB = new DatabaseImpl(DETAILS_DB);
stateDB = new DatabaseImpl(STATE_DB);
worldState = new TrieImpl(stateDB.getDb());
stateDB = new DatabaseImpl(STATE_DB);
worldState = new TrieImpl(stateDB.getDb());
}
@Override

View File

@ -49,20 +49,20 @@ public class TrackDatabase implements Database {
public void put(byte[] key, byte[] value) {
if (trackingChanges) {
ByteArrayWrapper wKey = new ByteArrayWrapper(key);
changes.put(wKey, value);
ByteArrayWrapper wKey = new ByteArrayWrapper(key);
changes.put(wKey, value);
} else {
db.put(key, value);
}
}
public byte[] get(byte[] key) {
if(trackingChanges) {
ByteArrayWrapper wKey = new ByteArrayWrapper(key);
if(trackingChanges) {
ByteArrayWrapper wKey = new ByteArrayWrapper(key);
if (deletes.contains(wKey)) return null;
if (changes.get(wKey) != null) return changes.get(wKey);
}
return db.get(key);
return db.get(key);
}
/** Delete object (key) from db **/

View File

@ -13,7 +13,7 @@ import org.ethereum.core.Genesis;
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 void add(Block block);
@ -26,10 +26,10 @@ public interface Blockchain {
public boolean hasParentOnTheChain(Block block);
public void reset();
public void close();
public void updateTotalDifficulty(Block block);
public void updateTotalDifficulty(Block block);
public BigInteger getTotalDifficulty();
public void setTotalDifficulty(BigInteger totalDifficulty);
public byte[] getBestBlockHash();
public byte[] getBestBlockHash();
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty);
TransactionReceipt getTransactionReceiptByHash(byte[] hash);

View File

@ -101,7 +101,7 @@ public class EthereumImpl implements Ethereum {
final Set<PeerInfo> peers = worldManager.getPeerDiscovery().getPeers();
synchronized (peers) {
for (PeerInfo peer : peers) { // it blocks until a peer is available.
if (peer.isOnline() && !excludePeers.contains(peer)) {
if (peer.isOnline() && !excludePeers.contains(peer)) {
logger.info("Found peer: {}", peer.toString());
if (listener != null)
listener.trace(String.format("Found online peer: [ %s ]", peer.toString()));
@ -115,14 +115,14 @@ public class EthereumImpl implements Ethereum {
@Override
public PeerInfo waitForOnlinePeer() {
PeerInfo peer = null;
while (peer == null) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
peer = this.findOnlinePeer();
}
while (peer == null) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
peer = this.findOnlinePeer();
}
return peer;
}
@ -148,11 +148,11 @@ public class EthereumImpl implements Ethereum {
@Override
public void connect(String ip, int port) {
logger.info("Connecting to: {}:{}", ip, port);
logger.info("Connecting to: {}:{}", ip, port);
PeerClient peerClient = worldManager.getActivePeer();
if (peerClient == null)
peerClient = ctx.getBean(PeerClient.class);
peerClient = ctx.getBean(PeerClient.class);
worldManager.setActivePeer(peerClient);
peerClient.connect(ip, port);

View File

@ -19,13 +19,13 @@ import java.util.HashMap;
public interface Repository {
/**
* Create a new account in the database
*
* @param addr of the contract
* @return newly created account state
*/
public AccountState createAccount(byte[] addr);
/**
* Create a new account in the database
*
* @param addr of the contract
* @return newly created account state
*/
public AccountState createAccount(byte[] addr);
/**
@ -34,13 +34,13 @@ public interface Repository {
* false otherwise
*/
public boolean isExist(byte[] addr);
/**
* Retrieve an account
*
* @param addr of the account
* @return account state as stored in the database
*/
/**
* Retrieve an account
*
* @param addr of the account
* @return account state as stored in the database
*/
public AccountState getAccountState(byte[] addr);
/**
@ -143,7 +143,7 @@ public interface Repository {
* @param gasUsed the amount of gas used in the block until that point
* @param txNumber is the number of the transaction for which the dump has to be made
* @param txHash is the hash of the given transaction.
* If null, the block state post coinbase reward is dumped.
* If null, the block state post coinbase reward is dumped.
*/
public void dumpState(Block block, long gasUsed, int txNumber, byte[] txHash);

View File

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

View File

@ -17,24 +17,24 @@ import java.util.*;
/**
* JSON Helper class to format data into ObjectNodes
* to match PyEthereum blockstate output
* to match PyEthereum blockstate output
*
* Dump format:
* {
* "address":
* {
* "nonce": "n1",
* "balance": "b1",
* "stateRoot": "s1",
* "codeHash": "c1",
* "code": "c2",
* "storage":
* {
* "key1": "value1",
* "key2": "value2"
* }
* }
* }
* "address":
* {
* "nonce": "n1",
* "balance": "b1",
* "stateRoot": "s1",
* "codeHash": "c1",
* "code": "c2",
* "storage":
* {
* "key1": "value1",
* "key2": "value2"
* }
* }
* }
*
* www.ethereumJ.com
*
@ -43,17 +43,17 @@ import java.util.*;
*/
public class JSONHelper {
public static void dumpState(ObjectNode statesNode, String address, AccountState state, ContractDetails details) {
public static void dumpState(ObjectNode statesNode, String address, AccountState state, ContractDetails details) {
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
Collections.sort((List<DataWord>) storageKeys);
Collections.sort((List<DataWord>) storageKeys);
ObjectNode account = statesNode.objectNode();
ObjectNode storage = statesNode.objectNode();
for (DataWord key : storageKeys) {
storage.put("0x" + Hex.toHexString(key.getData()),
"0x" + Hex.toHexString(details.getStorage().get(key).getNoLeadZeroesData()));
storage.put("0x" + Hex.toHexString(key.getData()),
"0x" + Hex.toHexString(details.getStorage().get(key).getNoLeadZeroesData()));
}
account.put("balance", state.getBalance() == null ? "0" : state.getBalance().toString());
// account.put("codeHash", details.getCodeHash() == null ? "0x" : "0x" + Hex.toHexString(details.getCodeHash()));
@ -65,17 +65,17 @@ public class JSONHelper {
statesNode.put(address, account);
}
public static void dumpBlock(ObjectNode blockNode, Block block,
long gasUsed, byte[] state, List<ByteArrayWrapper> keys,
Repository repository) {
blockNode.put("coinbase", Hex.toHexString(block.getCoinbase()));
blockNode.put("difficulty", new BigInteger(1, block.calcDifficulty()).toString());
blockNode.put("extra_data", "0x");
blockNode.put("gas_used", String.valueOf(gasUsed));
blockNode.put("nonce", "0x" + Hex.toHexString(block.getNonce()));
blockNode.put("number", String.valueOf(block.getNumber()));
blockNode.put("prevhash", "0x" + Hex.toHexString(block.getParentHash()));
public static void dumpBlock(ObjectNode blockNode, Block block,
long gasUsed, byte[] state, List<ByteArrayWrapper> keys,
Repository repository) {
blockNode.put("coinbase", Hex.toHexString(block.getCoinbase()));
blockNode.put("difficulty", new BigInteger(1, block.calcDifficulty()).toString());
blockNode.put("extra_data", "0x");
blockNode.put("gas_used", String.valueOf(gasUsed));
blockNode.put("nonce", "0x" + Hex.toHexString(block.getNonce()));
blockNode.put("number", String.valueOf(block.getNumber()));
blockNode.put("prevhash", "0x" + Hex.toHexString(block.getParentHash()));
ObjectNode statesNode = blockNode.objectNode();
for (ByteArrayWrapper key : keys) {
@ -95,8 +95,8 @@ public class JSONHelper {
blockNode.put("tx_list_root", ByteUtil.toHexString(block.getTxTrieRoot()));
blockNode.put("uncles_hash", "0x" + Hex.toHexString(block.getUnclesHash()));
// JSONHelper.dumpTransactions(blockNode,
// stateRoot, codeHash, code, storage);
// JSONHelper.dumpTransactions(blockNode,
// stateRoot, codeHash, code, storage);
}
}

View File

@ -15,28 +15,28 @@ import org.ethereum.config.SystemProperties;
public class JSONReader {
public static String loadJSON(String filename) {
String json = "";
if(!SystemProperties.CONFIG.vmTestLoadLocal())
json = getFromUrl("https://raw.githubusercontent.com/ethereum/tests/develop/" + filename);
return json == "" ? json = getFromLocal(filename) : json;
String json = "";
if(!SystemProperties.CONFIG.vmTestLoadLocal())
json = getFromUrl("https://raw.githubusercontent.com/ethereum/tests/develop/" + filename);
return json == "" ? json = getFromLocal(filename) : json;
}
public static String getFromLocal(String filename) {
System.out.println("Loading local file: " + filename);
try {
if(System.getProperty("ETHEREUM_TEST_PATH") == null) {
System.out.println("ETHEREUM_TEST_PATH is not passed as a VM argument, please make sure you pass it with the correct path");
return "";
}
System.out.println("From: " + System.getProperty("ETHEREUM_TEST_PATH"));
File vmTestFile = new File(System.getProperty("ETHEREUM_TEST_PATH") + filename);
return new String(Files.readAllBytes(vmTestFile.toPath()));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Loading local file: " + filename);
try {
if(System.getProperty("ETHEREUM_TEST_PATH") == null) {
System.out.println("ETHEREUM_TEST_PATH is not passed as a VM argument, please make sure you pass it with the correct path");
return "";
}
System.out.println("From: " + System.getProperty("ETHEREUM_TEST_PATH"));
File vmTestFile = new File(System.getProperty("ETHEREUM_TEST_PATH") + filename);
return new String(Files.readAllBytes(vmTestFile.toPath()));
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public static String getFromUrl(String urlToRead) {
URL url;
HttpURLConnection conn;

View File

@ -14,9 +14,9 @@ import org.json.simple.JSONObject;
import org.spongycastle.util.encoders.Hex;
public class Logs {
List<LogInfo> logs = new ArrayList<>();
public Logs(JSONArray jLogs) {
List<LogInfo> logs = new ArrayList<>();
public Logs(JSONArray jLogs) {
for (int i = 0; i < jLogs.size(); ++i){
@ -35,7 +35,7 @@ public class Logs {
LogInfo li = new LogInfo(address, topics, data);
logs.add(li);
}
}
}
public Iterator<LogInfo> getIterator(){

View File

@ -60,24 +60,24 @@ public class TestCase {
JSONObject preJSON = (JSONObject)testCaseJSONObj.get("pre");
JSONObject postJSON = new JSONObject();
if(testCaseJSONObj.containsKey("post")) // in cases where there is no post dictionary (when testing for exceptions for example)
postJSON = (JSONObject)testCaseJSONObj.get("post");
postJSON = (JSONObject)testCaseJSONObj.get("post");
JSONArray callCreates = new JSONArray();
if(testCaseJSONObj.containsKey("callcreates"))
callCreates = (JSONArray)testCaseJSONObj.get("callcreates");
callCreates = (JSONArray)testCaseJSONObj.get("callcreates");
JSONArray logsJSON = new JSONArray();
if(testCaseJSONObj.containsKey("logs"))
logsJSON = (JSONArray)testCaseJSONObj.get("logs");
logsJSON = (JSONArray)testCaseJSONObj.get("logs");
logs = new Logs(logsJSON);
String gasString = "0";
if(testCaseJSONObj.containsKey("gas"))
gasString = testCaseJSONObj.get("gas").toString();
gasString = testCaseJSONObj.get("gas").toString();
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString));
String outString = null;
if(testCaseJSONObj.containsKey("out"))
outString = testCaseJSONObj.get("out").toString();
outString = testCaseJSONObj.get("out").toString();
if (outString != null && outString.length() > 2)
this.out = Hex.decode(outString.substring(2));
else
@ -124,7 +124,7 @@ public class TestCase {
}
public Logs getLogs() {
return logs;
return logs;
}
public byte[] getGas() {

View File

@ -33,7 +33,7 @@ public class TestRunner {
private ProgramTrace trace = null;
public List<String> runTestSuite(TestSuite testSuite) {
Iterator<TestCase> testIterator = testSuite.iterator();
List<String> resultCollector = new ArrayList<>();
@ -137,174 +137,174 @@ public class TestRunner {
logger.info("--------- PRE ---------");
RepositoryDummy repository = loadRepository(testCase.getPre());
try {
try {
/* 2. Create ProgramInvoke - Env/Exec */
Env env = testCase.getEnv();
Exec exec = testCase.getExec();
Logs logs = testCase.getLogs();
/* 2. Create ProgramInvoke - Env/Exec */
Env env = testCase.getEnv();
Exec exec = testCase.getExec();
Logs logs = testCase.getLogs();
byte[] address = exec.getAddress();
byte[] origin = exec.getOrigin();
byte[] caller = exec.getCaller();
byte[] balance = ByteUtil.bigIntegerToBytes(repository.getBalance(exec.getAddress()));
byte[] gasPrice = exec.getGasPrice();
byte[] gas = exec.getGas();
byte[] callValue = exec.getValue();
byte[] msgData = exec.getData();
byte[] lastHash = env.getPreviousHash();
byte[] coinbase = env.getCurrentCoinbase();
long timestamp = new BigInteger(env.getCurrentTimestamp()).longValue();
long number = new BigInteger(env.getCurrentNumber()).longValue();
byte[] difficulty = env.getCurrentDifficlty();
long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue();
byte[] address = exec.getAddress();
byte[] origin = exec.getOrigin();
byte[] caller = exec.getCaller();
byte[] balance = ByteUtil.bigIntegerToBytes(repository.getBalance(exec.getAddress()));
byte[] gasPrice = exec.getGasPrice();
byte[] gas = exec.getGas();
byte[] callValue = exec.getValue();
byte[] msgData = exec.getData();
byte[] lastHash = env.getPreviousHash();
byte[] coinbase = env.getCurrentCoinbase();
long timestamp = new BigInteger(env.getCurrentTimestamp()).longValue();
long number = new BigInteger(env.getCurrentNumber()).longValue();
byte[] difficulty = env.getCurrentDifficlty();
long gaslimit = new BigInteger(env.getCurrentGasLimit()).longValue();
// Origin and caller need to exist in order to be able to execute
if(repository.getAccountState(origin) == null)
repository.createAccount(origin);
if(repository.getAccountState(caller) == null)
repository.createAccount(caller);
// Origin and caller need to exist in order to be able to execute
if(repository.getAccountState(origin) == null)
repository.createAccount(origin);
if(repository.getAccountState(caller) == null)
repository.createAccount(caller);
ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance,
gasPrice, gas, callValue, msgData, lastHash, coinbase,
timestamp, number, difficulty, gaslimit, repository, true);
ProgramInvoke programInvoke = new ProgramInvokeImpl(address, origin, caller, balance,
gasPrice, gas, callValue, msgData, lastHash, coinbase,
timestamp, number, difficulty, gaslimit, repository, true);
/* 3. Create Program - exec.code */
/* 4. run VM */
VM vm = new VM();
Program program = new Program(exec.getCode(), programInvoke);
boolean vmDidThrowAnEception = false;
RuntimeException e = null;
try {
while(!program.isStopped())
vm.step(program);
}
catch (RuntimeException ex) {
vmDidThrowAnEception = true;
e = ex;
}
/* 3. Create Program - exec.code */
/* 4. run VM */
VM vm = new VM();
Program program = new Program(exec.getCode(), programInvoke);
boolean vmDidThrowAnEception = false;
RuntimeException e = null;
try {
while(!program.isStopped())
vm.step(program);
}
catch (RuntimeException ex) {
vmDidThrowAnEception = true;
e = ex;
}
program.saveProgramTraceToFile(testCase.getName());
if(testCase.getPost().size() == 0) {
if(vmDidThrowAnEception != true) {
String output =
String.format("VM was expected to throw an exception");
logger.info(output);
results.add(output);
}
else
logger.info("VM did throw an exception: " + e.toString());
if(vmDidThrowAnEception != true) {
String output =
String.format("VM was expected to throw an exception");
logger.info(output);
results.add(output);
}
else
logger.info("VM did throw an exception: " + e.toString());
}
else {
if(vmDidThrowAnEception) {
String output =
String.format("VM threw an unexpected exception: " + e.toString());
logger.info(output);
results.add(output);
return results;
}
if(vmDidThrowAnEception) {
String output =
String.format("VM threw an unexpected exception: " + e.toString());
logger.info(output);
results.add(output);
return results;
}
this.trace = program.getProgramTrace();
this.trace = program.getProgramTrace();
System.out.println("--------- POST --------");
/* 5. Assert Post values */
for (ByteArrayWrapper key : testCase.getPost().keySet()) {
System.out.println("--------- POST --------");
/* 5. Assert Post values */
for (ByteArrayWrapper key : testCase.getPost().keySet()) {
AccountState accountState = testCase.getPost().get(key);
AccountState accountState = testCase.getPost().get(key);
long expectedNonce = accountState.getNonceLong();
BigInteger expectedBalance = accountState.getBigIntegerBalance();
byte[] expectedCode = accountState.getCode();
long expectedNonce = accountState.getNonceLong();
BigInteger expectedBalance = accountState.getBigIntegerBalance();
byte[] expectedCode = accountState.getCode();
boolean accountExist = (null != repository.getAccountState(key.getData()));
if (!accountExist) {
boolean accountExist = (null != repository.getAccountState(key.getData()));
if (!accountExist) {
String output =
String.format("The expected account does not exist. key: [ %s ]",
Hex.toHexString(key.getData()));
logger.info(output);
results.add(output);
continue;
}
String output =
String.format("The expected account does not exist. key: [ %s ]",
Hex.toHexString(key.getData()));
logger.info(output);
results.add(output);
continue;
}
long actualNonce = repository.getNonce(key.getData()).longValue();
BigInteger actualBalance = repository.getBalance(key.getData());
byte[] actualCode = repository.getCode(key.getData());
if (actualCode == null) actualCode = "".getBytes();
long actualNonce = repository.getNonce(key.getData()).longValue();
BigInteger actualBalance = repository.getBalance(key.getData());
byte[] actualCode = repository.getCode(key.getData());
if (actualCode == null) actualCode = "".getBytes();
if (expectedNonce != actualNonce) {
if (expectedNonce != actualNonce) {
String output =
String.format("The nonce result is different. key: [ %s ], expectedNonce: [ %d ] is actualNonce: [ %d ] ",
Hex.toHexString(key.getData()), expectedNonce, actualNonce);
logger.info(output);
results.add(output);
}
String output =
String.format("The nonce result is different. key: [ %s ], expectedNonce: [ %d ] is actualNonce: [ %d ] ",
Hex.toHexString(key.getData()), expectedNonce, actualNonce);
logger.info(output);
results.add(output);
}
if (!expectedBalance.equals(actualBalance)) {
if (!expectedBalance.equals(actualBalance)) {
String output =
String.format("The balance result is different. key: [ %s ], expectedBalance: [ %s ] is actualBalance: [ %s ] ",
Hex.toHexString(key.getData()), expectedBalance.toString(), actualBalance.toString());
logger.info(output);
results.add(output);
}
String output =
String.format("The balance result is different. key: [ %s ], expectedBalance: [ %s ] is actualBalance: [ %s ] ",
Hex.toHexString(key.getData()), expectedBalance.toString(), actualBalance.toString());
logger.info(output);
results.add(output);
}
if (!Arrays.equals(expectedCode, actualCode)) {
if (!Arrays.equals(expectedCode, actualCode)) {
String output =
String.format("The code result is different. account: [ %s ], expectedCode: [ %s ] is actualCode: [ %s ] ",
Hex.toHexString(key.getData()),
Hex.toHexString(expectedCode),
Hex.toHexString(actualCode));
logger.info(output);
results.add(output);
}
String output =
String.format("The code result is different. account: [ %s ], expectedCode: [ %s ] is actualCode: [ %s ] ",
Hex.toHexString(key.getData()),
Hex.toHexString(expectedCode),
Hex.toHexString(actualCode));
logger.info(output);
results.add(output);
}
// assert storage
Map<DataWord, DataWord> storage = accountState.getStorage();
for (DataWord storageKey : storage.keySet()) {
// assert storage
Map<DataWord, DataWord> storage = accountState.getStorage();
for (DataWord storageKey : storage.keySet()) {
byte[] expectedStValue = storage.get(storageKey).getData();
byte[] expectedStValue = storage.get(storageKey).getData();
ContractDetails contractDetails =
program.getResult().getRepository().getContractDetails(accountState.getAddress());
ContractDetails contractDetails =
program.getResult().getRepository().getContractDetails(accountState.getAddress());
if (contractDetails == null) {
if (contractDetails == null) {
String output =
String.format("Storage raw doesn't exist: key [ %s ], expectedValue: [ %s ]",
Hex.toHexString(storageKey.getData()),
Hex.toHexString(expectedStValue)
);
logger.info(output);
results.add(output);
continue;
}
String output =
String.format("Storage raw doesn't exist: key [ %s ], expectedValue: [ %s ]",
Hex.toHexString(storageKey.getData()),
Hex.toHexString(expectedStValue)
);
logger.info(output);
results.add(output);
continue;
}
Map<DataWord, DataWord> testStorage = contractDetails.getStorage();
DataWord actualValue = testStorage.get(new DataWord(storageKey.getData()));
Map<DataWord, DataWord> testStorage = contractDetails.getStorage();
DataWord actualValue = testStorage.get(new DataWord(storageKey.getData()));
if (actualValue == null ||
if (actualValue == null ||
!Arrays.equals(expectedStValue, actualValue.getNoLeadZeroesData())) {
String output =
String.format("Storage value different: key [ %s ], expectedValue: [ %s ], actualValue: [ %s ]",
Hex.toHexString(storageKey.getData()),
Hex.toHexString(expectedStValue),
actualValue == null ? "" : Hex.toHexString(actualValue.getNoLeadZeroesData()));
logger.info(output);
results.add(output);
}
}
String output =
String.format("Storage value different: key [ %s ], expectedValue: [ %s ], actualValue: [ %s ]",
Hex.toHexString(storageKey.getData()),
Hex.toHexString(expectedStValue),
actualValue == null ? "" : Hex.toHexString(actualValue.getNoLeadZeroesData()));
logger.info(output);
results.add(output);
}
}
/* asset logs */
List<LogInfo> logResult = program.getResult().getLogInfoList();
/* asset logs */
List<LogInfo> logResult = program.getResult().getLogInfoList();
Iterator<LogInfo> postLogs = logs.getIterator();
Iterator<LogInfo> postLogs = logs.getIterator();
int i = 0;
while(postLogs.hasNext()) {
while(postLogs.hasNext()) {
LogInfo expectedLogInfo = postLogs.next();
@ -313,25 +313,25 @@ public class TestRunner {
foundLogInfo = logResult.get(i);
if(foundLogInfo == null) {
String output =
String.format("Expected log [ %s ]", expectedLogInfo.toString());
logger.info(output);
results.add(output);
}
else {
if(!Arrays.equals(expectedLogInfo.getAddress(), foundLogInfo.getAddress())) {
String output =
String.format("Expected address [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getAddress()), Hex.toHexString(foundLogInfo.getAddress()));
logger.info(output);
results.add(output);
}
String output =
String.format("Expected log [ %s ]", expectedLogInfo.toString());
logger.info(output);
results.add(output);
}
else {
if(!Arrays.equals(expectedLogInfo.getAddress(), foundLogInfo.getAddress())) {
String output =
String.format("Expected address [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getAddress()), Hex.toHexString(foundLogInfo.getAddress()));
logger.info(output);
results.add(output);
}
if(!Arrays.equals(expectedLogInfo.getData(), foundLogInfo.getData())) {
String output =
String.format("Expected data [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getData()), Hex.toHexString(foundLogInfo.getData()));
logger.info(output);
results.add(output);
}
if(!Arrays.equals(expectedLogInfo.getData(), foundLogInfo.getData())) {
String output =
String.format("Expected data [ %s ], found [ %s ]", Hex.toHexString(expectedLogInfo.getData()), Hex.toHexString(foundLogInfo.getData()));
logger.info(output);
results.add(output);
}
if(!expectedLogInfo.getBloom().equals(foundLogInfo.getBloom())) {
String output =
@ -342,154 +342,154 @@ public class TestRunner {
results.add(output);
}
if(expectedLogInfo.getTopics().size() != foundLogInfo.getTopics().size()) {
String output =
String.format("Expected number of topics [ %d ], found [ %d ]", expectedLogInfo.getTopics().size(), foundLogInfo.getTopics().size());
logger.info(output);
results.add(output);
}
else {
int j=0;
for(DataWord topic: expectedLogInfo.getTopics()) {
byte[] foundTopic = foundLogInfo.getTopics().get(j).getData();
if(expectedLogInfo.getTopics().size() != foundLogInfo.getTopics().size()) {
String output =
String.format("Expected number of topics [ %d ], found [ %d ]", expectedLogInfo.getTopics().size(), foundLogInfo.getTopics().size());
logger.info(output);
results.add(output);
}
else {
int j=0;
for(DataWord topic: expectedLogInfo.getTopics()) {
byte[] foundTopic = foundLogInfo.getTopics().get(j).getData();
if(!Arrays.equals(topic.getData(), foundTopic)) {
String output =
String.format("Expected topic [ %s ], found [ %s ]", Hex.toHexString(topic.getData()), Hex.toHexString(foundTopic));
logger.info(output);
results.add(output);
}
if(!Arrays.equals(topic.getData(), foundTopic)) {
String output =
String.format("Expected topic [ %s ], found [ %s ]", Hex.toHexString(topic.getData()), Hex.toHexString(foundTopic));
logger.info(output);
results.add(output);
}
++j;
}
}
}
++j;
}
}
}
++i;
}
}
}
}
// TODO: assert that you have no extra accounts in the repository
// TODO: -> basically the deleted by suicide should be deleted
// TODO: -> and no unexpected created
// TODO: assert that you have no extra accounts in the repository
// TODO: -> basically the deleted by suicide should be deleted
// TODO: -> and no unexpected created
List<org.ethereum.vm.CallCreate> resultCallCreates =
program.getResult().getCallCreateList();
List<org.ethereum.vm.CallCreate> resultCallCreates =
program.getResult().getCallCreateList();
// assert call creates
for (int i = 0; i < testCase.getCallCreateList().size(); ++i) {
// assert call creates
for (int i = 0; i < testCase.getCallCreateList().size(); ++i) {
org.ethereum.vm.CallCreate resultCallCreate = null;
if (resultCallCreates != null && resultCallCreates.size() > i) {
resultCallCreate = resultCallCreates.get(i);
}
org.ethereum.vm.CallCreate resultCallCreate = null;
if (resultCallCreates != null && resultCallCreates.size() > i) {
resultCallCreate = resultCallCreates.get(i);
}
CallCreate expectedCallCreate = testCase.getCallCreateList().get(i);
CallCreate expectedCallCreate = testCase.getCallCreateList().get(i);
if (resultCallCreate == null && expectedCallCreate != null) {
if (resultCallCreate == null && expectedCallCreate != null) {
String output =
String.format("Missing call/create invoke: to: [ %s ], data: [ %s ], gas: [ %s ], value: [ %s ]",
Hex.toHexString(expectedCallCreate.getDestination()),
Hex.toHexString(expectedCallCreate.getData()),
Hex.toHexString(expectedCallCreate.getGasLimit()),
Hex.toHexString(expectedCallCreate.getValue()));
logger.info(output);
results.add(output);
String output =
String.format("Missing call/create invoke: to: [ %s ], data: [ %s ], gas: [ %s ], value: [ %s ]",
Hex.toHexString(expectedCallCreate.getDestination()),
Hex.toHexString(expectedCallCreate.getData()),
Hex.toHexString(expectedCallCreate.getGasLimit()),
Hex.toHexString(expectedCallCreate.getValue()));
logger.info(output);
results.add(output);
continue;
}
continue;
}
boolean assertDestination = Arrays.equals(
expectedCallCreate.getDestination(),
resultCallCreate.getDestination());
if (!assertDestination) {
boolean assertDestination = Arrays.equals(
expectedCallCreate.getDestination(),
resultCallCreate.getDestination());
if (!assertDestination) {
String output =
String.format("Call/Create destination is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getDestination()),
Hex.toHexString(resultCallCreate.getDestination()));
logger.info(output);
results.add(output);
}
String output =
String.format("Call/Create destination is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getDestination()),
Hex.toHexString(resultCallCreate.getDestination()));
logger.info(output);
results.add(output);
}
boolean assertData = Arrays.equals(
expectedCallCreate.getData(),
resultCallCreate.getData());
if (!assertData) {
boolean assertData = Arrays.equals(
expectedCallCreate.getData(),
resultCallCreate.getData());
if (!assertData) {
String output =
String.format("Call/Create data is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getData()),
Hex.toHexString(resultCallCreate.getData()));
logger.info(output);
results.add(output);
}
String output =
String.format("Call/Create data is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getData()),
Hex.toHexString(resultCallCreate.getData()));
logger.info(output);
results.add(output);
}
boolean assertGasLimit = Arrays.equals(
expectedCallCreate.getGasLimit(),
resultCallCreate.getGasLimit());
if (!assertGasLimit) {
String output =
String.format("Call/Create gasLimit is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getGasLimit()),
Hex.toHexString(resultCallCreate.getGasLimit()));
logger.info(output);
results.add(output);
}
boolean assertGasLimit = Arrays.equals(
expectedCallCreate.getGasLimit(),
resultCallCreate.getGasLimit());
if (!assertGasLimit) {
String output =
String.format("Call/Create gasLimit is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getGasLimit()),
Hex.toHexString(resultCallCreate.getGasLimit()));
logger.info(output);
results.add(output);
}
boolean assertValue = Arrays.equals(
expectedCallCreate.getValue(),
resultCallCreate.getValue());
if (!assertValue) {
String output =
String.format("Call/Create value is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getValue()),
Hex.toHexString(resultCallCreate.getValue()));
logger.info(output);
results.add(output);
}
}
boolean assertValue = Arrays.equals(
expectedCallCreate.getValue(),
resultCallCreate.getValue());
if (!assertValue) {
String output =
String.format("Call/Create value is different. Expected: [ %s ], result: [ %s ]",
Hex.toHexString(expectedCallCreate.getValue()),
Hex.toHexString(resultCallCreate.getValue()));
logger.info(output);
results.add(output);
}
}
// assert out
byte[] expectedHReturn = testCase.getOut();
byte[] actualHReturn = EMPTY_BYTE_ARRAY;
if (program.getResult().getHReturn() != null) {
actualHReturn = program.getResult().getHReturn().array();
}
// assert out
byte[] expectedHReturn = testCase.getOut();
byte[] actualHReturn = EMPTY_BYTE_ARRAY;
if (program.getResult().getHReturn() != null) {
actualHReturn = program.getResult().getHReturn().array();
}
if (!Arrays.equals(expectedHReturn, actualHReturn)) {
if (!Arrays.equals(expectedHReturn, actualHReturn)) {
String output =
String.format("HReturn is different. Expected hReturn: [ %s ], actual hReturn: [ %s ]",
Hex.toHexString(expectedHReturn),
Hex.toHexString(actualHReturn));
logger.info(output);
results.add(output);
}
String output =
String.format("HReturn is different. Expected hReturn: [ %s ], actual hReturn: [ %s ]",
Hex.toHexString(expectedHReturn),
Hex.toHexString(actualHReturn));
logger.info(output);
results.add(output);
}
// assert gas
BigInteger expectedGas = new BigInteger(testCase.getGas());
BigInteger actualGas = new BigInteger(gas).subtract(BigInteger.valueOf(program.getResult().getGasUsed()));
// assert gas
BigInteger expectedGas = new BigInteger(testCase.getGas());
BigInteger actualGas = new BigInteger(gas).subtract(BigInteger.valueOf(program.getResult().getGasUsed()));
if (!expectedGas.equals(actualGas)) {
if (!expectedGas.equals(actualGas)) {
String output =
String.format("Gas remaining is different. Expected gas remaining: [ %s ], actual gas remaining: [ %s ]",
expectedGas.toString() ,
actualGas.toString());
logger.info(output);
results.add(output);
}
/*
* end of if(testCase.getPost().size() == 0)
*/
String output =
String.format("Gas remaining is different. Expected gas remaining: [ %s ], actual gas remaining: [ %s ]",
expectedGas.toString() ,
actualGas.toString());
logger.info(output);
results.add(output);
}
/*
* end of if(testCase.getPost().size() == 0)
*/
}
return results;
} finally {
// repository.close();
}
return results;
} finally {
// repository.close();
}
}
public org.ethereum.core.Transaction createTransaction(Transaction tx){
@ -513,7 +513,7 @@ public class TestRunner {
RepositoryDummy track = new RepositoryDummy();
/* 1. Store pre-exist accounts - Pre */
/* 1. Store pre-exist accounts - Pre */
for (ByteArrayWrapper key : pre.keySet()) {
AccountState accountState = pre.get(key);

View File

@ -35,13 +35,13 @@ public class WorldManager {
private static final Logger logger = LoggerFactory.getLogger("general");
@Autowired
private Blockchain blockchain;
private Blockchain blockchain;
@Autowired
private Repository repository;
private Repository repository;
@Autowired
private Wallet wallet;
private Wallet wallet;
@Autowired
private PeerClient activePeer;
@ -72,7 +72,7 @@ public class WorldManager {
byte[] cbAddr = HashUtil.sha3(secret.getBytes());
wallet.importKey(cbAddr);
}
public void addListener(EthereumListener listener) {
logger.info("Ethereum listener added");
((EthereumListenerWrapper)this.listener).addListener(listener);
@ -109,7 +109,7 @@ public class WorldManager {
}
public PeerDiscovery getPeerDiscovery() {
return peerDiscovery;
return peerDiscovery;
}
public EthereumListener getListener() {
@ -117,20 +117,20 @@ public class WorldManager {
}
public void setWallet(Wallet wallet) {
this.wallet = wallet;
this.wallet = wallet;
}
public Repository getRepository() {
return repository;
}
public Blockchain getBlockchain() {
return blockchain;
}
public Wallet getWallet() {
return wallet;
}
public Repository getRepository() {
return repository;
}
public Blockchain getBlockchain() {
return blockchain;
}
public Wallet getWallet() {
return wallet;
}
public void setActivePeer(PeerClient peer) {
this.activePeer = peer;
@ -141,10 +141,10 @@ public class WorldManager {
}
public Set<Transaction> getPendingTransactions() {
return pendingTransactions;
return pendingTransactions;
}
public boolean isBlockchainLoading(){
public boolean isBlockchainLoading(){
return blockchain.getQueue().size() > 2;
}

View File

@ -34,38 +34,38 @@ public class Miner {
private boolean stop = false;
/**
* Adds a nonce to given block which complies with the given difficulty
*
* For the PoC series, we use a simplified proof-of-work.
* This is not ASIC resistant and is meant merely as a placeholder.
* It utilizes the bare SHA3 hash function to secure the block chain by requiring
* the SHA3 hash of the concatenation of the nonce and the headers SHA3 hash to be
* sufficiently low. It is formally defined as PoW:
*
* PoW(H, n) BE(SHA3(SHA3(RLP(H!n)) n))
*
* where:
* RLP(H!n) is the RLP encoding of the block header H, not including the
* final nonce component;
* SHA3 is the SHA3 hash function accepting an arbitrary length series of
* bytes and evaluating to a series of 32 bytes (i.e. 256-bit);
* n is the nonce, a series of 32 bytes;
* o is the series concatenation operator;
* BE(X) evaluates to the value equal to X when interpreted as a
* big-endian-encoded integer.
*
* @param newBlock without a valid nonce
* @param difficulty - the mining difficulty
* @return true if valid nonce has been added to the block
*/
public boolean mine(Block newBlock, byte[] difficulty) {
/**
* Adds a nonce to given block which complies with the given difficulty
*
* For the PoC series, we use a simplified proof-of-work.
* This is not ASIC resistant and is meant merely as a placeholder.
* It utilizes the bare SHA3 hash function to secure the block chain by requiring
* the SHA3 hash of the concatenation of the nonce and the headers SHA3 hash to be
* sufficiently low. It is formally defined as PoW:
*
* PoW(H, n) BE(SHA3(SHA3(RLP(H!n)) n))
*
* where:
* RLP(H!n) is the RLP encoding of the block header H, not including the
* final nonce component;
* SHA3 is the SHA3 hash function accepting an arbitrary length series of
* bytes and evaluating to a series of 32 bytes (i.e. 256-bit);
* n is the nonce, a series of 32 bytes;
* o is the series concatenation operator;
* BE(X) evaluates to the value equal to X when interpreted as a
* big-endian-encoded integer.
*
* @param newBlock without a valid nonce
* @param difficulty - the mining difficulty
* @return true if valid nonce has been added to the block
*/
public boolean mine(Block newBlock, byte[] difficulty) {
// eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; }
stop = false;
BigInteger max = BigInteger.valueOf(2).pow(255);
byte[] target = BigIntegers.asUnsignedByteArray(32,
max.divide(new BigInteger(1, difficulty)));
BigInteger max = BigInteger.valueOf(2).pow(255);
byte[] target = BigIntegers.asUnsignedByteArray(32,
max.divide(new BigInteger(1, difficulty)));
long newGasLimit = Math.max(125000,
@ -74,10 +74,10 @@ public class Miner {
byte[] hash = SHA3Helper.sha3(newBlock.getEncodedWithoutNonce());
byte[] testNonce = new byte[32];
byte[] concat;
while(ByteUtil.increment(testNonce) && !stop) {
byte[] testNonce = new byte[32];
byte[] concat;
while(ByteUtil.increment(testNonce) && !stop) {
if (testNonce[31] == 0 && testNonce[30] == 0){
System.out.println("mining: " + new BigInteger(1, testNonce));
@ -85,15 +85,15 @@ public class Miner {
if (testNonce[31] == 0)
sleep();
concat = Arrays.concatenate(hash, testNonce);
byte[] result = SHA3Helper.sha3(concat);
if(FastByteComparisons.compareTo(result, 0, 32, target, 0, 32) < 0) {
newBlock.setNonce(testNonce);
return true;
}
}
return false; // couldn't find a valid nonce
}
concat = Arrays.concatenate(hash, testNonce);
byte[] result = SHA3Helper.sha3(concat);
if(FastByteComparisons.compareTo(result, 0, 32, target, 0, 32) < 0) {
newBlock.setNonce(testNonce);
return true;
}
}
return false; // couldn't find a valid nonce
}
public void stop(){
stop = true;

View File

@ -25,42 +25,42 @@ import java.util.concurrent.ConcurrentLinkedQueue;
@Component
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 */
private Deque<byte[]> blockHashQueue = new ArrayDeque<>();
/** Queue with blocks to be validated and added to the blockchain */
private Queue<Block> blockReceivedQueue = new ConcurrentLinkedQueue<>();
/** Highest known total difficulty, representing the heaviest chain on the network */
/** The list of hashes of the heaviest chain on the network,
* for which this client doesn't have the blocks yet */
private Deque<byte[]> blockHashQueue = new ArrayDeque<>();
/** Queue with blocks to be validated and added to the blockchain */
private Queue<Block> blockReceivedQueue = new ConcurrentLinkedQueue<>();
/** Highest known total difficulty, representing the heaviest chain on the network */
private BigInteger highestTotalDifficulty;
/** 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");
@Autowired
Blockchain blockchain;
public BlockQueue() {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
nudgeQueue();
}
}, 10, 10);
}
public BlockQueue() {
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
nudgeQueue();
}
}, 10, 10);
}
/**
* Processing the queue adding blocks to the chain.
*/
private void nudgeQueue() {
if (blockReceivedQueue.isEmpty())
return;
logger.info("BlockQueue size: {}", blockReceivedQueue.size());
/**
* Processing the queue adding blocks to the chain.
*/
private void nudgeQueue() {
if (blockReceivedQueue.isEmpty())
return;
logger.info("BlockQueue size: {}", blockReceivedQueue.size());
while(!blockReceivedQueue.isEmpty()){
Block block = blockReceivedQueue.poll();
@ -68,27 +68,27 @@ public class BlockQueue {
blockchain.tryToConnect(block);
}
}
}
/**
* Add a list of blocks to the processing queue.
* The list is validated by making sure the first block in the received list of blocks
* is the next expected block number of the queue.
*
* The queue is configured to contain a maximum number of blocks to avoid memory issues
* If the list exceeds that, the rest of the received blocks in the list are discarded.
*
* @param blockList - the blocks received from a peer to be added to the queue
*/
public void addBlocks(List<Block> blockList) {
/**
* Add a list of blocks to the processing queue.
* The list is validated by making sure the first block in the received list of blocks
* is the next expected block number of the queue.
*
* The queue is configured to contain a maximum number of blocks to avoid memory issues
* If the list exceeds that, the rest of the received blocks in the list are discarded.
*
* @param blockList - the blocks received from a peer to be added to the queue
*/
public void addBlocks(List<Block> blockList) {
blockReceivedQueue.addAll(blockList);
lastBlock = blockList.get(blockList.size() - 1);
logger.info("Blocks waiting to be proceed: queue.size: [{}] lastBlock.number: [{}]" ,
blockReceivedQueue.size(),
logger.info("Blocks waiting to be proceed: queue.size: [{}] lastBlock.number: [{}]" ,
blockReceivedQueue.size(),
lastBlock.getNumber());
}
}
/**
* adding single block to the queue usually
@ -104,49 +104,49 @@ public class BlockQueue {
blockReceivedQueue.size(),
lastBlock.getNumber());
}
/**
* Returns the last block in the queue. If the queue is empty,
* this will return the last block added to the blockchain.
*
* @return The last known block this client on the network
* and will never return <code>null</code> as there is
* always the Genesis block at the start of the chain.
*/
public Block getLastBlock() {
if (blockReceivedQueue.isEmpty())
return blockchain.getBestBlock();
return lastBlock;
}
/**
* Returns the last block in the queue. If the queue is empty,
* this will return the last block added to the blockchain.
*
* @return The last known block this client on the network
* and will never return <code>null</code> as there is
* always the Genesis block at the start of the chain.
*/
public Block getLastBlock() {
if (blockReceivedQueue.isEmpty())
return blockchain.getBestBlock();
return lastBlock;
}
/**
* Reset the queue of hashes of blocks to be retrieved
* and add the best hash to the top of the queue
*
* @param hash - the best hash
*/
public void setBestHash(byte[] hash) {
blockHashQueue.clear();
blockHashQueue.addLast(hash);
}
/**
* Reset the queue of hashes of blocks to be retrieved
* and add the best hash to the top of the queue
*
* @param hash - the best hash
*/
public void setBestHash(byte[] hash) {
blockHashQueue.clear();
blockHashQueue.addLast(hash);
}
/**
* Returns the last added hash to the queue representing
* the latest known block on the network
*
* @return The best hash on the network known to the client
*/
public byte[] getBestHash() {
return blockHashQueue.peekLast();
}
/**
* Returns the last added hash to the queue representing
* the latest known block on the network
*
* @return The best hash on the network known to the client
*/
public byte[] getBestHash() {
return blockHashQueue.peekLast();
}
public void addHash(byte[] hash) {
blockHashQueue.addLast(hash);
public void addHash(byte[] hash) {
blockHashQueue.addLast(hash);
if (logger.isTraceEnabled()){
logger.trace("Adding hash to a hashQueue: [{}]" , Hex.toHexString(hash));
}
}
}
public void returnHashes(List<byte[]> hashes){
@ -158,20 +158,20 @@ public class BlockQueue {
public void addNewBlockHash(byte[] hash){
blockHashQueue.addFirst(hash);
}
/**
* Return a list of hashes from blocks that still need to be downloaded.
*
* @return A list of hashes for which blocks need to be retrieved.
*/
public List<byte[]> getHashes() {
/**
* Return a list of hashes from blocks that still need to be downloaded.
*
* @return A list of hashes for which blocks need to be retrieved.
*/
public List<byte[]> getHashes() {
List<byte[]> hashes = new ArrayList<>();
while (!blockHashQueue.isEmpty() && hashes.size() < CONFIG.maxBlocksAsk()) {
hashes.add(blockHashQueue.removeLast());
}
return hashes;
}
List<byte[]> hashes = new ArrayList<>();
while (!blockHashQueue.isEmpty() && hashes.size() < CONFIG.maxBlocksAsk()) {
hashes.add(blockHashQueue.removeLast());
}
return hashes;
}
// a bit ugly but really gives
// good result
@ -179,39 +179,39 @@ public class BlockQueue {
logger.info("Block hashes list size: [{}]", blockHashQueue.size());
}
private class BlockByIndexComparator implements Comparator<Block> {
private class BlockByIndexComparator implements Comparator<Block> {
@Override
public int compare(Block o1, Block o2) {
@Override
public int compare(Block o1, Block o2) {
if (o1 == null || o2 == null)
throw new NullPointerException();
if (o1 == null || o2 == null)
throw new NullPointerException();
if (o1.getNumber() > o2.getNumber())
return 1;
if (o1.getNumber() < o2.getNumber())
return -1;
if (o1.getNumber() > o2.getNumber())
return 1;
if (o1.getNumber() < o2.getNumber())
return -1;
return 0;
}
}
return 0;
}
}
public BigInteger getHighestTotalDifficulty() {
return highestTotalDifficulty;
}
return highestTotalDifficulty;
}
public void setHighestTotalDifficulty(BigInteger highestTotalDifficulty) {
this.highestTotalDifficulty = highestTotalDifficulty;
}
public void setHighestTotalDifficulty(BigInteger highestTotalDifficulty) {
this.highestTotalDifficulty = highestTotalDifficulty;
}
/**
* Returns the current number of blocks in the queue
*
* @return the current number of blocks in the queue
*/
public int size() {
return blockReceivedQueue.size();
}
/**
* Returns the current number of blocks in the queue
*
* @return the current number of blocks in the queue
*/
public int size() {
return blockReceivedQueue.size();
}
public boolean isHashesEmpty(){
return blockHashQueue.size() == 0;
@ -222,12 +222,12 @@ public class BlockQueue {
this.blockReceivedQueue.clear();
}
/**
* Cancel and purge the timer-thread that
* processes the blocks in the queue
*/
public void close() {
timer.cancel();
timer.purge();
}
/**
* Cancel and purge the timer-thread that
* processes the blocks in the queue
*/
public void close() {
timer.cancel();
timer.purge();
}
}

View File

@ -16,17 +16,17 @@ import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* This class contains the logic for sending messages in a queue
* This class contains the logic for sending messages in a queue
*
* Messages open by send and answered by receive of appropriate message
* PING by PONG
* GET_PEERS by PEERS
* GET_TRANSACTIONS by TRANSACTIONS
* GET_BLOCK_HASHES by BLOCK_HASHES
* GET_BLOCKS by BLOCKS
* Messages open by send and answered by receive of appropriate message
* PING by PONG
* GET_PEERS by PEERS
* GET_TRANSACTIONS by TRANSACTIONS
* GET_BLOCK_HASHES by BLOCK_HASHES
* GET_BLOCKS by BLOCKS
*
* The following messages will not be answered:
* PONG, PEERS, HELLO, STATUS, TRANSACTIONS, BLOCKS
* The following messages will not be answered:
* PONG, PEERS, HELLO, STATUS, TRANSACTIONS, BLOCKS
*
* @author Roman Mandeleil
*/
@ -34,11 +34,11 @@ import java.util.concurrent.ConcurrentLinkedQueue;
@Scope("prototype")
public class MessageQueue {
private static final Logger logger = LoggerFactory.getLogger("net");
private static final Logger logger = LoggerFactory.getLogger("net");
private Queue<MessageRoundtrip> messageQueue = new ConcurrentLinkedQueue<>();
private ChannelHandlerContext ctx = null;
private final Timer timer = new Timer("MessageQueue");
private Queue<MessageRoundtrip> messageQueue = new ConcurrentLinkedQueue<>();
private ChannelHandlerContext ctx = null;
private final Timer timer = new Timer("MessageQueue");
@Autowired
WorldManager worldManager;
@ -55,67 +55,67 @@ public class MessageQueue {
}, 10, 10);
}
public void sendMessage(Message msg) {
public void sendMessage(Message msg) {
if (msg instanceof PingMessage && hasPing)
return;
if (msg instanceof PingMessage && !hasPing)
hasPing = true;
messageQueue.add(new MessageRoundtrip(msg));
}
messageQueue.add(new MessageRoundtrip(msg));
}
public void receivedMessage(Message msg) throws InterruptedException {
public void receivedMessage(Message msg) throws InterruptedException {
worldManager.getListener().trace("[Recv: " + msg + "]");
if (messageQueue.peek() != null) {
MessageRoundtrip messageRoundtrip = messageQueue.peek();
Message waitingMessage = messageRoundtrip.getMsg();
if (messageQueue.peek() != null) {
MessageRoundtrip messageRoundtrip = messageQueue.peek();
Message waitingMessage = messageRoundtrip.getMsg();
if (waitingMessage instanceof PingMessage) hasPing = false;
if (waitingMessage.getAnswerMessage() != null
&& msg.getClass() == waitingMessage.getAnswerMessage()) {
messageRoundtrip.answer();
logger.debug("Message round trip covered: [{}] ",
messageRoundtrip.getMsg().getClass());
}
}
}
if (waitingMessage.getAnswerMessage() != null
&& msg.getClass() == waitingMessage.getAnswerMessage()) {
messageRoundtrip.answer();
logger.debug("Message round trip covered: [{}] ",
messageRoundtrip.getMsg().getClass());
}
}
}
private void removeAnsweredMessage(MessageRoundtrip messageRoundtrip) {
if (messageRoundtrip != null && messageRoundtrip.isAnswered())
messageQueue.remove();
}
private void removeAnsweredMessage(MessageRoundtrip messageRoundtrip) {
if (messageRoundtrip != null && messageRoundtrip.isAnswered())
messageQueue.remove();
}
private void nudgeQueue() {
// remove last answered message on the queue
removeAnsweredMessage(messageQueue.peek());
// Now send the next message
sendToWire(messageQueue.peek());
}
private void nudgeQueue() {
// remove last answered message on the queue
removeAnsweredMessage(messageQueue.peek());
// Now send the next message
sendToWire(messageQueue.peek());
}
private void sendToWire(MessageRoundtrip messageRoundtrip) {
private void sendToWire(MessageRoundtrip messageRoundtrip) {
if (messageRoundtrip != null && messageRoundtrip.getRetryTimes() == 0) {
// TODO: retry logic || messageRoundtrip.hasToRetry()){
if (messageRoundtrip != null && messageRoundtrip.getRetryTimes() == 0) {
// TODO: retry logic || messageRoundtrip.hasToRetry()){
Message msg = messageRoundtrip.getMsg();
Message msg = messageRoundtrip.getMsg();
EthereumListener listener = worldManager.getListener();
listener.onSendMessage(msg);
ctx.writeAndFlush(msg);
ctx.writeAndFlush(msg);
if (msg.getAnswerMessage() == null)
messageQueue.remove();
else {
messageRoundtrip.incRetryTimes();
messageRoundtrip.saveTime();
}
}
}
if (msg.getAnswerMessage() == null)
messageQueue.remove();
else {
messageRoundtrip.incRetryTimes();
messageRoundtrip.saveTime();
}
}
}
public void close(){
timer.cancel();

View File

@ -12,41 +12,41 @@ import org.ethereum.net.message.Message;
*/
public class MessageRoundtrip {
private Message msg = null;
long lastTimestamp = 0;
long retryTimes = 0;
boolean answered = false;
private Message msg = null;
long lastTimestamp = 0;
long retryTimes = 0;
boolean answered = false;
public MessageRoundtrip(Message msg) {
this.msg = msg;
saveTime();
}
public MessageRoundtrip(Message msg) {
this.msg = msg;
saveTime();
}
public boolean isAnswered() {
return answered;
}
public boolean isAnswered() {
return answered;
}
public void answer() {
answered = true;
}
public void answer() {
answered = true;
}
public long getRetryTimes() {
return retryTimes;
}
public long getRetryTimes() {
return retryTimes;
}
public void incRetryTimes() {
++retryTimes;
}
public void incRetryTimes() {
++retryTimes;
}
public void saveTime() {
lastTimestamp = System.currentTimeMillis();
}
public void saveTime() {
lastTimestamp = System.currentTimeMillis();
}
public boolean hasToRetry() {
return 20000 < System.currentTimeMillis() - lastTimestamp;
}
public boolean hasToRetry() {
return 20000 < System.currentTimeMillis() - lastTimestamp;
}
public Message getMsg() {
return msg;
}
public Message getMsg() {
return msg;
}
}

View File

@ -6,43 +6,43 @@ package org.ethereum.net.client;
public class Capability implements Comparable<Capability> {
public final static String P2P = "p2p";
public final static String ETH = "eth";
public final static String SHH = "shh";
private String name;
private byte version;
public final static String ETH = "eth";
public final static String SHH = "shh";
private String name;
private byte version;
public Capability(String name, byte version) {
this.name = name;
this.version = version;
}
public String getName() {
return name;
}
public Capability(String name, byte version) {
this.name = name;
this.version = version;
}
public String getName() {
return name;
}
public byte getVersion() {
return version;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Capability)) return false;
public byte getVersion() {
return version;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof Capability)) return false;
Capability other = (Capability)obj;
if (this.name == null)
return other.name == null;
else
return this.name.equals(other.name) && this.version == other.version;
}
Capability other = (Capability)obj;
if (this.name == null)
return other.name == null;
else
return this.name.equals(other.name) && this.version == other.version;
}
@Override
public int compareTo(Capability o) {
return this.name.compareTo(o.name);
}
public String toString() {
return name + ":" + version;
}
@Override
public int compareTo(Capability o) {
return this.name.compareTo(o.name);
}
public String toString() {
return name + ":" + version;
}
}

View File

@ -43,7 +43,7 @@ public class PeerClient {
public void connect(String host, int port) {
EventLoopGroup workerGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
worldManager.getListener().trace("Connecting to: " + host + ":" + port);
try {
@ -66,9 +66,9 @@ public class PeerClient {
logger.debug("Connection is closed");
} catch (Exception e) {
logger.debug("Exception: {} ({})", e.getMessage(), e.getClass().getName());
logger.debug("Exception: {} ({})", e.getMessage(), e.getClass().getName());
} finally {
workerGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}

View File

@ -18,66 +18,66 @@ import org.ethereum.util.Utils;
*/
public class BlockHashesMessage extends EthMessage {
/** List of block hashes from the peer ordered from child to parent */
private List<byte[]> blockHashes;
/** List of block hashes from the peer ordered from child to parent */
private List<byte[]> blockHashes;
public BlockHashesMessage(byte[] payload) {
super(payload);
}
public BlockHashesMessage(byte[] payload) {
super(payload);
}
public BlockHashesMessage(List<byte[]> blockHashes) {
this.blockHashes = blockHashes;
parsed = true;
}
public BlockHashesMessage(List<byte[]> blockHashes) {
this.blockHashes = blockHashes;
parsed = true;
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
blockHashes = new ArrayList<>();
for (int i = 1; i < paramsList.size(); ++i) {
RLPItem rlpData = ((RLPItem) paramsList.get(i));
blockHashes.add(rlpData.getRLPData());
}
parsed = true;
}
blockHashes = new ArrayList<>();
for (int i = 1; i < paramsList.size(); ++i) {
RLPItem rlpData = ((RLPItem) paramsList.get(i));
blockHashes.add(rlpData.getRLPData());
}
parsed = true;
}
private void encode() {
List<byte[]> encodedElements = new ArrayList<>();
encodedElements.add(RLP.encodeByte(BLOCK_HASHES.asByte()));
for (byte[] blockHash : blockHashes)
encodedElements.add(RLP.encodeElement(blockHash));
byte[][] encodedElementArray = encodedElements
.toArray(new byte[encodedElements.size()][]);
this.encoded = RLP.encodeList(encodedElementArray);
}
private void encode() {
List<byte[]> encodedElements = new ArrayList<>();
encodedElements.add(RLP.encodeByte(BLOCK_HASHES.asByte()));
for (byte[] blockHash : blockHashes)
encodedElements.add(RLP.encodeElement(blockHash));
byte[][] encodedElementArray = encodedElements
.toArray(new byte[encodedElements.size()][]);
this.encoded = RLP.encodeList(encodedElementArray);
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
public List<byte[]> getBlockHashes() {
if (!parsed) parse();
return blockHashes;
}
public List<byte[]> getBlockHashes() {
if (!parsed) parse();
return blockHashes;
}
@Override
public EthMessageCodes getCommand(){
return EthMessageCodes.BLOCK_HASHES;
}
@Override
public String toString() {
if (!parsed) parse();
StringBuffer sb = Utils.getHashlistShort(this.blockHashes);
return "[" + this.getCommand().name() + sb.toString() + "] (" + this.blockHashes.size() + ")";
}
@Override
public String toString() {
if (!parsed) parse();
StringBuffer sb = Utils.getHashlistShort(this.blockHashes);
return "[" + this.getCommand().name() + sb.toString() + "] (" + this.blockHashes.size() + ")";
}
}

View File

@ -17,28 +17,28 @@ import static org.ethereum.net.eth.EthMessageCodes.BLOCKS;
*/
public class BlocksMessage extends EthMessage {
private List<Block> blocks;
private List<Block> blocks;
public BlocksMessage(byte[] encoded) {
super(encoded);
}
public BlocksMessage(byte[] encoded) {
super(encoded);
}
public BlocksMessage(List<Block> blocks){
this.blocks = blocks;
parsed = true;
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
blocks = new ArrayList<>();
for (int i = 1; i < paramsList.size(); ++i) {
RLPList rlpData = ((RLPList) paramsList.get(i));
Block blockData = new Block(rlpData.getRLPData());
blocks.add(blockData);
}
parsed = true;
}
blocks = new ArrayList<>();
for (int i = 1; i < paramsList.size(); ++i) {
RLPList rlpData = ((RLPList) paramsList.get(i));
Block blockData = new Block(rlpData.getRLPData());
blocks.add(blockData);
}
parsed = true;
}
private void encode() {
@ -56,34 +56,34 @@ public class BlocksMessage extends EthMessage {
}
@Override
public byte[] getEncoded() {
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
return encoded;
}
public List<Block> getBlocks() {
if (!parsed) parse();
return blocks;
}
public List<Block> getBlocks() {
if (!parsed) parse();
return blocks;
}
@Override
public EthMessageCodes getCommand(){
return EthMessageCodes.BLOCKS;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
public String toString() {
if (!parsed) parse();
public String toString() {
if (!parsed) parse();
StringBuffer sb = new StringBuffer();
for (Block blockData : this.getBlocks()) {
sb.append("\n ").append(blockData.toFlatString());
}
return "[" + getCommand().name() + sb.toString() + "]";
}
StringBuffer sb = new StringBuffer();
for (Block blockData : this.getBlocks()) {
sb.append("\n ").append(blockData.toFlatString());
}
return "[" + getCommand().name() + sb.toString() + "]";
}
}

View File

@ -30,13 +30,13 @@ import static org.ethereum.net.message.StaticMessages.GET_TRANSACTIONS_MESSAGE;
* <p>
* Peers with 'eth' capability can send/receive:
* <ul>
* <li>STATUS : Announce their status to the peer</li>
* <li>GET_TRANSACTIONS : Request a list of pending transactions</li>
* <li>TRANSACTIONS : Send a list of pending transactions</li>
* <li>GET_BLOCK_HASHES : Request a list of known block hashes</li>
* <li>BLOCK_HASHES : Send a list of known block hashes</li>
* <li>GET_BLOCKS : Request a list of blocks</li>
* <li>BLOCKS : Send a list of blocks</li>
* <li>STATUS : Announce their status to the peer</li>
* <li>GET_TRANSACTIONS : Request a list of pending transactions</li>
* <li>TRANSACTIONS : Send a list of pending transactions</li>
* <li>GET_BLOCK_HASHES : Request a list of known block hashes</li>
* <li>BLOCK_HASHES : Send a list of known block hashes</li>
* <li>GET_BLOCKS : Request a list of blocks</li>
* <li>BLOCKS : Send a list of blocks</li>
* </ul>
*/
@Component
@ -78,7 +78,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
}
public EthHandler(MessageQueue msgQueue, boolean peerDiscoveryMode) {
this.peerDiscoveryMode = peerDiscoveryMode;
this.peerDiscoveryMode = peerDiscoveryMode;
this.msgQueue = msgQueue;
}
@ -112,7 +112,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
switch (msg.getCommand()) {
case STATUS:
msgQueue.receivedMessage(msg);
processStatus((StatusMessage) msg, ctx);
processStatus((StatusMessage) msg, ctx);
break;
case GET_TRANSACTIONS:
// todo: eventually get_transaction is going deprecated
@ -181,7 +181,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
* <ul>
* <li>checking if peer is using the same genesis, protocol and network</li>
* <li>seeing if total difficulty is higher than total difficulty from all other peers</li>
* <li>send GET_BLOCK_HASHES to this peer based on bestHash</li>
* <li>send GET_BLOCK_HASHES to this peer based on bestHash</li>
* </ul>
*
* @param msg is the StatusMessage
@ -201,7 +201,7 @@ public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
if (!Arrays.equals(msg.getGenesisHash(), Blockchain.GENESIS_HASH)
|| msg.getProtocolVersion() != EthHandler.VERSION) {
logger.info("Removing EthHandler for {} due to protocol incompatibility", ctx.channel().remoteAddress());
// msgQueue.sendMessage(new DisconnectMessage(ReasonCode.INCOMPATIBLE_NETWORK));
// msgQueue.sendMessage(new DisconnectMessage(ReasonCode.INCOMPATIBLE_NETWORK));
ctx.pipeline().remove(this); // Peer is not compatible for the 'eth' sub-protocol
} else if (msg.getNetworkId() != EthHandler.NETWORK_ID)
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.INCOMPATIBLE_NETWORK));

View File

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

View File

@ -13,46 +13,46 @@ import java.util.Map;
*/
public enum EthMessageCodes {
/* Ethereum protocol */
/* Ethereum protocol */
/** [0x00, [PROTOCOL_VERSION, NETWORK_ID, TD, BEST_HASH, GENESIS_HASH] <br>
* Inform a peer of it's current ethereum state. This message should be
* send after the initial handshake and prior to any ethereum related messages. */
STATUS(0x00),
/** [0x00, [PROTOCOL_VERSION, NETWORK_ID, TD, BEST_HASH, GENESIS_HASH] <br>
* Inform a peer of it's current ethereum state. This message should be
* send after the initial handshake and prior to any ethereum related messages. */
STATUS(0x00),
/** [+0x01] Request the peer to send all transactions
* currently in the queue. */
GET_TRANSACTIONS(0x01),
/** [+0x01] Request the peer to send all transactions
* currently in the queue. */
GET_TRANSACTIONS(0x01),
/** [+0x02, [nonce, receiving_address, value, ...], ...] <br>
* Specify (a) transaction(s) that the peer should make sure is included
* on its transaction queue. The items in the list (following the first item 0x12)
* are transactions in the format described in the main Ethereum specification. */
TRANSACTIONS(0x02),
/** [+0x02, [nonce, receiving_address, value, ...], ...] <br>
* Specify (a) transaction(s) that the peer should make sure is included
* on its transaction queue. The items in the list (following the first item 0x12)
* are transactions in the format described in the main Ethereum specification. */
TRANSACTIONS(0x02),
/** [+0x03, [hash : B_32, maxBlocks: P]: <br>
* Requests a BlockHashes message of at most maxBlocks entries,
* of block hashes from the blockchain, starting at the parent of block hash.
* Does not require the peer to give maxBlocks hashes -
* they could give somewhat fewer. */
GET_BLOCK_HASHES(0x03),
/** [+0x03, [hash : B_32, maxBlocks: P]: <br>
* Requests a BlockHashes message of at most maxBlocks entries,
* of block hashes from the blockchain, starting at the parent of block hash.
* Does not require the peer to give maxBlocks hashes -
* they could give somewhat fewer. */
GET_BLOCK_HASHES(0x03),
/** [+0x04, [hash_0: B_32, hash_1: B_32, ....]: <br>Gives a series of hashes
* of blocks (each the child of the next). This implies that the blocks
* are ordered from youngest to oldest. */
BLOCK_HASHES(0x04),
/** [+0x04, [hash_0: B_32, hash_1: B_32, ....]: <br>Gives a series of hashes
* of blocks (each the child of the next). This implies that the blocks
* are ordered from youngest to oldest. */
BLOCK_HASHES(0x04),
/** [+0x05, [hash_0: B_32, hash_1: B_32, ....]: <br>Requests a Blocks message
* detailing a number of blocks to be sent, each referred to by a hash. <br>
* <b>Note:</b> Don't expect that the peer necessarily give you all these blocks
* in a single message - you might have to re-request them. */
GET_BLOCKS(0x05),
/** [+0x05, [hash_0: B_32, hash_1: B_32, ....]: <br>Requests a Blocks message
* detailing a number of blocks to be sent, each referred to by a hash. <br>
* <b>Note:</b> Don't expect that the peer necessarily give you all these blocks
* in a single message - you might have to re-request them. */
GET_BLOCKS(0x05),
/** [+0x06, [block_header, transaction_list, uncle_list], ...] <br>
* Specify (a) block(s) that the peer should know about.
* The items in the list (following the first item, 0x13)
* are blocks in the format described in the main Ethereum specification. */
BLOCKS(0x06),
/** [+0x06, [block_header, transaction_list, uncle_list], ...] <br>
* Specify (a) block(s) that the peer should know about.
* The items in the list (following the first item, 0x13)
* are blocks in the format described in the main Ethereum specification. */
BLOCKS(0x06),
/**
* [+0x07 [blockHeader, transactionList, uncleList], totalDifficulty] <br>
@ -81,18 +81,18 @@ public enum EthMessageCodes {
}
public static EthMessageCodes fromByte(byte i) {
EthMessageCodes type = intToTypeMap.get(i - OFFSET);
EthMessageCodes type = intToTypeMap.get(i - OFFSET);
return type;
}
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){
EthMessageCodes.OFFSET = offset;
}
public byte asByte() {
return (byte) (cmd + OFFSET);
return (byte) (cmd + OFFSET);
}
}

View File

@ -14,62 +14,62 @@ import org.spongycastle.util.encoders.Hex;
*/
public class GetBlockHashesMessage extends EthMessage {
/** The newest block hash from which to start sending older hashes */
private byte[] bestHash;
/** The maximum number of blocks to return.
* <b>Note:</b> the peer could return fewer. */
private int maxBlocks;
/** The newest block hash from which to start sending older hashes */
private byte[] bestHash;
/** The maximum number of blocks to return.
* <b>Note:</b> the peer could return fewer. */
private int maxBlocks;
public GetBlockHashesMessage(byte[] encoded) {
super(encoded);
}
public GetBlockHashesMessage(byte[] encoded) {
super(encoded);
}
public GetBlockHashesMessage(byte[] hash, int maxBlocks) {
this.bestHash = hash;
this.maxBlocks = maxBlocks;
parsed = true;
encode();
}
public GetBlockHashesMessage(byte[] hash, int maxBlocks) {
this.bestHash = hash;
this.maxBlocks = maxBlocks;
parsed = true;
encode();
}
private void encode() {
byte[] command = RLP.encodeByte(GET_BLOCK_HASHES.asByte());
byte[] hash = RLP.encodeElement(this.bestHash);
byte[] maxBlocks = RLP.encodeInt(this.maxBlocks);
this.encoded = RLP.encodeList(command, hash, maxBlocks);
}
private void encode() {
byte[] command = RLP.encodeByte(GET_BLOCK_HASHES.asByte());
byte[] hash = RLP.encodeElement(this.bestHash);
byte[] maxBlocks = RLP.encodeInt(this.maxBlocks);
this.encoded = RLP.encodeList(command, hash, maxBlocks);
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
this.bestHash = paramsList.get(1).getRLPData();
byte[] maxBlocksBytes = paramsList.get(2).getRLPData();
this.maxBlocks = ByteUtil.byteArrayToInt(maxBlocksBytes);
this.bestHash = paramsList.get(1).getRLPData();
byte[] maxBlocksBytes = paramsList.get(2).getRLPData();
this.maxBlocks = ByteUtil.byteArrayToInt(maxBlocksBytes);
parsed = true;
}
parsed = true;
}
@Override
public byte[] getEncoded() {
if(encoded == null) encode();
return encoded;
}
@Override
public byte[] getEncoded() {
if(encoded == null) encode();
return encoded;
}
@Override
public Class<BlockHashesMessage> getAnswerMessage() {
return BlockHashesMessage.class;
}
@Override
public Class<BlockHashesMessage> getAnswerMessage() {
return BlockHashesMessage.class;
}
public byte[] getBestHash() {
if (!parsed) parse();
return bestHash;
}
public byte[] getBestHash() {
if (!parsed) parse();
return bestHash;
}
public int getMaxBlocks() {
if (!parsed) parse();
return maxBlocks;
}
public int getMaxBlocks() {
if (!parsed) parse();
return maxBlocks;
}
@Override
public EthMessageCodes getCommand(){
@ -77,11 +77,11 @@ public class GetBlockHashesMessage extends EthMessage {
}
@Override
public String toString() {
if (!parsed) parse();
return "[" + this.getCommand().name() +
" bestHash=" + Hex.toHexString(bestHash) +
" maxBlocks=" + maxBlocks + "]";
}
@Override
public String toString() {
if (!parsed) parse();
return "[" + this.getCommand().name() +
" bestHash=" + Hex.toHexString(bestHash) +
" maxBlocks=" + maxBlocks + "]";
}
}

View File

@ -17,64 +17,64 @@ import static org.ethereum.net.eth.EthMessageCodes.GET_BLOCKS;
*/
public class GetBlocksMessage extends EthMessage {
/** List of block hashes for which to retrieve the blocks */
private List<byte[]> blockHashes;
/** List of block hashes for which to retrieve the blocks */
private List<byte[]> blockHashes;
public GetBlocksMessage(byte[] encoded) {
super(encoded);
}
public GetBlocksMessage(byte[] encoded) {
super(encoded);
}
public GetBlocksMessage(List<byte[]> blockHashes) {
this.blockHashes = blockHashes;
parsed = true;
}
public GetBlocksMessage(List<byte[]> blockHashes) {
this.blockHashes = blockHashes;
parsed = true;
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
blockHashes = new ArrayList<>();
for (int i = 1; i < paramsList.size(); ++i) {
blockHashes.add(((RLPItem) paramsList.get(i)).getRLPData());
}
parsed = true;
}
blockHashes = new ArrayList<>();
for (int i = 1; i < paramsList.size(); ++i) {
blockHashes.add(((RLPItem) paramsList.get(i)).getRLPData());
}
parsed = true;
}
private void encode() {
List<byte[]> encodedElements = new ArrayList<>();
encodedElements.add(RLP.encodeByte(GET_BLOCKS.asByte()));
for (byte[] hash : blockHashes)
encodedElements.add(RLP.encodeElement(hash));
byte[][] encodedElementArray = encodedElements
.toArray(new byte[encodedElements.size()][]);
this.encoded = RLP.encodeList(encodedElementArray);
}
private void encode() {
List<byte[]> encodedElements = new ArrayList<>();
encodedElements.add(RLP.encodeByte(GET_BLOCKS.asByte()));
for (byte[] hash : blockHashes)
encodedElements.add(RLP.encodeElement(hash));
byte[][] encodedElementArray = encodedElements
.toArray(new byte[encodedElements.size()][]);
this.encoded = RLP.encodeList(encodedElementArray);
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public Class<BlocksMessage> getAnswerMessage() {
return BlocksMessage.class;
}
@Override
public Class<BlocksMessage> getAnswerMessage() {
return BlocksMessage.class;
}
public List<byte[]> getBlockHashes() {
if (!parsed) parse();
return blockHashes;
}
public List<byte[]> getBlockHashes() {
if (!parsed) parse();
return blockHashes;
}
@Override
public EthMessageCodes getCommand(){
return EthMessageCodes.GET_BLOCKS;
}
public String toString() {
if (!parsed) parse();
public String toString() {
if (!parsed) parse();
StringBuffer sb = Utils.getHashlistShort(this.blockHashes);
return "[" + this.getCommand().name() + sb.toString() + "] (" + this.blockHashes.size() + ")";
}
StringBuffer sb = Utils.getHashlistShort(this.blockHashes);
return "[" + this.getCommand().name() + sb.toString() + "] (" + this.blockHashes.size() + ")";
}
}

View File

@ -11,8 +11,8 @@ import org.spongycastle.util.encoders.Hex;
*/
public class GetTransactionsMessage extends EthMessage {
/** GetTransactions message is always a the same single command payload */
private final static byte[] FIXED_PAYLOAD = Hex.decode("C116");
/** GetTransactions message is always a the same single command payload */
private final static byte[] FIXED_PAYLOAD = Hex.decode("C116");
public byte[] getEncoded() {
return FIXED_PAYLOAD;
@ -30,7 +30,7 @@ public class GetTransactionsMessage extends EthMessage {
@Override
public String toString() {
return "[" + this.getCommand().name() + "]";
return "[" + this.getCommand().name() + "]";
}
}

View File

@ -12,12 +12,12 @@ import org.spongycastle.util.encoders.Hex;
*/
public class NewBlockMessage extends EthMessage {
private Block block;
private Block block;
private byte[] difficulty;
public NewBlockMessage(byte[] encoded) {
super(encoded);
}
public NewBlockMessage(byte[] encoded) {
super(encoded);
}
public NewBlockMessage(Block block, byte[] difficulty){
this.block = block;
@ -34,15 +34,15 @@ public class NewBlockMessage extends EthMessage {
parsed = true;
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
RLPList blockRLP = ((RLPList) paramsList.get(1));
block = new Block(blockRLP.getRLPData());
difficulty = paramsList.get(2).getRLPData();
parsed = true;
}
}
public Block getBlock(){
if (!parsed) parse();
@ -54,25 +54,25 @@ public class NewBlockMessage extends EthMessage {
return difficulty;
}
@Override
public byte[] getEncoded() {
return encoded;
}
@Override
public byte[] getEncoded() {
return encoded;
}
@Override
public EthMessageCodes getCommand(){
return EthMessageCodes.NEW_BLOCK;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
public String toString() {
if (!parsed) parse();
public String toString() {
if (!parsed) parse();
String blockString = this.getBlock().toString();
return "NEW_BLOCK [ " + blockString + "\n difficulty: " + Hex.toHexString(difficulty) + " ]";
}
}
}

View File

@ -20,25 +20,25 @@ public class PacketCountMessage extends EthMessage {
public byte[] getEncoded() {
return this.encoded;
}
}
private void encode() {
this.encoded = RLP.encodeList(new byte[] {EthMessageCodes.STATUS.asByte()} );
}
@Override
public Class<PongMessage> getAnswerMessage() {
return PongMessage.class;
}
@Override
public Class<PongMessage> getAnswerMessage() {
return PongMessage.class;
}
@Override
public EthMessageCodes getCommand(){
return EthMessageCodes.PACKET_COUNT;
}
@Override
public String toString() {
return "[" + getCommand().name() + "]";
}
@Override
public String toString() {
return "[" + getCommand().name() + "]";
}
}

View File

@ -42,23 +42,23 @@ public class StatusMessage extends EthMessage {
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
this.protocolVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0];
byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0];
this.totalDifficulty = ((RLPItem) paramsList.get(3)).getRLPData();
this.bestHash = ((RLPItem) paramsList.get(4)).getRLPData();
this.genesisHash = ((RLPItem) paramsList.get(5)).getRLPData();
this.protocolVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0];
byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
this.networkId = networkIdBytes == null ? 0 : networkIdBytes[0];
this.totalDifficulty = ((RLPItem) paramsList.get(3)).getRLPData();
this.bestHash = ((RLPItem) paramsList.get(4)).getRLPData();
this.genesisHash = ((RLPItem) paramsList.get(5)).getRLPData();
parsed = true;
}
private void encode() {
byte[] command = RLP.encodeByte(STATUS.asByte());
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
byte[] networkId = RLP.encodeByte(this.networkId);
byte[] totalDifficulty = RLP.encodeElement(this.totalDifficulty);
byte[] bestHash = RLP.encodeElement(this.bestHash);
byte[] genesisHash = RLP.encodeElement(this.genesisHash);
byte[] command = RLP.encodeByte(STATUS.asByte());
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
byte[] networkId = RLP.encodeByte(this.networkId);
byte[] totalDifficulty = RLP.encodeElement(this.totalDifficulty);
byte[] bestHash = RLP.encodeElement(this.bestHash);
byte[] genesisHash = RLP.encodeElement(this.genesisHash);
this.encoded = RLP.encodeList(command, protocolVersion, networkId,
totalDifficulty, bestHash, genesisHash);

View File

@ -18,7 +18,7 @@ import java.util.Set;
* @see org.ethereum.net.eth.EthMessageCodes#TRANSACTIONS
*/
public class TransactionsMessage extends EthMessage {
private Set<Transaction> transactions;
public TransactionsMessage(byte[] encoded) {
@ -38,9 +38,9 @@ public class TransactionsMessage extends EthMessage {
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
transactions = new HashSet<>();
transactions = new HashSet<>();
for (int i = 1; i < paramsList.size(); ++i) {
RLPList rlpTxData = (RLPList) paramsList.get(i);
Transaction tx = new Transaction(rlpTxData.getRLPData());
@ -50,19 +50,19 @@ public class TransactionsMessage extends EthMessage {
}
private void encode() {
List<byte[]> encodedElements = new ArrayList<>();
encodedElements.add(RLP.encodeByte(TRANSACTIONS.asByte()));
for (Transaction tx : transactions)
List<byte[]> encodedElements = new ArrayList<>();
encodedElements.add(RLP.encodeByte(TRANSACTIONS.asByte()));
for (Transaction tx : transactions)
encodedElements.add(tx.getEncoded());
byte[][] encodedElementArray = encodedElements
.toArray(new byte[encodedElements.size()][]);
byte[][] encodedElementArray = encodedElements
.toArray(new byte[encodedElements.size()][]);
this.encoded = RLP.encodeList(encodedElementArray);
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
if (encoded == null) encode();
return encoded;
}

View File

@ -12,7 +12,7 @@ public abstract class Message {
protected byte[] encoded;
protected byte code;
public Message() {}
public Message() {}
public Message(byte[] encoded) {
this.encoded = encoded;
@ -24,14 +24,14 @@ public abstract class Message {
*
* @return RLP encoded byte array representation of this message
*/
public abstract byte[] getEncoded();
public abstract Class<?> getAnswerMessage();
/**
* Returns the message in String format
*
* @return A string with all attributes of the message
*/
public abstract String toString();
public abstract byte[] getEncoded();
public abstract Class<?> getAnswerMessage();
/**
* Returns the message in String format
*
* @return A string with all attributes of the message
*/
public abstract String toString();
}

View File

@ -9,7 +9,7 @@ import java.util.Map;
*/
public enum ReasonCode {
/** [0x00] Disconnect request by other peer */
/** [0x00] Disconnect request by other peer */
REQUESTED(0x00),
/** [0x01] */
@ -37,7 +37,7 @@ public enum ReasonCode {
PEER_QUITING(0x08),
/** [0xFF] Reason not specified */
UNKNOWN(0xFF);
UNKNOWN(0xFF);
private int reason;
@ -53,13 +53,13 @@ public enum ReasonCode {
}
public static ReasonCode fromInt(int i) {
ReasonCode type = intToTypeMap.get(Integer.valueOf(i));
ReasonCode type = intToTypeMap.get(Integer.valueOf(i));
if (type == null)
return ReasonCode.UNKNOWN;
return type;
}
public byte asByte() {
return (byte) reason;
return (byte) reason;
}
}

View File

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

View File

@ -25,37 +25,37 @@ import org.spongycastle.util.encoders.Hex;
*/
public class StaticMessages {
public static final String PEER_ID = Hex.toHexString(HashUtil.randomPeerId());
public final static PingMessage PING_MESSAGE = new PingMessage();
public final static PongMessage PONG_MESSAGE = new PongMessage();
public final static HelloMessage HELLO_MESSAGE = generateHelloMessage();
public final static GetPeersMessage GET_PEERS_MESSAGE = new GetPeersMessage();
public final static GetTransactionsMessage GET_TRANSACTIONS_MESSAGE = new GetTransactionsMessage();
public static final String PEER_ID = Hex.toHexString(HashUtil.randomPeerId());
public final static PingMessage PING_MESSAGE = new PingMessage();
public final static PongMessage PONG_MESSAGE = new PongMessage();
public final static HelloMessage HELLO_MESSAGE = generateHelloMessage();
public final static GetPeersMessage GET_PEERS_MESSAGE = new GetPeersMessage();
public final static GetTransactionsMessage GET_TRANSACTIONS_MESSAGE = new GetTransactionsMessage();
public static final byte[] SYNC_TOKEN = Hex.decode("22400891");
public static final byte[] SYNC_TOKEN = Hex.decode("22400891");
private static HelloMessage generateHelloMessage() {
String helloAnnouncement = buildHelloAnnouncement();
byte p2pVersion = P2pHandler.VERSION;
List<Capability> capabilities = Arrays.asList(
new Capability(Capability.ETH, EthHandler.VERSION),
new Capability(Capability.SHH, ShhHandler.VERSION));
int listenPort = SystemProperties.CONFIG.listenPort();
private static HelloMessage generateHelloMessage() {
String helloAnnouncement = buildHelloAnnouncement();
byte p2pVersion = P2pHandler.VERSION;
List<Capability> capabilities = Arrays.asList(
new Capability(Capability.ETH, EthHandler.VERSION),
new Capability(Capability.SHH, ShhHandler.VERSION));
int listenPort = SystemProperties.CONFIG.listenPort();
return new HelloMessage(p2pVersion, helloAnnouncement,
capabilities, listenPort, PEER_ID);
}
return new HelloMessage(p2pVersion, helloAnnouncement,
capabilities, listenPort, PEER_ID);
}
private static String buildHelloAnnouncement() {
String version = SystemProperties.CONFIG.projectVersion();
String system = System.getProperty("os.name");
if (system.contains(" "))
system = system.substring(0, system.indexOf(" "));
if (System.getProperty("java.vm.vendor").contains("Android"))
system = "Android";
String phrase = SystemProperties.CONFIG.helloPhrase();
private static String buildHelloAnnouncement() {
String version = SystemProperties.CONFIG.projectVersion();
String system = System.getProperty("os.name");
if (system.contains(" "))
system = system.substring(0, system.indexOf(" "));
if (System.getProperty("java.vm.vendor").contains("Android"))
system = "Android";
String phrase = SystemProperties.CONFIG.helloPhrase();
return String.format("Ethereum(J)/v%s/%s/%s/Java", version, phrase, system);
}
return String.format("Ethereum(J)/v%s/%s/%s/Java", version, phrase, system);
}
}

View File

@ -16,58 +16,58 @@ import static org.ethereum.net.message.ReasonCode.REQUESTED;
*/
public class DisconnectMessage extends P2pMessage {
private ReasonCode reason;
private ReasonCode reason;
public DisconnectMessage(byte[] encoded) {
super(encoded);
}
public DisconnectMessage(byte[] encoded) {
super(encoded);
}
public DisconnectMessage(ReasonCode reason) {
this.reason = reason;
parsed = true;
}
public DisconnectMessage(ReasonCode reason) {
this.reason = reason;
parsed = true;
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
byte[] reasonBytes = ((RLPItem) paramsList.get(1)).getRLPData();
if (reasonBytes == null)
this.reason = REQUESTED;
else
this.reason = ReasonCode.fromInt(reasonBytes[0]);
byte[] reasonBytes = ((RLPItem) paramsList.get(1)).getRLPData();
if (reasonBytes == null)
this.reason = REQUESTED;
else
this.reason = ReasonCode.fromInt(reasonBytes[0]);
parsed = true;
}
parsed = true;
}
private void encode() {
byte[] encodedCommand = RLP.encodeByte(DISCONNECT.asByte());
byte[] encodedReason = RLP.encodeByte(this.reason.asByte());
this.encoded = RLP.encodeList(encodedCommand, encodedReason);
}
private void encode() {
byte[] encodedCommand = RLP.encodeByte(DISCONNECT.asByte());
byte[] encodedReason = RLP.encodeByte(this.reason.asByte());
this.encoded = RLP.encodeList(encodedCommand, encodedReason);
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public P2pMessageCodes getCommand(){
return P2pMessageCodes.DISCONNECT;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
public ReasonCode getReason() {
if (!parsed) parse();
return reason;
}
public ReasonCode getReason() {
if (!parsed) parse();
return reason;
}
public String toString() {
if (!parsed) parse();
return "[" + this.getCommand().name() + " reason=" + reason + "]";
}
public String toString() {
if (!parsed) parse();
return "[" + this.getCommand().name() + " reason=" + reason + "]";
}
}

View File

@ -9,26 +9,26 @@ import org.spongycastle.util.encoders.Hex;
*/
public class GetPeersMessage extends P2pMessage {
/** GetPeers message is always a the same single command payload */
private final static byte[] FIXED_PAYLOAD = Hex.decode("C104");
/** GetPeers message is always a the same single command payload */
private final static byte[] FIXED_PAYLOAD = Hex.decode("C104");
@Override
public byte[] getEncoded() {
return FIXED_PAYLOAD;
}
@Override
public byte[] getEncoded() {
return FIXED_PAYLOAD;
}
@Override
public P2pMessageCodes getCommand(){
return P2pMessageCodes.GET_PEERS;
}
@Override
public Class<PeersMessage> getAnswerMessage() {
return null;
}
@Override
public Class<PeersMessage> getAnswerMessage() {
return null;
}
@Override
public String toString() {
return "[" + this.getCommand().name() + "]";
}
@Override
public String toString() {
return "[" + this.getCommand().name() + "]";
}
}

View File

@ -20,47 +20,47 @@ import java.util.List;
*/
public class HelloMessage extends P2pMessage {
/** The implemented version of the P2P protocol. */
private byte p2pVersion;
/** The underlying client. A user-readable string. */
private String clientId;
/** A peer-network capability code, readable ASCII and 3 letters.
* Currently only "eth", "shh" and "bzz" are known. */
private List<Capability> capabilities;
/** The port on which the peer is listening for an incoming connection */
private int listenPort;
/** The identity and public key of the peer */
private String peerId;
/** The implemented version of the P2P protocol. */
private byte p2pVersion;
/** The underlying client. A user-readable string. */
private String clientId;
/** A peer-network capability code, readable ASCII and 3 letters.
* Currently only "eth", "shh" and "bzz" are known. */
private List<Capability> capabilities;
/** The port on which the peer is listening for an incoming connection */
private int listenPort;
/** The identity and public key of the peer */
private String peerId;
public HelloMessage(byte[] encoded) {
super(encoded);
}
public HelloMessage(byte[] encoded) {
super(encoded);
}
public HelloMessage(byte p2pVersion, String clientId,
List<Capability> capabilities, int listenPort, String peerId) {
this.p2pVersion = p2pVersion;
this.clientId = clientId;
this.capabilities = capabilities;
this.listenPort = listenPort;
this.peerId = peerId;
this.parsed = true;
}
public HelloMessage(byte p2pVersion, String clientId,
List<Capability> capabilities, int listenPort, String peerId) {
this.p2pVersion = p2pVersion;
this.clientId = clientId;
this.capabilities = capabilities;
this.listenPort = listenPort;
this.peerId = peerId;
this.parsed = true;
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
// TODO: find out if it can be 0x00. Do we need to check for this?
// The message does not distinguish between 0 and null,
// so we check command code for null.
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
// TODO: find out if it can be 0x00. Do we need to check for this?
// The message does not distinguish between 0 and null,
// so we check command code for null.
byte[] p2pVersionBytes = ((RLPItem) paramsList.get(1)).getRLPData();
this.p2pVersion = p2pVersionBytes != null ? p2pVersionBytes[0] : 0;
byte[] p2pVersionBytes = ((RLPItem) paramsList.get(1)).getRLPData();
this.p2pVersion = p2pVersionBytes != null ? p2pVersionBytes[0] : 0;
byte[] clientIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
this.clientId = new String(clientIdBytes != null ? clientIdBytes : EMPTY_BYTE_ARRAY);
byte[] clientIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
this.clientId = new String(clientIdBytes != null ? clientIdBytes : EMPTY_BYTE_ARRAY);
RLPList capabilityList = (RLPList) paramsList.get(3);
this.capabilities = new ArrayList<>();
for (int i = 0; i < capabilityList.size(); i++) {
RLPList capabilityList = (RLPList) paramsList.get(3);
this.capabilities = new ArrayList<>();
for (int i = 0; i < capabilityList.size(); i++) {
RLPElement capId = ((RLPList)capabilityList.get(i)).get(0);
RLPElement capVersion = ((RLPList)capabilityList.get(i)).get(1);
@ -69,66 +69,66 @@ public class HelloMessage extends P2pMessage {
byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0];
Capability cap = new Capability(name, version);
this.capabilities.add(cap);
}
this.capabilities.add(cap);
}
byte[] peerPortBytes = ((RLPItem) paramsList.get(4)).getRLPData();
this.listenPort = ByteUtil.byteArrayToInt(peerPortBytes);
byte[] peerPortBytes = ((RLPItem) paramsList.get(4)).getRLPData();
this.listenPort = ByteUtil.byteArrayToInt(peerPortBytes);
byte[] peerIdBytes = ((RLPItem) paramsList.get(5)).getRLPData();
this.peerId = Hex.toHexString(peerIdBytes);
this.parsed = true;
}
byte[] peerIdBytes = ((RLPItem) paramsList.get(5)).getRLPData();
this.peerId = Hex.toHexString(peerIdBytes);
this.parsed = true;
}
private void encode() {
byte[] command = RLP.encodeByte(HELLO.asByte());
byte[] p2pVersion = RLP.encodeByte(this.p2pVersion);
byte[] clientId = RLP.encodeString(this.clientId);
byte[][] capabilities = new byte[this.capabilities.size()][];
for (int i = 0; i < this.capabilities.size(); i++) {
Capability capability = this.capabilities.get(i);
capabilities[i] = RLP.encodeList(
private void encode() {
byte[] command = RLP.encodeByte(HELLO.asByte());
byte[] p2pVersion = RLP.encodeByte(this.p2pVersion);
byte[] clientId = RLP.encodeString(this.clientId);
byte[][] capabilities = new byte[this.capabilities.size()][];
for (int i = 0; i < this.capabilities.size(); i++) {
Capability capability = this.capabilities.get(i);
capabilities[i] = RLP.encodeList(
RLP.encodeElement(capability.getName().getBytes()),
RLP.encodeElement(new byte[] {capability.getVersion() }));
}
byte[] capabilityList = RLP.encodeList(capabilities);
byte[] peerPort = RLP.encodeInt(this.listenPort);
byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId));
}
byte[] capabilityList = RLP.encodeList(capabilities);
byte[] peerPort = RLP.encodeInt(this.listenPort);
byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId));
this.encoded = RLP.encodeList(command, p2pVersion, clientId,
capabilityList, peerPort, peerId);
}
this.encoded = RLP.encodeList(command, p2pVersion, clientId,
capabilityList, peerPort, peerId);
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
public byte getP2PVersion() {
if (!parsed) parse();
return p2pVersion;
}
public byte getP2PVersion() {
if (!parsed) parse();
return p2pVersion;
}
public String getClientId() {
if (!parsed) parse();
return clientId;
}
public String getClientId() {
if (!parsed) parse();
return clientId;
}
public List<Capability> getCapabilities() {
if (!parsed) parse();
return capabilities;
}
public List<Capability> getCapabilities() {
if (!parsed) parse();
return capabilities;
}
public int getListenPort() {
if (!parsed) parse();
return listenPort;
}
public int getListenPort() {
if (!parsed) parse();
return listenPort;
}
public String getPeerId() {
if (!parsed) parse();
return peerId;
}
public String getPeerId() {
if (!parsed) parse();
return peerId;
}
@Override
public P2pMessageCodes getCommand(){
@ -136,17 +136,17 @@ public class HelloMessage extends P2pMessage {
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
public String toString() {
if (!parsed) parse();
return "[" + this.getCommand().name() + " p2pVersion="
+ this.p2pVersion + " clientId=" + this.clientId
+ " capabilities=[" + Joiner.on(" ").join(this.capabilities)
+ "]" + " peerPort=" + this.listenPort + " peerId="
+ this.peerId + "]";
}
public String toString() {
if (!parsed) parse();
return "[" + this.getCommand().name() + " p2pVersion="
+ this.p2pVersion + " clientId=" + this.clientId
+ " capabilities=[" + Joiner.on(" ").join(this.capabilities)
+ "]" + " peerPort=" + this.listenPort + " peerId="
+ this.peerId + "]";
}
}

View File

@ -35,26 +35,26 @@ import org.springframework.stereotype.Component;
*
* Peers can send/receive
* <ul>
* <li>HELLO : Announce themselves to the network</li>
* <li>DISCONNECT : Disconnect themselves from the network</li>
* <li>GET_PEERS : Request a list of other knows peers</li>
* <li>PEERS : Send a list of known peers</li>
* <li>PING : Check if another peer is still alive</li>
* <li>PONG : Confirm that they themselves are still alive</li>
* <li>HELLO : Announce themselves to the network</li>
* <li>DISCONNECT : Disconnect themselves from the network</li>
* <li>GET_PEERS : Request a list of other knows peers</li>
* <li>PEERS : Send a list of known peers</li>
* <li>PING : Check if another peer is still alive</li>
* <li>PONG : Confirm that they themselves are still alive</li>
* </ul>
*/
@Component
@Scope("prototype")
public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
public final static byte VERSION = 2;
private final static Logger logger = LoggerFactory.getLogger("net");
public final static byte VERSION = 2;
private final static Logger logger = LoggerFactory.getLogger("net");
private final Timer timer = new Timer("MessageTimer");
private final Timer timer = new Timer("MessageTimer");
private MessageQueue msgQueue;
private boolean tearDown = false;
private MessageQueue msgQueue;
private boolean tearDown = false;
private boolean active = false;
private boolean peerDiscoveryMode = false;
@ -70,10 +70,10 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
this.peerDiscoveryMode = false;
}
public P2pHandler(MessageQueue msgQueue, boolean peerDiscoveryMode) {
this.msgQueue = msgQueue;
this.peerDiscoveryMode = peerDiscoveryMode;
}
public P2pHandler(MessageQueue msgQueue, boolean peerDiscoveryMode) {
this.msgQueue = msgQueue;
this.peerDiscoveryMode = peerDiscoveryMode;
}
public void setWorldManager(WorldManager worldManager) {
this.worldManager = worldManager;
@ -84,13 +84,13 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
public void channelActive(ChannelHandlerContext ctx) throws Exception {
active = true;
msgQueue.activate(ctx);
// Send HELLO once when channel connection has been established
msgQueue.sendMessage(HELLO_MESSAGE);
startTimers();
}
// Send HELLO once when channel connection has been established
msgQueue.sendMessage(HELLO_MESSAGE);
startTimers();
}
public void activate(){
@ -104,8 +104,8 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
return active;
}
@Override
public void channelRead0(final ChannelHandlerContext ctx, P2pMessage msg) throws InterruptedException {
@Override
public void channelRead0(final ChannelHandlerContext ctx, P2pMessage msg) throws InterruptedException {
if (!isActive()) return;
@ -114,29 +114,29 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
worldManager.getListener().trace(String.format( "P2PHandler invoke: [%s]", msg.getCommand()));
switch (msg.getCommand()) {
case HELLO:
msgQueue.receivedMessage(msg);
switch (msg.getCommand()) {
case HELLO:
msgQueue.receivedMessage(msg);
setHandshake((HelloMessage) msg, ctx);
sendGetPeers();
break;
case DISCONNECT:
msgQueue.receivedMessage(msg);
break;
case PING:
msgQueue.receivedMessage(msg);
break;
case DISCONNECT:
msgQueue.receivedMessage(msg);
break;
case PING:
msgQueue.receivedMessage(msg);
ctx.writeAndFlush(PONG_MESSAGE);
break;
case PONG:
msgQueue.receivedMessage(msg);
break;
case GET_PEERS:
msgQueue.receivedMessage(msg);
break;
case PONG:
msgQueue.receivedMessage(msg);
break;
case GET_PEERS:
msgQueue.receivedMessage(msg);
sendPeers(); // todo: implement session management for peer request
break;
case PEERS:
msgQueue.receivedMessage(msg);
processPeers(ctx, (PeersMessage) msg);
break;
case PEERS:
msgQueue.receivedMessage(msg);
processPeers(ctx, (PeersMessage) msg);
if (peerDiscoveryMode &&
!handshakeHelloMessage.getCapabilities().contains(Capability.ETH)){
@ -146,18 +146,18 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
ctx.disconnect().sync();
}
break;
default:
ctx.fireChannelRead(msg);
break;
}
}
default:
ctx.fireChannelRead(msg);
break;
}
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
logger.info("channel inactive: ", ctx.toString());
active = false;
this.killTimers();
}
this.killTimers();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
@ -170,7 +170,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
private void processPeers(ChannelHandlerContext ctx, PeersMessage peersMessage) {
worldManager.getPeerDiscovery().addPeers(peersMessage.getPeers());
}
}
private void sendGetPeers(){
msgQueue.sendMessage( StaticMessages.GET_PEERS_MESSAGE );
@ -190,22 +190,22 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
new Peer(peer.getAddress(), peer.getPort(), peer.getPeerId());
}
PeersMessage msg = new PeersMessage(peerSet);
PeersMessage msg = new PeersMessage(peerSet);
lastPeersSent = peers;
msgQueue.sendMessage(msg);
msgQueue.sendMessage(msg);
}
private void setHandshake(HelloMessage msg, ChannelHandlerContext ctx) {
private void setHandshake(HelloMessage msg, ChannelHandlerContext ctx) {
this.handshakeHelloMessage = msg;
if (msg.getP2PVersion() != P2pHandler.VERSION)
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.INCOMPATIBLE_PROTOCOL));
else {
List<Capability> capInCommon = new ArrayList<>();
for (Capability capability : msg.getCapabilities()) {
if (HELLO_MESSAGE.getCapabilities().contains(capability)) {
if (capability.getName().equals(Capability.ETH)){
if (msg.getP2PVersion() != P2pHandler.VERSION)
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.INCOMPATIBLE_PROTOCOL));
else {
List<Capability> capInCommon = new ArrayList<>();
for (Capability capability : msg.getCapabilities()) {
if (HELLO_MESSAGE.getCapabilities().contains(capability)) {
if (capability.getName().equals(Capability.ETH)){
// Activate EthHandler for this peer
EthHandler ethHandler =
@ -221,21 +221,21 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
(ShhHandler)ctx.pipeline().get(Capability.SHH);
shhHandler.activate();
}
capInCommon.add(capability);
}
}
capInCommon.add(capability);
}
}
adaptMessageIds(capInCommon);
InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress();
int port = msg.getListenPort();
PeerInfo confirmedPeer = new PeerInfo(address, port, msg.getPeerId());
confirmedPeer.setOnline(false);
confirmedPeer.getCapabilities().addAll(msg.getCapabilities());
InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress();
int port = msg.getListenPort();
PeerInfo confirmedPeer = new PeerInfo(address, port, msg.getPeerId());
confirmedPeer.setOnline(false);
confirmedPeer.getCapabilities().addAll(msg.getCapabilities());
//todo calculate the Offsets
worldManager.getPeerDiscovery().getPeers().add(confirmedPeer);
}
}
}
}
/**
* submit transaction to the network
@ -256,7 +256,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
public void adaptMessageIds(List<Capability> capabilities) {
Collections.sort(capabilities);
Collections.sort(capabilities);
byte offset = (byte) (P2pMessageCodes.USER.asByte() + 1);
for (Capability capability : capabilities) {
@ -290,12 +290,12 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
/*
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
msgQueue.sendMessage(GET_PEERS_MESSAGE);
msgQueue.sendMessage(GET_PEERS_MESSAGE);
}
}, 500, 25000);
*/
}
public void killTimers(){
timer.cancel();
timer.purge();

View File

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

View File

@ -13,36 +13,36 @@ import java.util.Map;
*/
public enum P2pMessageCodes {
/* P2P protocol */
/* P2P protocol */
/** [0x00, P2P_VERSION, CLIEND_ID, CAPS, LISTEN_PORT, CLIENT_ID] <br>
* First packet sent over the connection, and sent once by both sides.
* No other messages may be sent until a Hello is received. */
HELLO(0x00),
/** [0x00, P2P_VERSION, CLIEND_ID, CAPS, LISTEN_PORT, CLIENT_ID] <br>
* First packet sent over the connection, and sent once by both sides.
* No other messages may be sent until a Hello is received. */
HELLO(0x00),
/** [0x01, REASON] <br>Inform the peer that a disconnection is imminent;
* if received, a peer should disconnect immediately. When sending,
* well-behaved hosts give their peers a fighting chance (read: wait 2 seconds)
* to disconnect to before disconnecting themselves. */
DISCONNECT(0x01),
/** [0x01, REASON] <br>Inform the peer that a disconnection is imminent;
* if received, a peer should disconnect immediately. When sending,
* well-behaved hosts give their peers a fighting chance (read: wait 2 seconds)
* to disconnect to before disconnecting themselves. */
DISCONNECT(0x01),
/** [0x02] <br>Requests an immediate reply of Pong from the peer. */
PING(0x02),
/** [0x02] <br>Requests an immediate reply of Pong from the peer. */
PING(0x02),
/** [0x03] <br>Reply to peer's Ping packet. */
PONG(0x03),
/** [0x03] <br>Reply to peer's Ping packet. */
PONG(0x03),
/** [0x04] <br>Request the peer to enumerate some known peers
* for us to connect to. This should include the peer itself. */
GET_PEERS(0x04),
/** [0x04] <br>Request the peer to enumerate some known peers
* for us to connect to. This should include the peer itself. */
GET_PEERS(0x04),
/** [0x05, [IP1, Port1, Id1], [IP2, Port2, Id2], ... ] <br>
* Specifies a number of known peers. IP is a 4-byte array 'ABCD'
* that should be interpreted as the IP address A.B.C.D.
* Port is a 2-byte array that should be interpreted as a
* 16-bit big-endian integer. Id is the 512-bit hash that acts
* as the unique identifier of the node. */
PEERS(0x05),
/** [0x05, [IP1, Port1, Id1], [IP2, Port2, Id2], ... ] <br>
* Specifies a number of known peers. IP is a 4-byte array 'ABCD'
* that should be interpreted as the IP address A.B.C.D.
* Port is a 2-byte array that should be interpreted as a
* 16-bit big-endian integer. Id is the 512-bit hash that acts
* as the unique identifier of the node. */
PEERS(0x05),
/**
@ -65,7 +65,7 @@ public enum P2pMessageCodes {
}
public static P2pMessageCodes fromByte(byte i) {
P2pMessageCodes type = intToTypeMap.get(Integer.valueOf(i));
P2pMessageCodes type = intToTypeMap.get(Integer.valueOf(i));
return type;
}
@ -78,6 +78,6 @@ public enum P2pMessageCodes {
}
public byte asByte() {
return (byte) (cmd);
return (byte) (cmd);
}
}

View File

@ -13,65 +13,65 @@ import java.util.List;
*/
public class Peer {
private InetAddress address;
private int port;
private String peerId;
private InetAddress address;
private int port;
private String peerId;
private List<Capability> capabilities;
private List<Capability> capabilities;
public Peer(InetAddress ip, int port, String peerId) {
this.address = ip;
this.port = port;
this.peerId = peerId;
this.capabilities = new ArrayList<>();
}
public Peer(InetAddress ip, int port, String peerId) {
this.address = ip;
this.port = port;
this.peerId = peerId;
this.capabilities = new ArrayList<>();
}
public InetAddress getAddress() {
return address;
}
public InetAddress getAddress() {
return address;
}
public int getPort() {
return port;
}
public int getPort() {
return port;
}
public String getPeerId() {
return peerId == null ? "" : peerId;
}
public String getPeerId() {
return peerId == null ? "" : peerId;
}
public List<Capability> getCapabilities() {
return capabilities;
}
public List<Capability> getCapabilities() {
return capabilities;
}
public byte[] getEncoded() {
byte[] ip = RLP.encodeElement(this.address.getAddress());
byte[] port = RLP.encodeInt(this.port);
byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId));
byte[][] encodedCaps = new byte[this.capabilities.size()][];
for (int i = 0; i < this.capabilities.size()*2; i++) {
encodedCaps[i] = RLP.encodeString(this.capabilities.get(i).getName());
encodedCaps[i] = RLP.encodeByte(this.capabilities.get(i).getVersion());
}
byte[] capabilities = RLP.encodeList(encodedCaps);
return RLP.encodeList(ip, port, peerId, capabilities);
}
public byte[] getEncoded() {
byte[] ip = RLP.encodeElement(this.address.getAddress());
byte[] port = RLP.encodeInt(this.port);
byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId));
byte[][] encodedCaps = new byte[this.capabilities.size()][];
for (int i = 0; i < this.capabilities.size()*2; i++) {
encodedCaps[i] = RLP.encodeString(this.capabilities.get(i).getName());
encodedCaps[i] = RLP.encodeByte(this.capabilities.get(i).getVersion());
}
byte[] capabilities = RLP.encodeList(encodedCaps);
return RLP.encodeList(ip, port, peerId, capabilities);
}
@Override
public String toString() {
return "[ip=" + getAddress().getHostAddress() +
" port=" + getPort()
+ " peerId=" + getPeerId() + "]";
}
@Override
public String toString() {
return "[ip=" + getAddress().getHostAddress() +
" port=" + getPort()
+ " peerId=" + getPeerId() + "]";
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
Peer peerData = (Peer) obj;
return peerData.peerId.equals(this.peerId)
|| this.getAddress().equals(peerData.getAddress());
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
Peer peerData = (Peer) obj;
return peerData.peerId.equals(this.peerId)
|| this.getAddress().equals(peerData.getAddress());
}
@Override
public int hashCode() {
return -1; // override for equals function
}
@Override
public int hashCode() {
return -1; // override for equals function
}
}

View File

@ -21,81 +21,81 @@ import org.spongycastle.util.encoders.Hex;
*/
public class PeersMessage extends P2pMessage {
private boolean parsed = false;
private boolean parsed = false;
private Set<Peer> peers;
private Set<Peer> peers;
public PeersMessage(byte[] payload) {
super(payload);
}
public PeersMessage(byte[] payload) {
super(payload);
}
public PeersMessage(Set<Peer> peers) {
this.peers = peers;
parsed = true;
}
public PeersMessage(Set<Peer> peers) {
this.peers = peers;
parsed = true;
}
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
private void parse() {
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
peers = new LinkedHashSet<>();
for (int i = 1; i < paramsList.size(); ++i) {
RLPList peerParams = (RLPList) paramsList.get(i);
byte[] ipBytes = peerParams.get(0).getRLPData();
byte[] portBytes = peerParams.get(1).getRLPData();
byte[] peerIdRaw = peerParams.get(2).getRLPData();
peers = new LinkedHashSet<>();
for (int i = 1; i < paramsList.size(); ++i) {
RLPList peerParams = (RLPList) paramsList.get(i);
byte[] ipBytes = peerParams.get(0).getRLPData();
byte[] portBytes = peerParams.get(1).getRLPData();
byte[] peerIdRaw = peerParams.get(2).getRLPData();
try {
int peerPort = ByteUtil.byteArrayToInt(portBytes);
InetAddress address = InetAddress.getByAddress(ipBytes);
try {
int peerPort = ByteUtil.byteArrayToInt(portBytes);
InetAddress address = InetAddress.getByAddress(ipBytes);
String peerId = peerIdRaw == null ? "" : Hex.toHexString(peerIdRaw);
Peer peer = new Peer(address, peerPort, peerId);
peers.add(peer);
} catch (UnknownHostException e) {
throw new RuntimeException("Malformed ip", e);
}
}
this.parsed = true;
}
peers.add(peer);
} catch (UnknownHostException e) {
throw new RuntimeException("Malformed ip", e);
}
}
this.parsed = true;
}
private void encode() {
byte[][] encodedByteArrays = new byte[this.peers.size() + 1][];
encodedByteArrays[0] = RLP.encodeByte(this.getCommand().asByte());
List<Peer> peerList = new ArrayList<>(this.peers);
for (int i = 0; i < peerList.size(); i++) {
encodedByteArrays[i + 1] = peerList.get(i).getEncoded();
}
this.encoded = RLP.encodeList(encodedByteArrays);
}
private void encode() {
byte[][] encodedByteArrays = new byte[this.peers.size() + 1][];
encodedByteArrays[0] = RLP.encodeByte(this.getCommand().asByte());
List<Peer> peerList = new ArrayList<>(this.peers);
for (int i = 0; i < peerList.size(); i++) {
encodedByteArrays[i + 1] = peerList.get(i).getEncoded();
}
this.encoded = RLP.encodeList(encodedByteArrays);
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
@Override
public byte[] getEncoded() {
if (encoded == null) encode();
return encoded;
}
public Set<Peer> getPeers() {
if (!parsed) this.parse();
return peers;
}
public Set<Peer> getPeers() {
if (!parsed) this.parse();
return peers;
}
@Override
public P2pMessageCodes getCommand(){
return P2pMessageCodes.PEERS;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
public String toString() {
if (!parsed) this.parse();
public String toString() {
if (!parsed) this.parse();
StringBuffer sb = new StringBuffer();
for (Peer peerData : peers) {
sb.append("\n ").append(peerData);
}
return "[" + this.getCommand().name() + sb.toString() + "]";
}
StringBuffer sb = new StringBuffer();
for (Peer peerData : peers) {
sb.append("\n ").append(peerData);
}
return "[" + this.getCommand().name() + sb.toString() + "]";
}
}

View File

@ -9,25 +9,25 @@ import org.spongycastle.util.encoders.Hex;
*/
public class PingMessage extends P2pMessage {
/** Ping message is always a the same single command payload */
private static byte[] FIXED_PAYLOAD = Hex.decode("C102");
/** Ping message is always a the same single command payload */
private static byte[] FIXED_PAYLOAD = Hex.decode("C102");
public byte[] getEncoded() {
return FIXED_PAYLOAD;
}
public byte[] getEncoded() {
return FIXED_PAYLOAD;
}
@Override
public Class<PongMessage> getAnswerMessage() {
return PongMessage.class;
}
@Override
public Class<PongMessage> getAnswerMessage() {
return PongMessage.class;
}
@Override
public P2pMessageCodes getCommand(){
return P2pMessageCodes.PING;
}
@Override
public String toString() {
return "[" + getCommand().name() + "]";
}
@Override
public String toString() {
return "[" + getCommand().name() + "]";
}
}

View File

@ -10,26 +10,26 @@ import org.spongycastle.util.encoders.Hex;
*/
public class PongMessage extends P2pMessage {
/** Pong message is always a the same single command payload */
private static byte[] FIXED_PAYLOAD = Hex.decode("C103");
/** Pong message is always a the same single command payload */
private static byte[] FIXED_PAYLOAD = Hex.decode("C103");
@Override
public byte[] getEncoded() {
return FIXED_PAYLOAD;
}
@Override
public byte[] getEncoded() {
return FIXED_PAYLOAD;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public Class<?> getAnswerMessage() {
return null;
}
@Override
public P2pMessageCodes getCommand(){
return P2pMessageCodes.PONG;
}
@Override
public String toString() {
return "[" + this.getCommand().name() + "]";
}
@Override
public String toString() {
return "[" + this.getCommand().name() + "]";
}
}

View File

@ -65,7 +65,7 @@ public class DiscoveryChannel {
public void connect(String host, int port) {
EventLoopGroup workerGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
worldManager.getListener().trace("Connecting to: " + host + ":" + port);
try {
@ -123,10 +123,10 @@ public class DiscoveryChannel {
logger.debug("Connection is closed");
} catch (Exception e) {
logger.debug("Exception: {} ({})", e.getMessage(), e.getClass().getName());
logger.debug("Exception: {} ({})", e.getMessage(), e.getClass().getName());
throw new Error("Disconnnected");
} finally {
workerGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
if (!peerDiscoveryMode){
// EthereumListener listener = WorldManager.getInstance().getListener();

View File

@ -22,38 +22,38 @@ import static org.ethereum.config.SystemProperties.CONFIG;
@Component
public class PeerDiscovery {
private static final Logger logger = LoggerFactory.getLogger("peerdiscovery");
private static final Logger logger = LoggerFactory.getLogger("peerdiscovery");
private final Set<PeerInfo> peers = Collections.synchronizedSet(new HashSet<PeerInfo>());
private PeerMonitorThread monitor;
private ThreadFactory threadFactory;
private ThreadPoolExecutor executorPool;
private RejectedExecutionHandler rejectionHandler;
private final Set<PeerInfo> peers = Collections.synchronizedSet(new HashSet<PeerInfo>());
private PeerMonitorThread monitor;
private ThreadFactory threadFactory;
private ThreadPoolExecutor executorPool;
private RejectedExecutionHandler rejectionHandler;
@Autowired
private ApplicationContext ctx;
private final AtomicBoolean started = new AtomicBoolean(false);
private final AtomicBoolean started = new AtomicBoolean(false);
public void start() {
public void start() {
// RejectedExecutionHandler implementation
rejectionHandler = new RejectionLogger();
// RejectedExecutionHandler implementation
rejectionHandler = new RejectionLogger();
// Get the ThreadFactory implementation to use
threadFactory = Executors.defaultThreadFactory();
// Get the ThreadFactory implementation to use
threadFactory = Executors.defaultThreadFactory();
// creating the ThreadPoolExecutor
executorPool = new ThreadPoolExecutor(CONFIG.peerDiscoveryWorkers(),
// creating the ThreadPoolExecutor
executorPool = new ThreadPoolExecutor(CONFIG.peerDiscoveryWorkers(),
CONFIG.peerDiscoveryWorkers(), 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(
1000), threadFactory, rejectionHandler);
1000), threadFactory, rejectionHandler);
// start the monitoring thread
monitor = new PeerMonitorThread(executorPool, 1, this);
Thread monitorThread = new Thread(monitor);
monitorThread.start();
// start the monitoring thread
monitor = new PeerMonitorThread(executorPool, 1, this);
Thread monitorThread = new Thread(monitor);
monitorThread.start();
// Initialize PeerData
List<PeerInfo> peerDataList = parsePeerDiscoveryIpList(CONFIG.peerDiscoveryIPList());
@ -65,23 +65,23 @@ public class PeerDiscovery {
executorPool.execute(workerThread);
}
started.set(true);
}
started.set(true);
}
public void stop() {
executorPool.shutdown();
monitor.shutdown();
started.set(false);
}
public void stop() {
executorPool.shutdown();
monitor.shutdown();
started.set(false);
}
public boolean isStarted() {
return started.get();
}
public boolean isStarted() {
return started.get();
}
public Set<PeerInfo> getPeers() {
return peers;
}
return peers;
}
/**
* Update list of known peers with new peers
* This method checks for duplicate peer id's and addresses
@ -90,7 +90,7 @@ public class PeerDiscovery {
*/
public void addPeers(Set<Peer> newPeers) {
synchronized (peers) {
for (final Peer newPeer : newPeers) {
for (final Peer newPeer : newPeers) {
PeerInfo peerInfo =
new PeerInfo(newPeer.getAddress(), newPeer.getPort(), newPeer.getPeerId());
if (started.get() && !peers.contains(peerInfo )){
@ -107,13 +107,13 @@ public class PeerDiscovery {
}
}
private void startWorker(PeerInfo peerInfo) {
private void startWorker(PeerInfo peerInfo) {
logger.debug("Add new peer for discovery: {}", peerInfo);
logger.debug("Add new peer for discovery: {}", peerInfo);
WorkerThread workerThread = ctx.getBean(WorkerThread.class);
workerThread.init(peerInfo, executorPool);
executorPool.execute(workerThread);
}
}
public List<PeerInfo> parsePeerDiscoveryIpList(final String peerDiscoveryIpList){

View File

@ -15,61 +15,61 @@ import java.util.List;
*/
public class PeerInfo {
private InetAddress address;
private int port;
private String peerId;
private InetAddress address;
private int port;
private String peerId;
private List<Capability> capabilities;
private List<Capability> capabilities;
private HelloMessage handshakeHelloMessage;
private StatusMessage statusMessage;
private transient boolean isOnline = false;
private transient long lastCheckTime = 0;
private transient boolean isOnline = false;
private transient long lastCheckTime = 0;
public PeerInfo(InetAddress ip, int port, String peerId) {
this.address = ip;
this.port = port;
this.peerId = peerId;
this.capabilities = new ArrayList<>();
}
public PeerInfo(InetAddress ip, int port, String peerId) {
this.address = ip;
this.port = port;
this.peerId = peerId;
this.capabilities = new ArrayList<>();
}
public InetAddress getAddress() {
return address;
}
public InetAddress getAddress() {
return address;
}
public int getPort() {
return port;
}
public int getPort() {
return port;
}
public String getPeerId() {
return peerId == null ? "" : peerId;
}
public String getPeerId() {
return peerId == null ? "" : peerId;
}
public boolean isOnline() {
if (getCapabilities().size() < 0)
return false;
return isOnline;
}
public boolean isOnline() {
if (getCapabilities().size() < 0)
return false;
return isOnline;
}
public void setOnline(boolean online) {
isOnline = online;
}
public void setOnline(boolean online) {
isOnline = online;
}
public long getLastCheckTime() {
return lastCheckTime;
}
public long getLastCheckTime() {
return lastCheckTime;
}
public void setLastCheckTime(long lastCheckTime) {
this.lastCheckTime = lastCheckTime;
}
public void setLastCheckTime(long lastCheckTime) {
this.lastCheckTime = lastCheckTime;
}
public List<Capability> getCapabilities() {
return capabilities;
}
public List<Capability> getCapabilities() {
return capabilities;
}
@Override
public String toString() {
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@ -80,14 +80,14 @@ public class PeerInfo {
.append(this.statusMessage == null ? "" : statusMessage + "\n");
return sb.toString();
}
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
PeerInfo peerData = (PeerInfo) obj;
return peerData.hashCode() == this.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null) return false;
PeerInfo peerData = (PeerInfo) obj;
return peerData.hashCode() == this.hashCode();
}
@Override

View File

@ -7,52 +7,52 @@ import java.util.concurrent.ThreadPoolExecutor;
public class PeerMonitorThread implements Runnable {
private final static Logger logger = LoggerFactory.getLogger("peermonitor");
private final static Logger logger = LoggerFactory.getLogger("peermonitor");
private final PeerDiscovery peerDiscovery;
private ThreadPoolExecutor executor;
private int seconds;
private volatile boolean run = true;
private StringBuffer toStringBuff = new StringBuffer();
private int seconds;
private volatile boolean run = true;
private StringBuffer toStringBuff = new StringBuffer();
public PeerMonitorThread(ThreadPoolExecutor executor, int delay, PeerDiscovery peerDiscovery) {
this.executor = executor;
this.seconds = delay;
public PeerMonitorThread(ThreadPoolExecutor executor, int delay, PeerDiscovery peerDiscovery) {
this.executor = executor;
this.seconds = delay;
this.peerDiscovery = peerDiscovery;
}
}
public void shutdown() {
this.run = false;
}
public void shutdown() {
this.run = false;
}
@Override
public void run() {
while (run) {
if (logger.isInfoEnabled()) {
toStringBuff.setLength(0);
toStringBuff.append("[monitor] [");
toStringBuff.append(this.executor.getPoolSize());
toStringBuff.append("/");
toStringBuff.append(this.executor.getCorePoolSize());
toStringBuff.append("] Active: ");
toStringBuff.append(this.executor.getActiveCount());
toStringBuff.append(", Completed: ");
toStringBuff.append(this.executor.getCompletedTaskCount());
toStringBuff.append(", Task: ");
toStringBuff.append(this.executor.getTaskCount());
toStringBuff.append(", isShutdown: ");
toStringBuff.append(this.executor.isShutdown());
toStringBuff.append(", isTerminated: ");
toStringBuff.append(this.executor.isTerminated());
toStringBuff.append(", peersDiscovered: ");
toStringBuff.append(peerDiscovery.getPeers().size());
logger.info(toStringBuff.toString());
}
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
logger.error("Thread interrupted", e);
}
}
}
@Override
public void run() {
while (run) {
if (logger.isInfoEnabled()) {
toStringBuff.setLength(0);
toStringBuff.append("[monitor] [");
toStringBuff.append(this.executor.getPoolSize());
toStringBuff.append("/");
toStringBuff.append(this.executor.getCorePoolSize());
toStringBuff.append("] Active: ");
toStringBuff.append(this.executor.getActiveCount());
toStringBuff.append(", Completed: ");
toStringBuff.append(this.executor.getCompletedTaskCount());
toStringBuff.append(", Task: ");
toStringBuff.append(this.executor.getTaskCount());
toStringBuff.append(", isShutdown: ");
toStringBuff.append(this.executor.isShutdown());
toStringBuff.append(", isTerminated: ");
toStringBuff.append(this.executor.isTerminated());
toStringBuff.append(", peersDiscovered: ");
toStringBuff.append(peerDiscovery.getPeers().size());
logger.info(toStringBuff.toString());
}
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException e) {
logger.error("Thread interrupted", e);
}
}
}
}

View File

@ -15,10 +15,10 @@ import java.util.concurrent.ThreadPoolExecutor;
*/
public class RejectionLogger implements RejectedExecutionHandler {
private static final Logger logger = LoggerFactory.getLogger("wire");
private static final Logger logger = LoggerFactory.getLogger("wire");
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
logger.warn(r.toString() + " is rejected");
}
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
logger.warn(r.toString() + " is rejected");
}
}

View File

@ -18,36 +18,36 @@ import java.util.concurrent.ThreadPoolExecutor;
@Scope("prototype")
public class WorkerThread implements Runnable {
private final static Logger logger = LoggerFactory.getLogger("peerdiscovery");
private final static Logger logger = LoggerFactory.getLogger("peerdiscovery");
private PeerInfo peerInfo;
private ThreadPoolExecutor poolExecutor;
private PeerInfo peerInfo;
private ThreadPoolExecutor poolExecutor;
private boolean running = true;
@Autowired
ApplicationContext ctx;
public WorkerThread() {
}
public WorkerThread() {
}
public void init(PeerInfo peer, ThreadPoolExecutor poolExecutor){
this.peerInfo = peer;
this.poolExecutor = poolExecutor;
}
@Override
public void run() {
logger.debug("{} start", Thread.currentThread().getName());
@Override
public void run() {
logger.debug("{} start", Thread.currentThread().getName());
processCommand();
logger.debug("{} end", Thread.currentThread().getName());
logger.debug("{} end", Thread.currentThread().getName());
sleep(1000);
poolExecutor.execute(this);
}
poolExecutor.execute(this);
}
private void processCommand() {
private void processCommand() {
try {
try {
DiscoveryChannel discoveryChannel = ctx.getBean(DiscoveryChannel.class);
discoveryChannel.connect(peerInfo.getAddress().getHostAddress(), peerInfo.getPort());
@ -59,18 +59,18 @@ public class WorkerThread implements Runnable {
logger.info("Peer is online: [{}] ", peerInfo);
} catch (Throwable e) {
if (peerInfo.isOnline())
logger.info("Peer: [{}] went offline, due to: [{}]", peerInfo
.getAddress().getHostAddress(), e);
peerInfo.setOnline(false);
} finally {
logger.info("Peer: " + peerInfo.toString() + " is "
+ (peerInfo.isOnline() ? "online" : "offline"));
peerInfo.setLastCheckTime(System.currentTimeMillis());
} catch (Throwable e) {
if (peerInfo.isOnline())
logger.info("Peer: [{}] went offline, due to: [{}]", peerInfo
.getAddress().getHostAddress(), e);
peerInfo.setOnline(false);
} finally {
logger.info("Peer: " + peerInfo.toString() + " is "
+ (peerInfo.isOnline() ? "online" : "offline"));
peerInfo.setLastCheckTime(System.currentTimeMillis());
}
}
}
}
private void sleep(long milliseconds){
@ -82,8 +82,8 @@ public class WorkerThread implements Runnable {
}
@Override
public String toString() {
return "Worker for: " + this.peerInfo.toString();
}
@Override
public String toString() {
return "Worker for: " + this.peerInfo.toString();
}
}

View File

@ -74,10 +74,10 @@ public class PeerServer {
logger.debug("Connection is closed");
} catch (Exception e) {
logger.debug("Exception: {} ({})", e.getMessage(), e.getClass().getName());
logger.debug("Exception: {} ({})", e.getMessage(), e.getClass().getName());
throw new Error("Server Disconnnected");
} finally {
workerGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}

View File

@ -21,12 +21,12 @@ import org.springframework.stereotype.Component;
@Scope("prototype")
public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
public final static byte VERSION = 1;
public final static byte VERSION = 1;
private MessageQueue msgQueue = null;
private boolean active = false;
private final static Logger logger = LoggerFactory.getLogger("net");
private final static Logger logger = LoggerFactory.getLogger("net");
@Autowired
WorldManager worldManager;
@ -34,12 +34,12 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
public ShhHandler(){
}
public ShhHandler(MessageQueue msgQueue) {
public ShhHandler(MessageQueue msgQueue) {
this.msgQueue = msgQueue;
}
}
@Override
public void channelRead0(final ChannelHandlerContext ctx, ShhMessage msg) throws InterruptedException {
@Override
public void channelRead0(final ChannelHandlerContext ctx, ShhMessage msg) throws InterruptedException {
if (!isActive()) return;
@ -48,7 +48,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
worldManager.getListener().trace(String.format( "ShhHandler invoke: [%s]", msg.getCommand()));
switch (msg.getCommand()) {
switch (msg.getCommand()) {
case STATUS:
break;
case MESSAGE:
@ -60,10 +60,10 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
case PACKET_COUNT:
break;
default:
break;
}
}
break;
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.error(cause.getCause().toString());
@ -74,7 +74,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
active = false;
logger.debug("handlerRemoved: ... ");
logger.debug("handlerRemoved: ... ");
}
public void activate(){

View File

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

View File

@ -13,22 +13,22 @@ import java.util.Map;
*/
public enum ShhMessageCodes {
/* Whisper Protocol */
/* Whisper Protocol */
/** [+0x00] */
STATUS(0x00),
STATUS(0x00),
/** [+0x01] */
MESSAGE(0x01),
/** [+0x01] */
MESSAGE(0x01),
/** [+0x02] */
ADD_FILTER(0x02),
/** [+0x02] */
ADD_FILTER(0x02),
/** [+0x03] */
REMOVE_FILTER(0x03),
/** [+0x03] */
REMOVE_FILTER(0x03),
/** [+0x04] */
PACKET_COUNT(0x04);
/** [+0x04] */
PACKET_COUNT(0x04);
static byte OFFSET = 0;
private int cmd;
@ -45,7 +45,7 @@ public enum ShhMessageCodes {
}
public static ShhMessageCodes fromByte(byte i) {
ShhMessageCodes type = intToTypeMap.get(i - OFFSET);
ShhMessageCodes type = intToTypeMap.get(i - OFFSET);
return type;
}
@ -62,6 +62,6 @@ public enum ShhMessageCodes {
}
public byte asByte() {
return (byte) (cmd + OFFSET);
return (byte) (cmd + OFFSET);
}
}

View File

@ -12,13 +12,13 @@ import org.ethereum.core.Transaction;
*/
public class TransactionExecutor {
static {
instance = new TransactionExecutor();
}
public static TransactionExecutor instance;
private ExecutorService executor = Executors.newFixedThreadPool(1);
static {
instance = new TransactionExecutor();
}
public static TransactionExecutor instance;
private ExecutorService executor = Executors.newFixedThreadPool(1);
public Future<Transaction> submitTransaction(TransactionTask task) {
return executor.submit(task);
}
public Future<Transaction> submitTransaction(TransactionTask task) {
return executor.submit(task);
}
}

View File

@ -18,36 +18,36 @@ import static java.lang.Thread.sleep;
*/
public class TransactionTask implements Callable<Transaction> {
private static final Logger logger = LoggerFactory.getLogger(TransactionTask.class);
private static final Logger logger = LoggerFactory.getLogger(TransactionTask.class);
private Transaction tx;
private Transaction tx;
private WorldManager worldManager;
public TransactionTask(Transaction tx, WorldManager worldManager) {
this.tx = tx;
public TransactionTask(Transaction tx, WorldManager worldManager) {
this.tx = tx;
this.worldManager = worldManager;
}
}
@Override
public Transaction call() throws Exception {
@Override
public Transaction call() throws Exception {
try {
logger.info("Call() tx: {}", tx.toString());
try {
logger.info("Call() tx: {}", tx.toString());
Wallet wallet = worldManager.getWallet();
ChannelManager channelManager = worldManager.getChannelManager();
WalletTransaction walletTransaction = wallet.addByWalletTransaction(tx);
channelManager.sendTransaction(tx);
WalletTransaction walletTransaction = wallet.addByWalletTransaction(tx);
channelManager.sendTransaction(tx);
while (walletTransaction.getApproved() < 1) {
sleep(10);
}
logger.info("return approved: {}", walletTransaction.getApproved());
} catch (Throwable th) {
logger.warn("Exception caught: {}", th);
while (walletTransaction.getApproved() < 1) {
sleep(10);
}
logger.info("return approved: {}", walletTransaction.getApproved());
} catch (Throwable th) {
logger.warn("Exception caught: {}", th);
worldManager.getWallet().removeTransaction(tx);
}
return null;
}
}
return null;
}
}

View File

@ -8,18 +8,18 @@ import org.ethereum.core.Transaction;
*/
public class WalletTransaction {
private Transaction tx;
int approved = 0; // each time the tx got from the wire this value increased
private Transaction tx;
int approved = 0; // each time the tx got from the wire this value increased
public WalletTransaction(Transaction tx) {
this.tx = tx;
}
public WalletTransaction(Transaction tx) {
this.tx = tx;
}
public void incApproved() {
++this.approved;
}
public void incApproved() {
++this.approved;
}
public int getApproved() {
return approved;
}
public int getApproved() {
return approved;
}
}

View File

@ -30,60 +30,60 @@ public class MessageDecoder extends ByteToMessageDecoder {
@Autowired
WorldManager worldManager;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (!isValidEthereumPacket(in)) {
return;
}
if (!isValidEthereumPacket(in)) {
return;
}
byte[] encoded = new byte[in.readInt()];
in.readBytes(encoded);
if (loggerWire.isDebugEnabled())
loggerWire.debug("Encoded: [{}]", Hex.toHexString(encoded));
byte[] encoded = new byte[in.readInt()];
in.readBytes(encoded);
if (loggerWire.isDebugEnabled())
loggerWire.debug("Encoded: [{}]", Hex.toHexString(encoded));
Message msg = MessageFactory.createMessage(encoded);
Message msg = MessageFactory.createMessage(encoded);
if (loggerNet.isInfoEnabled())
if (loggerNet.isInfoEnabled())
loggerNet.info("From: \t{} \tRecv: \t{}", ctx.channel().remoteAddress(), msg);
EthereumListener listener = worldManager.getListener();
listener.onRecvMessage(msg);
out.add(msg);
out.add(msg);
in.markReaderIndex();
}
private boolean isValidEthereumPacket(ByteBuf in) {
// Ethereum message is at least 8 bytes
if (in.readableBytes() < 8)
return false;
private boolean isValidEthereumPacket(ByteBuf in) {
// Ethereum message is at least 8 bytes
if (in.readableBytes() < 8)
return false;
long syncToken = in.readUnsignedInt();
long syncToken = in.readUnsignedInt();
if (!((syncToken >> 24 & 0xFF) == 0x22 &&
(syncToken >> 16 & 0xFF) == 0x40 &&
(syncToken >> 8 & 0xFF) == 0x08 &&
(syncToken & 0xFF) == 0x91 )) {
// TODO: Drop frame and continue.
// A collision can happen (although rare)
// If this happens too often, it's an attack.
// In that case, drop the peer.
loggerWire.error("Abandon garbage, wrong sync token: [{}]", syncToken);
}
// TODO: Drop frame and continue.
// A collision can happen (although rare)
// If this happens too often, it's an attack.
// In that case, drop the peer.
loggerWire.error("Abandon garbage, wrong sync token: [{}]", syncToken);
}
// Don't have the full message yet
// Don't have the full message yet
long msgSize = in.getInt(in.readerIndex());
if (msgSize > in.readableBytes()) {
loggerWire.trace("msg decode: magicBytes: [{}], readBytes: [{}] / msgSize: [{}] ",
if (msgSize > in.readableBytes()) {
loggerWire.trace("msg decode: magicBytes: [{}], readBytes: [{}] / msgSize: [{}] ",
syncToken, in.readableBytes(), msgSize);
in.resetReaderIndex();
return false;
}
in.resetReaderIndex();
return false;
}
loggerWire.trace("Message fully constructed: readBytes: [{}] / msgSize: [{}]", in.readableBytes(), msgSize);
return true;
}
loggerWire.trace("Message fully constructed: readBytes: [{}] / msgSize: [{}]", in.readableBytes(), msgSize);
return true;
}
}

View File

@ -23,27 +23,27 @@ import org.springframework.stereotype.Component;
@Scope("prototype")
public class MessageEncoder extends MessageToByteEncoder<Message> {
private static final Logger loggerWire = LoggerFactory.getLogger("wire");
private static final Logger loggerNet = LoggerFactory.getLogger("net");
private static final Logger loggerWire = LoggerFactory.getLogger("wire");
private static final Logger loggerNet = LoggerFactory.getLogger("net");
@Autowired
WorldManager worldManager;
@Override
protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
@Override
protected void encode(ChannelHandlerContext ctx, Message msg, ByteBuf out) throws Exception {
String output = String.format("To: \t%s \tSend: \t%s", ctx.channel().remoteAddress(), msg);
worldManager.getListener().trace(output);
if (loggerNet.isInfoEnabled())
if (loggerNet.isInfoEnabled())
loggerNet.info("To: \t{} \tSend: \t{}", ctx.channel().remoteAddress(), msg);
byte[] encoded = msg.getEncoded();
if (loggerWire.isDebugEnabled())
loggerWire.debug("Encoded: [{}]", Hex.toHexString(encoded));
out.capacity(encoded.length + 8);
byte[] encoded = msg.getEncoded();
if (loggerWire.isDebugEnabled())
loggerWire.debug("Encoded: [{}]", Hex.toHexString(encoded));
out.capacity(encoded.length + 8);
out.writeBytes(StaticMessages.SYNC_TOKEN);
out.writeBytes(ByteUtil.calcPacketLength(encoded));
out.writeBytes(encoded);

View File

@ -36,8 +36,8 @@ public class SerpentCompiler {
}
public static String compileFullNotion(String code) {
SerpentParser parser = ParserUtils.getParser(SerpentLexer.class,
SerpentParser.class, code);
SerpentParser parser = ParserUtils.getParser(SerpentLexer.class,
SerpentParser.class, code);
ParseTree tree = parser.parse_init_code_block();
String result = new SerpentToAssemblyCompiler().visit(tree);
@ -87,22 +87,22 @@ public class SerpentCompiler {
String lexa = lexaList.get(i);
{ // skiping the [asm asm] block
if (lexa.equals("asm]")) {
skiping = false;
lexaList.remove(i);
--i;
continue;
}
if (lexa.equals("[asm")) {
skiping = true;
lexaList.remove(i);
--i;
continue;
}
if (skiping)
continue;
}
{ // skiping the [asm asm] block
if (lexa.equals("asm]")) {
skiping = false;
lexaList.remove(i);
--i;
continue;
}
if (lexa.equals("[asm")) {
skiping = true;
lexaList.remove(i);
--i;
continue;
}
if (skiping)
continue;
}
if (OpCode.contains(lexa) ||
lexa.contains("REF_") ||
@ -124,7 +124,7 @@ public class SerpentCompiler {
// encode ref for 5 bytes
for (int i = 0; i < lexaList.size(); ++i) {
String lexa = lexaList.get(i);
if (!lexa.contains("REF_")) continue;
lexaList.add(i + 1, lexa);

View File

@ -126,7 +126,7 @@ public class SerpentToAssemblyCompiler extends SerpentBaseVisitor<String> {
// check if there is 'else'
if (ctx.block(i) != null) {
// body
// body
String elseBlockCode = visitBlock(ctx.block(i));
// append to general retCode
@ -194,7 +194,7 @@ public class SerpentToAssemblyCompiler extends SerpentBaseVisitor<String> {
// msg assigned has two arrays to calc
if (ctx.msg_func() != null) {
String msgCode = visitMsg_func(ctx.msg_func(), varName);
String msgCode = visitMsg_func(ctx.msg_func(), varName);
return msgCode;
} else if (ctx.arr_def() != null) {
// if it's an array the all management is different
@ -701,7 +701,7 @@ public class SerpentToAssemblyCompiler extends SerpentBaseVisitor<String> {
private Integer getMsgOutputArraySize(String code) {
String result = "0";
String result = "0";
Pattern pattern = Pattern.compile("<out_size ([0-9])* out_size>");
Matcher matcher = pattern.matcher(code.trim());
if (matcher.find()) {

View File

@ -15,105 +15,105 @@ import org.iq80.leveldb.WriteBatch;
* Created on: 20/05/2014 10:44
*/
public class Cache {
private Map<ByteArrayWrapper, Node> nodes = new ConcurrentHashMap<>();
private DB db;
private boolean isDirty;
private Map<ByteArrayWrapper, Node> nodes = new ConcurrentHashMap<>();
private DB db;
private boolean isDirty;
public Cache(DB db) {
this.db = db;
}
public Cache(DB db) {
this.db = db;
}
/**
* Put the node in the cache if RLP encoded value is longer than 32 bytes
*
* @param o the Node which could be a pair-, multi-item Node or single Value
* @return sha3 hash of RLP encoded node if length &gt; 32 otherwise return node itself
*/
public Object put(Object o) {
Value value = new Value(o);
byte[] enc = value.encode();
if (enc.length >= 32) {
byte[] sha = HashUtil.sha3(enc);
this.nodes.put(new ByteArrayWrapper(sha), new Node(value, true));
this.isDirty = true;
return sha;
}
return value;
}
/**
* Put the node in the cache if RLP encoded value is longer than 32 bytes
*
* @param o the Node which could be a pair-, multi-item Node or single Value
* @return sha3 hash of RLP encoded node if length &gt; 32 otherwise return node itself
*/
public Object put(Object o) {
Value value = new Value(o);
byte[] enc = value.encode();
if (enc.length >= 32) {
byte[] sha = HashUtil.sha3(enc);
this.nodes.put(new ByteArrayWrapper(sha), new Node(value, true));
this.isDirty = true;
return sha;
}
return value;
}
public Value get(byte[] key) {
ByteArrayWrapper keyObj = new ByteArrayWrapper(key);
// First check if the key is the cache
if (this.nodes.get(keyObj) != null) {
return this.nodes.get(keyObj).getValue();
}
public Value get(byte[] key) {
ByteArrayWrapper keyObj = new ByteArrayWrapper(key);
// First check if the key is the cache
if (this.nodes.get(keyObj) != null) {
return this.nodes.get(keyObj).getValue();
}
// Get the key of the database instead and cache it
byte[] data = this.db.get(key);
Value value = Value.fromRlpEncoded(data);
// Create caching node
this.nodes.put(keyObj, new Node(value, false));
// Get the key of the database instead and cache it
byte[] data = this.db.get(key);
Value value = Value.fromRlpEncoded(data);
// Create caching node
this.nodes.put(keyObj, new Node(value, false));
return value;
}
return value;
}
public void delete(byte[] key) {
ByteArrayWrapper keyObj = new ByteArrayWrapper(key);
this.nodes.remove(keyObj);
public void delete(byte[] key) {
ByteArrayWrapper keyObj = new ByteArrayWrapper(key);
this.nodes.remove(keyObj);
if (db == null) return;
this.db.delete(key);
}
this.db.delete(key);
}
public void commit() {
public void commit() {
if (db == null) return;
// Don't try to commit if it isn't dirty
if (!this.isDirty) {
return;
}
// Don't try to commit if it isn't dirty
if (!this.isDirty) {
return;
}
WriteBatch batch = db.createWriteBatch();
for (ByteArrayWrapper key : this.nodes.keySet()) {
Node node = this.nodes.get(key);
if (node.isDirty()) {
for (ByteArrayWrapper key : this.nodes.keySet()) {
Node node = this.nodes.get(key);
if (node.isDirty()) {
batch.put(key.getData(), node.getValue().encode());
node.setDirty(false);
}
}
node.setDirty(false);
}
}
db.write(batch);
this.isDirty = false;
}
this.isDirty = false;
}
public void undo() {
Iterator<Map.Entry<ByteArrayWrapper, Node>> iter = this.nodes.entrySet().iterator();
while (iter.hasNext()) {
if(iter.next().getValue().isDirty()) {
iter.remove();
}
}
this.isDirty = false;
}
public void undo() {
Iterator<Map.Entry<ByteArrayWrapper, Node>> iter = this.nodes.entrySet().iterator();
while (iter.hasNext()) {
if(iter.next().getValue().isDirty()) {
iter.remove();
}
}
this.isDirty = false;
}
public boolean isDirty() {
return isDirty;
}
public boolean isDirty() {
return isDirty;
}
public void setDirty(boolean isDirty) {
this.isDirty = isDirty;
}
public void setDirty(boolean isDirty) {
this.isDirty = isDirty;
}
public Map<ByteArrayWrapper, Node> getNodes() {
return nodes;
}
public Map<ByteArrayWrapper, Node> getNodes() {
return nodes;
}
public DB getDb() {
return db;
}
public DB getDb() {
return db;
}
public String cacheDump(){

View File

@ -6,9 +6,9 @@ import org.ethereum.util.Value;
/**
* A Node in a Merkle Patricia Tree is one of the following:
*
* - NULL (represented as the empty string)
* - A two-item array [ key, value ] (1 key for 2-item array)
* - A 17-item array [ v0 ... v15, vt ] (16 keys for 17-item array)
* - NULL (represented as the empty string)
* - A two-item array [ key, value ] (1 key for 2-item array)
* - A 17-item array [ v0 ... v15, vt ] (16 keys for 17-item array)
*
* The idea is that in the event that there is a long path of nodes
* each with only one element, we shortcut the descent by setting up
@ -16,12 +16,12 @@ import org.ethereum.util.Value;
* to descend, in the compact encoding described above, and the value
* is just the hash of the node like in the standard radix tree.
*
* R
* / \
* / \
* N N
* / \ / \
* L L L L
* R
* / \
* / \
* N N
* / \ / \
* L L L L
* *
* Also, we add another conceptual change: internal nodes can no longer
* have values, only leaves with no children of their own can; however,
@ -32,7 +32,7 @@ import org.ethereum.util.Value;
*
* Where a node is referenced inside a node, what is included is:
*
* H(rlp.encode(x)) where H(x) = sha3(x) if len(x) &gt;= 32 else x
* H(rlp.encode(x)) where H(x) = sha3(x) if len(x) &gt;= 32 else x
*
* Note that when updating a trie, you will need to store the key/value pair (sha3(x), x)
* in a persistent lookup table when you create a node with length &gt;= 32,
@ -45,32 +45,32 @@ import org.ethereum.util.Value;
*/
public class Node {
/* RLP encoded value of the Trie-node */
private Value value;
private boolean dirty;
/* RLP encoded value of the Trie-node */
private Value value;
private boolean dirty;
public Node(Value val) {
this(val, false);
}
public Node(Value val, boolean dirty) {
this.value = val;
this.dirty = dirty;
}
public Node(Value val) {
this(val, false);
}
public Node(Value val, boolean dirty) {
this.value = val;
this.dirty = dirty;
}
public Node copy() {
return new Node(this.value, this.dirty);
}
public Node copy() {
return new Node(this.value, this.dirty);
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean ditry) {
this.dirty = ditry;
}
public Value getValue() {
return value;
}
public boolean isDirty() {
return dirty;
}
public void setDirty(boolean ditry) {
this.dirty = ditry;
}
public Value getValue() {
return value;
}
}

View File

@ -14,12 +14,12 @@ public interface Trie {
*/
public byte[] get(byte[] key);
/**
* Insert or update a value in the trie for a specified key
*
* @param key - any length byte array
* @param value rlp encoded byte array of the object to store
*/
/**
* Insert or update a value in the trie for a specified key
*
* @param key - any length byte array
* @param value rlp encoded byte array of the object to store
*/
public void update(byte[] key, byte[] value);
/**

View File

@ -82,7 +82,7 @@ public class TrieImpl implements Trie {
@Override
public void setRoot(byte[] root) {
this.root = root;
this.root = root;
}
/**************************************
@ -102,7 +102,7 @@ public class TrieImpl implements Trie {
@Override
public byte[] get(byte[] key) {
if (logger.isDebugEnabled())
logger.debug("Retrieving key {}", Hex.toHexString(key));
logger.debug("Retrieving key {}", Hex.toHexString(key));
byte[] k = binToNibbles(key);
Value c = new Value(this.get(this.root, k));
@ -166,7 +166,7 @@ public class TrieImpl implements Trie {
}
/****************************************
* Private functions *
* Private functions *
****************************************/
private Object get(Object node, byte[] key) {
@ -389,10 +389,10 @@ public class TrieImpl implements Trie {
// Simple compare function which compares two tries based on their stateRoot
@Override
public boolean equals(Object trie) {
if (this == trie) return true;
if (trie instanceof Trie)
return Arrays.equals(this.getRootHash(), ((Trie) trie).getRootHash());
return false;
if (this == trie) return true;
if (trie instanceof Trie)
return Arrays.equals(this.getRootHash(), ((Trie) trie).getRootHash());
return false;
}
@Override
@ -418,7 +418,7 @@ public class TrieImpl implements Trie {
}
/********************************
* Utility functions *
* Utility functions *
*******************************/
// Created an array of empty elements of required length

View File

@ -11,80 +11,80 @@ import static org.ethereum.util.CompactEncoder.unpackToNibbles;
* Created on: 20/05/2014 10:44
*/
public class TrieIterator {
private TrieImpl trie;
private String key;
private String value;
private TrieImpl trie;
private String key;
private String value;
private List<byte[]> shas;
private List<String> values;
private List<byte[]> shas;
private List<String> values;
public TrieIterator(TrieImpl t) {
this.trie = t;
}
public TrieIterator(TrieImpl t) {
this.trie = t;
}
// Some time in the near future this will need refactoring :-)
// XXX Note to self, IsSlice == inline node. Str == sha3 to node
private void workNode(Value currentNode) {
if (currentNode.length() == 2) {
byte[] k = unpackToNibbles(currentNode.get(0).asBytes());
// Some time in the near future this will need refactoring :-)
// XXX Note to self, IsSlice == inline node. Str == sha3 to node
private void workNode(Value currentNode) {
if (currentNode.length() == 2) {
byte[] k = unpackToNibbles(currentNode.get(0).asBytes());
if (currentNode.get(1).asString() == "") {
this.workNode(currentNode.get(1));
} else {
if (k[k.length-1] == 16) {
this.values.add(currentNode.get(1).asString());
} else {
this.shas.add(currentNode.get(1).asBytes());
this.getNode(currentNode.get(1).asBytes());
}
}
} else {
for (int i = 0; i < currentNode.length(); i++) {
if (i == 16 && currentNode.get(i).length() != 0) {
this.values.add(currentNode.get(i).asString());
} else {
if (currentNode.get(i).asString() == "") {
this.workNode(currentNode.get(i));
} else {
String val = currentNode.get(i).asString();
if (val != "") {
this.shas.add(currentNode.get(1).asBytes());
this.getNode(val.getBytes());
}
}
}
}
}
}
if (currentNode.get(1).asString() == "") {
this.workNode(currentNode.get(1));
} else {
if (k[k.length-1] == 16) {
this.values.add(currentNode.get(1).asString());
} else {
this.shas.add(currentNode.get(1).asBytes());
this.getNode(currentNode.get(1).asBytes());
}
}
} else {
for (int i = 0; i < currentNode.length(); i++) {
if (i == 16 && currentNode.get(i).length() != 0) {
this.values.add(currentNode.get(i).asString());
} else {
if (currentNode.get(i).asString() == "") {
this.workNode(currentNode.get(i));
} else {
String val = currentNode.get(i).asString();
if (val != "") {
this.shas.add(currentNode.get(1).asBytes());
this.getNode(val.getBytes());
}
}
}
}
}
}
private void getNode(byte[] node) {
Value currentNode = this.trie.getCache().get(node);
this.workNode(currentNode);
}
private void getNode(byte[] node) {
Value currentNode = this.trie.getCache().get(node);
this.workNode(currentNode);
}
private List<byte[]> collect() {
if (this.trie.getRoot() == "") {
return null;
}
this.getNode(new Value(this.trie.getRoot()).asBytes());
return this.shas;
}
private List<byte[]> collect() {
if (this.trie.getRoot() == "") {
return null;
}
this.getNode(new Value(this.trie.getRoot()).asBytes());
return this.shas;
}
public int purge() {
List<byte[]> shas = this.collect();
for (byte[] sha : shas) {
this.trie.getCache().delete(sha);
}
return this.values.size();
}
public int purge() {
List<byte[]> shas = this.collect();
for (byte[] sha : shas) {
this.trie.getCache().delete(sha);
}
return this.values.size();
}
private String getKey() {
return "";
}
private String getKey() {
return "";
}
private String getValue() {
return "";
}
private String getValue() {
return "";
}
}

View File

@ -32,8 +32,8 @@ public class ByteUtil {
* @return numBytes byte long array.
*/
public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) {
if (b == null)
return null;
if (b == null)
return null;
byte[] bytes = new byte[numBytes];
byte[] biBytes = b.toByteArray();
int start = (biBytes.length == numBytes + 1) ? 1 : 0;
@ -50,7 +50,7 @@ public class ByteUtil {
*
* @param value - any big integer number. A <code>null</code>-value will return <code>null</code>
* @return A byte array without a leading zero byte if present in the signed encoding.
* BigInteger.ZERO will return an array with length 1 and byte-value 0.
* BigInteger.ZERO will return an array with length 1 and byte-value 0.
*/
public static byte[] bigIntegerToBytes(BigInteger value) {
if (value == null)
@ -68,7 +68,7 @@ public class ByteUtil {
/**
* Returns the amount of nibbles that match each other from 0 ...
* amount will never be larger than smallest input
* amount will never be larger than smallest input
*
* @param a - first input
* @param b - second input
@ -78,8 +78,8 @@ public class ByteUtil {
int i = 0;
int length = a.length < b.length ? a.length : b.length;
while (i < length) {
if (a[i] != b[i])
break;
if (a[i] != b[i])
break;
i++;
}
return i;
@ -92,7 +92,7 @@ public class ByteUtil {
* @return <code>byte[]</code> of length 8, representing the long value
*/
public static byte[] longToBytes(long val) {
return ByteBuffer.allocate(8).putLong(val).array();
return ByteBuffer.allocate(8).putLong(val).array();
}
/**
@ -102,7 +102,7 @@ public class ByteUtil {
*
* @param data - byte-array to convert to a hex-string
* @return hex representation of the data.<br>
* Returns an empty String if the input is <code>null</code>
* Returns an empty String if the input is <code>null</code>
*
* @see Hex#toHexString
*/
@ -125,19 +125,19 @@ public class ByteUtil {
return len;
}
/**
* Cast hex encoded value from byte[] to int
*
* Limited to Integer.MAX_VALUE: 2^32-1 (4 bytes)
*
* @param b array contains the values
* @return unsigned positive int value.
*/
public static int byteArrayToInt(byte[] b) {
if (b == null || b.length == 0)
return 0;
return new BigInteger(1, b).intValue();
}
/**
* Cast hex encoded value from byte[] to int
*
* Limited to Integer.MAX_VALUE: 2^32-1 (4 bytes)
*
* @param b array contains the values
* @return unsigned positive int value.
*/
public static int byteArrayToInt(byte[] b) {
if (b == null || b.length == 0)
return 0;
return new BigInteger(1, b).intValue();
}
/**
* Cast hex encoded value from byte[] to int
@ -153,11 +153,11 @@ public class ByteUtil {
return new BigInteger(1, b).longValue();
}
/**
* Turn nibbles to a pretty looking output string
*
* Example. [ 1, 2, 3, 4, 5 ] becomes '\x11\x23\x45'
*
* Example. [ 1, 2, 3, 4, 5 ] becomes '\x11\x23\x45'
*
* @param nibbles - getting byte of data [ 04 ] and turning
* it to a '\x04' representation
@ -202,50 +202,50 @@ public class ByteUtil {
* @param arg - not more that 32 bits
* @return - bytes of the value pad with complete to 32 zeroes
*/
public static byte[] encodeValFor32Bits(Object arg) {
public static byte[] encodeValFor32Bits(Object arg) {
byte[] data;
byte[] data;
// check if the string is numeric
if (arg.toString().trim().matches("-?\\d+(\\.\\d+)?"))
data = new BigInteger(arg.toString().trim()).toByteArray();
// check if it's hex number
else if (arg.toString().trim().matches("0[xX][0-9a-fA-F]+"))
// check if the string is numeric
if (arg.toString().trim().matches("-?\\d+(\\.\\d+)?"))
data = new BigInteger(arg.toString().trim()).toByteArray();
// check if it's hex number
else if (arg.toString().trim().matches("0[xX][0-9a-fA-F]+"))
data = new BigInteger(arg.toString().trim().substring(2), 16).toByteArray();
else
data = arg.toString().trim().getBytes();
data = arg.toString().trim().getBytes();
if (data.length > 32)
throw new RuntimeException("values can't be more than 32 byte");
if (data.length > 32)
throw new RuntimeException("values can't be more than 32 byte");
byte[] val = new byte[32];
byte[] val = new byte[32];
int j = 0;
for (int i = data.length; i > 0; --i) {
val[31 - j] = data[i - 1];
++j;
}
return val;
}
int j = 0;
for (int i = data.length; i > 0; --i) {
val[31 - j] = data[i - 1];
++j;
}
return val;
}
/**
* encode the values and concatenate together
/**
* encode the values and concatenate together
* @param args Object
* @return byte[]
*/
public static byte[] encodeDataList(Object... args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (Object arg : args) {
byte[] val = encodeValFor32Bits(arg);
try {
baos.write(val);
} catch (IOException e) {
throw new Error("Happen something that should never happen ", e);
}
}
return baos.toByteArray();
}
*/
public static byte[] encodeDataList(Object... args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (Object arg : args) {
byte[] val = encodeValFor32Bits(arg);
try {
baos.write(val);
} catch (IOException e) {
throw new Error("Happen something that should never happen ", e);
}
}
return baos.toByteArray();
}
public static int firstNonZeroByte(byte[] data){
int firstNonZero = -1;
@ -259,29 +259,29 @@ public class ByteUtil {
return firstNonZero;
}
public static byte[] stripLeadingZeroes(byte[] data) {
public static byte[] stripLeadingZeroes(byte[] data) {
if (data == null)
return null;
if (data == null)
return null;
int firstNonZero = firstNonZeroByte(data);
int i = 0;
for (; i < data.length; ++i) {
if (data[i] != 0) {
firstNonZero = i;
break;
}
}
if (i == data.length)
return new byte[1];
if (firstNonZero == 0)
return data;
int firstNonZero = firstNonZeroByte(data);
int i = 0;
for (; i < data.length; ++i) {
if (data[i] != 0) {
firstNonZero = i;
break;
}
}
if (i == data.length)
return new byte[1];
if (firstNonZero == 0)
return data;
byte[] result = new byte[data.length - firstNonZero];
System.arraycopy(data, firstNonZero, result, 0, data.length - firstNonZero);
byte[] result = new byte[data.length - firstNonZero];
System.arraycopy(data, firstNonZero, result, 0, data.length - firstNonZero);
return result;
}
return result;
}
/**
* increment byte array as a number until max is reached
@ -311,10 +311,10 @@ public class ByteUtil {
* @return Byte array of given size with a copy of the <code>src</code>
*/
public static byte[] copyToArray(BigInteger value) {
byte[] src = ByteUtil.bigIntegerToBytes(value);
byte[] dest = ByteBuffer.allocate(32).array();
System.arraycopy(src, 0, dest, dest.length - src.length, src.length);
return dest;
byte[] src = ByteUtil.bigIntegerToBytes(value);
byte[] dest = ByteBuffer.allocate(32).array();
System.arraycopy(src, 0, dest, dest.length - src.length, src.length);
return dest;
}

View File

@ -48,7 +48,7 @@ import java.util.Map;
*/
public class CompactEncoder {
private final static byte TERMINATOR = 16;
private final static byte TERMINATOR = 16;
private final static Map<Character, Byte> hexMap = new HashMap<>();
static {
hexMap.put('0', (byte)0x0);
@ -69,70 +69,70 @@ public class CompactEncoder {
hexMap.put('f', (byte)0xf);
}
/**
* Pack nibbles to binary
*
* @param nibbles sequence. may have a terminator
* @return hex-encoded byte array
*/
public static byte[] packNibbles(byte[] nibbles) {
int terminator = 0;
if (nibbles[nibbles.length-1] == TERMINATOR) {
terminator = 1;
nibbles = copyOf(nibbles, nibbles.length-1);
}
int oddlen = nibbles.length % 2;
int flag = 2*terminator + oddlen;
if (oddlen != 0) {
byte[] flags = new byte[] { (byte) flag};
nibbles = concatenate(flags, nibbles);
} else {
byte[] flags = new byte[] { (byte) flag, 0};
nibbles = concatenate(flags, nibbles);
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < nibbles.length; i += 2) {
buffer.write(16*nibbles[i] + nibbles[i+1]);
}
return buffer.toByteArray();
}
/**
* Pack nibbles to binary
*
* @param nibbles sequence. may have a terminator
* @return hex-encoded byte array
*/
public static byte[] packNibbles(byte[] nibbles) {
int terminator = 0;
if (nibbles[nibbles.length-1] == TERMINATOR) {
terminator = 1;
nibbles = copyOf(nibbles, nibbles.length-1);
}
int oddlen = nibbles.length % 2;
int flag = 2*terminator + oddlen;
if (oddlen != 0) {
byte[] flags = new byte[] { (byte) flag};
nibbles = concatenate(flags, nibbles);
} else {
byte[] flags = new byte[] { (byte) flag, 0};
nibbles = concatenate(flags, nibbles);
}
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
for (int i = 0; i < nibbles.length; i += 2) {
buffer.write(16*nibbles[i] + nibbles[i+1]);
}
return buffer.toByteArray();
}
/**
* Unpack a binary string to its nibbles equivalent
*
* @param str of binary data
* @return array of nibbles in byte-format
*/
public static byte[] unpackToNibbles(byte[] str) {
byte[] base = binToNibbles(str);
base = copyOf(base, base.length - 1);
if (base[0] >= 2) {
base = appendByte(base, TERMINATOR);
}
if (base[0] % 2 == 1) {
base = copyOfRange(base, 1, base.length);
} else {
base = copyOfRange(base, 2, base.length);
}
return base;
}
/**
* Unpack a binary string to its nibbles equivalent
*
* @param str of binary data
* @return array of nibbles in byte-format
*/
public static byte[] unpackToNibbles(byte[] str) {
byte[] base = binToNibbles(str);
base = copyOf(base, base.length - 1);
if (base[0] >= 2) {
base = appendByte(base, TERMINATOR);
}
if (base[0] % 2 == 1) {
base = copyOfRange(base, 1, base.length);
} else {
base = copyOfRange(base, 2, base.length);
}
return base;
}
/**
* Transforms a binary array to hexadecimal format + terminator
*
/**
* Transforms a binary array to hexadecimal format + terminator
*
* @param str byte[]
* @return array with each individual nibble adding a terminator at the end
*/
public static byte[] binToNibbles(byte[] str) {
byte[] hexEncoded = encode(str);
ByteBuffer slice = ByteBuffer.allocate(hexEncoded.length + 1);
for (byte b : hexEncoded) {
slice.put(hexMap.get((char)b));
}
slice.put(TERMINATOR);
return slice.array();
}
* @return array with each individual nibble adding a terminator at the end
*/
public static byte[] binToNibbles(byte[] str) {
byte[] hexEncoded = encode(str);
ByteBuffer slice = ByteBuffer.allocate(hexEncoded.length + 1);
for (byte b : hexEncoded) {
slice.put(hexMap.get((char)b));
}
slice.put(TERMINATOR);
return slice.array();
}
public static byte[] binToNibblesNoTerminator(byte[] str) {
byte[] hexEncoded = encode(str);

View File

@ -7,37 +7,37 @@ import org.spongycastle.util.encoders.Hex;
@SuppressWarnings("serial")
public class DecodeResult implements Serializable {
private int pos;
private Object decoded;
public DecodeResult(int pos, Object decoded) {
this.pos = pos;
this.decoded = decoded;
}
public int getPos() {
return pos;
}
public Object getDecoded() {
return decoded;
}
public String toString() {
return asString(this.decoded);
}
private String asString(Object decoded) {
if(decoded instanceof String) {
return (String) decoded;
} else if (decoded instanceof byte[]) {
return Hex.toHexString((byte[]) decoded);
} else if (decoded instanceof Object[]) {
String result = "";
for (Object item : (Object[]) decoded) {
result += asString(item);
}
return result;
}
throw new RuntimeException("Not a valid type. Should not occur");
}
private int pos;
private Object decoded;
public DecodeResult(int pos, Object decoded) {
this.pos = pos;
this.decoded = decoded;
}
public int getPos() {
return pos;
}
public Object getDecoded() {
return decoded;
}
public String toString() {
return asString(this.decoded);
}
private String asString(Object decoded) {
if(decoded instanceof String) {
return (String) decoded;
} else if (decoded instanceof byte[]) {
return Hex.toHexString((byte[]) decoded);
} else if (decoded instanceof Object[]) {
String result = "";
for (Object item : (Object[]) decoded) {
result += asString(item);
}
return result;
}
throw new RuntimeException("Not a valid type. Should not occur");
}
}

View File

@ -7,9 +7,9 @@ import java.util.concurrent.ConcurrentHashMap;
*/
public class LRUMap<K,V> extends ConcurrentHashMap<K,V> {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
protected final int maxEntries;
protected final int maxEntries;
public LRUMap(int initialEntries, int maxEntries) {
super(initialEntries, 0.8f, 3);

File diff suppressed because it is too large Load Diff

View File

@ -12,5 +12,5 @@ import java.io.Serializable;
*/
public interface RLPElement extends Serializable {
public byte[] getRLPData();
public byte[] getRLPData();
}

View File

@ -8,15 +8,15 @@ package org.ethereum.util;
*/
public class RLPItem implements RLPElement {
byte[] rlpData;
public RLPItem(byte[] rlpData) {
this.rlpData = rlpData;
}
public byte[] getRLPData() {
if (rlpData.length == 0)
return null;
return rlpData;
}
byte[] rlpData;
public RLPItem(byte[] rlpData) {
this.rlpData = rlpData;
}
public byte[] getRLPData() {
if (rlpData.length == 0)
return null;
return rlpData;
}
}

View File

@ -19,21 +19,21 @@ public class RLPList extends ArrayList<RLPElement> implements RLPElement {
return rlpData;
}
public static void recursivePrint(RLPElement element) {
public static void recursivePrint(RLPElement element) {
if (element == null)
throw new RuntimeException("RLPElement object can't be null");
if (element instanceof RLPList) {
if (element == null)
throw new RuntimeException("RLPElement object can't be null");
if (element instanceof RLPList) {
RLPList rlpList = (RLPList) element;
System.out.print("[");
for (RLPElement singleElement : rlpList) {
recursivePrint(singleElement);
}
System.out.print("]");
} else {
String hex = ByteUtil.toHexString(((RLPItem) element).getRLPData());
System.out.print(hex + ", ");
}
}
RLPList rlpList = (RLPList) element;
System.out.print("[");
for (RLPElement singleElement : rlpList) {
recursivePrint(singleElement);
}
System.out.print("]");
} else {
String hex = ByteUtil.toHexString(((RLPItem) element).getRLPData());
System.out.print(hex + ", ");
}
}
}

View File

@ -38,9 +38,9 @@ public class Utils {
* @return String formatted as - yyyy.MM.dd HH:mm:ss
*/
public static String longToDateTime(long timestamp) {
Date date = new Date(timestamp * 1000);
DateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
return formatter.format(date);
Date date = new Date(timestamp * 1000);
DateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
return formatter.format(date);
}
public static ImageIcon getImageIcon(String resource) {
@ -67,17 +67,17 @@ public class Utils {
* @return - decode and validated address byte[]
*/
public static byte[] addressStringToBytes(String hex) {
byte[] addr = null;
try { addr = Hex.decode(hex); }
catch(DecoderException addressIsNotValid) { return null; }
if(isValidAddress(addr))
return addr;
return null;
byte[] addr = null;
try { addr = Hex.decode(hex); }
catch(DecoderException addressIsNotValid) { return null; }
if(isValidAddress(addr))
return addr;
return null;
}
public static boolean isValidAddress(byte[] addr) {
return addr != null && addr.length == 20;
return addr != null && addr.length == 20;
}
/**
@ -115,15 +115,15 @@ public class Utils {
return Double.parseDouble (version.substring (0, pos - 1));
}
public static StringBuffer getHashlistShort(List<byte[]> blockHashes) {
public static StringBuffer getHashlistShort(List<byte[]> blockHashes) {
StringBuffer sb = new StringBuffer();
if (blockHashes.isEmpty()) return sb.append("[]");
String firstHash = Hex.toHexString(blockHashes.get(0));
String lastHash = Hex.toHexString(blockHashes.get(blockHashes.size()-1));
return sb.append(" ").append(firstHash).append("...").append(lastHash);
}
String lastHash = Hex.toHexString(blockHashes.get(blockHashes.size()-1));
return sb.append(" ").append(firstHash).append("...").append(lastHash);
}
}

View File

@ -30,10 +30,10 @@ public class Value {
this.value = obj;
}
}
/* *****************
* Convert
* *****************/
/* *****************
* Convert
* *****************/
public Object asObj() {
return value;
@ -102,10 +102,10 @@ public class Value {
// If this wasn't a slice you probably shouldn't be using this function
return new Value(null);
}
/* *****************
* Utility
* *****************/
/* *****************
* Utility
* *****************/
public byte[] encode() {
return RLP.encode(value);
@ -114,10 +114,10 @@ public class Value {
public boolean cmp(Value o) {
return DeepEquals.deepEquals(this, o);
}
/* *****************
* Checks
* *****************/
/* *****************
* Checks
* *****************/
public boolean isList() {
return value != null && value.getClass().isArray() && !value.getClass().getComponentType().isPrimitive();
@ -169,12 +169,12 @@ public class Value {
int hexChars = 0;
byte[] data = (byte[])value;
for (int i = 0; i < data.length; ++i) {
for (int i = 0; i < data.length; ++i) {
if ((data[i] >= 48 && data[i] <= 57)
|| (data[i] >= 97 && data[i] <= 102))
++hexChars;
}
if ((data[i] >= 48 && data[i] <= 57)
|| (data[i] >= 97 && data[i] <= 102))
++hexChars;
}
if ((double) hexChars / (double) data.length > 0.9)
return true;
@ -242,7 +242,7 @@ public class Value {
for (int i = 0; i < list.length; ++i){
Value val = new Value(list[i]);
if (val.isString() || val.isEmpty()){
buffer.append("'").append(val.toString()).append("'");
buffer.append("'").append(val.toString()).append("'");
} else {
buffer.append(val.toString());
}

View File

@ -19,23 +19,23 @@ import java.nio.ByteBuffer;
*/
public class DataWord implements Comparable<DataWord> {
/* Maximum value of the DataWord */
public static final BigInteger _2_256 = BigInteger.valueOf(2).pow(256);
public static final BigInteger MAX_VALUE = _2_256.subtract(BigInteger.ONE);
public static final DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack
public static final DataWord ZERO_EMPTY_ARRAY = new DataWord(new byte[0]); // don't push it in to the stack
/* Maximum value of the DataWord */
public static final BigInteger _2_256 = BigInteger.valueOf(2).pow(256);
public static final BigInteger MAX_VALUE = _2_256.subtract(BigInteger.ONE);
public static final DataWord ZERO = new DataWord(new byte[32]); // don't push it in to the stack
public static final DataWord ZERO_EMPTY_ARRAY = new DataWord(new byte[0]); // don't push it in to the stack
private byte[] data = new byte[32];
public DataWord() {
}
public DataWord() {
}
public DataWord(int num) {
ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num);
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bInt.array(), 0, data.array(), 28, 4);
this.data = data.array();
}
public DataWord(int num) {
ByteBuffer bInt = ByteBuffer.allocate(4).putInt(num);
ByteBuffer data = ByteBuffer.allocate(32);
System.arraycopy(bInt.array(), 0, data.array(), 28, 4);
this.data = data.array();
}
public DataWord(long num) {
ByteBuffer bLong = ByteBuffer.allocate(8).putLong(num);
@ -44,14 +44,14 @@ public class DataWord implements Comparable<DataWord> {
this.data = data.array();
}
public DataWord(byte[] data) {
if (data == null)
this.data = ByteUtil.EMPTY_BYTE_ARRAY;
else if (data.length <= 32)
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
else
throw new RuntimeException("Data word can't exit 32 bytes: " + data);
}
public DataWord(byte[] data) {
if (data == null)
this.data = ByteUtil.EMPTY_BYTE_ARRAY;
else if (data.length <= 32)
System.arraycopy(data, 0, this.data, 32 - data.length, data.length);
else
throw new RuntimeException("Data word can't exit 32 bytes: " + data);
}
public byte[] getData() {
return data;
@ -61,7 +61,7 @@ public class DataWord implements Comparable<DataWord> {
return ByteUtil.stripLeadingZeroes(data);
}
public byte[] getLast20Bytes() {
return Arrays.copyOfRange(data, 12, data.length);
return Arrays.copyOfRange(data, 12, data.length);
}
public BigInteger value() {
@ -77,10 +77,10 @@ public class DataWord implements Comparable<DataWord> {
* @throws ArithmeticException - if this will not fit in an int.
*/
public int intValue() {
BigDecimal tmpValue = new BigDecimal(this.value());
if(this.bytesOccupied() > 4)
return Integer.MAX_VALUE;
return tmpValue.intValueExact();
BigDecimal tmpValue = new BigDecimal(this.value());
if(this.bytesOccupied() > 4)
return Integer.MAX_VALUE;
return tmpValue.intValueExact();
}
/**
@ -92,7 +92,7 @@ public class DataWord implements Comparable<DataWord> {
* @throws ArithmeticException - if this will not fit in a long.
*/
public long longValue() {
BigDecimal tmpValue = new BigDecimal(this.value());
BigDecimal tmpValue = new BigDecimal(this.value());
return tmpValue.longValueExact();
}
@ -159,29 +159,29 @@ public class DataWord implements Comparable<DataWord> {
this.data = ByteUtil.copyToArray(MAX_VALUE.subtract(this.value()));
}
// By : Holger
// From : http://stackoverflow.com/a/24023466/459349
// By : Holger
// From : http://stackoverflow.com/a/24023466/459349
public void add(DataWord word) {
byte[] result = new byte[32];
for (int i = 31, overflow = 0; i >= 0; i--) {
int v = (this.data[i] & 0xff) + (word.data[i] & 0xff) + overflow;
result[i] = (byte) v;
overflow = v >>> 8;
}
this.data = result;
byte[] result = new byte[32];
for (int i = 31, overflow = 0; i >= 0; i--) {
int v = (this.data[i] & 0xff) + (word.data[i] & 0xff) + overflow;
result[i] = (byte) v;
overflow = v >>> 8;
}
this.data = result;
}
// old add-method with BigInteger quick hack
public void add2(DataWord word) {
BigInteger result = value().add(word.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
BigInteger result = value().add(word.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
}
// TODO: mul can be done in more efficient way
// TODO: with shift left shift right trick
// TODO without BigInteger quick hack
public void mul(DataWord word) {
BigInteger result = value().multiply(word.value());
BigInteger result = value().multiply(word.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
}
@ -193,8 +193,8 @@ public class DataWord implements Comparable<DataWord> {
return;
}
BigInteger result = value().divide(word.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
BigInteger result = value().divide(word.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
}
// TODO: improve with no BigInteger
@ -205,21 +205,21 @@ public class DataWord implements Comparable<DataWord> {
return;
}
BigInteger result = sValue().divide(word.sValue());
BigInteger result = sValue().divide(word.sValue());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
}
// TODO: improve with no BigInteger
public void sub(DataWord word) {
BigInteger result = value().subtract(word.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
BigInteger result = value().subtract(word.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
}
// TODO: improve with no BigInteger
public void exp(DataWord word) {
BigInteger result = value().modPow(word.value(), _2_256);
this.data = ByteUtil.copyToArray(result);
BigInteger result = value().modPow(word.value(), _2_256);
this.data = ByteUtil.copyToArray(result);
}
// TODO: improve with no BigInteger
@ -246,13 +246,13 @@ public class DataWord implements Comparable<DataWord> {
}
public void addmod(DataWord word1, DataWord word2) {
this.add(word1);
BigInteger result = this.value().mod(word2.value());
this.add(word1);
BigInteger result = this.value().mod(word2.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
}
public void mulmod(DataWord word1, DataWord word2) {
BigInteger result = value().multiply(word1.value()).mod(word2.value());
BigInteger result = value().multiply(word1.value()).mod(word2.value());
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
}
@ -261,8 +261,8 @@ public class DataWord implements Comparable<DataWord> {
}
public String shortHex() {
String hexValue = Hex.toHexString(getNoLeadZeroesData()).toUpperCase();
return "0x" + hexValue.replaceFirst("^0+(?!$)", "");
String hexValue = Hex.toHexString(getNoLeadZeroesData()).toUpperCase();
return "0x" + hexValue.replaceFirst("^0+(?!$)", "");
}
public DataWord clone() {
@ -296,14 +296,14 @@ public class DataWord implements Comparable<DataWord> {
return (int) Math.signum(result);
}
public void signExtend(byte k) {
if (0 > k || k > 31)
throw new IndexOutOfBoundsException();
byte mask = this.sValue().testBit((k * 8) + 7) ? (byte) 0xff : 0;
for (int i = 31; i > k; i--) {
this.data[31 - i] = mask;
}
}
public void signExtend(byte k) {
if (0 > k || k > 31)
throw new IndexOutOfBoundsException();
byte mask = this.sValue().testBit((k * 8) + 7) ? (byte) 0xff : 0;
for (int i = 31; i > k; i--) {
this.data[31 - i] = mask;
}
}
public int bytesOccupied(){
int firstNonZero = ByteUtil.firstNonZeroByte(data);

View File

@ -8,8 +8,8 @@ package org.ethereum.vm;
*/
public class GasCost {
/** Cost 1 gas */
public static int STEP = 1;
/** Cost 1 gas */
public static int STEP = 1;
/** Cost 20 gas */
public static int BALANCE = 20;
/** Cost 10 gas */
@ -18,30 +18,30 @@ public class GasCost {
public static int SHA3_WORD = 10;
/** Cost 20 gas */
public static int SLOAD = 20;
/** Cost 0 gas */
public static int STOP = 0;
/** Cost 0 gas */
public static int SUICIDE = 0;
/** Cost 300 gas */
public static int SSTORE = 300;
/** Cost 0 gas */
public static int STOP = 0;
/** Cost 0 gas */
public static int SUICIDE = 0;
/** Cost 300 gas */
public static int SSTORE = 300;
/** Cost 100 gas */
public static int RESET_SSTORE = 100;
/** Cost 100 gas */
public static int REFUND_SSTORE = 100;
/** Cost 100 gas */
public static int CREATE = 100;
/** Cost 100 gas */
public static int CREATE = 100;
/** Cost 1 gas */
public static int CREATE_DATA_BYTE = 5;
/** Cost 20 gas */
public static int CALL = 20;
/** Cost 1 gas */
public static int MEMORY = 1;
/** Cost 5 gas */
public static int TX_NO_ZERO_DATA = 5;
public static int CALL = 20;
/** Cost 1 gas */
public static int MEMORY = 1;
/** Cost 5 gas */
public static int TX_NO_ZERO_DATA = 5;
/** Cost 1 gas */
public static int TX_ZERO_DATA = 1;
/** Cost 500 gas */
public static int TRANSACTION = 500;
/** Cost 500 gas */
public static int TRANSACTION = 500;
/** Cost 32 gas */
public static int LOG_GAS = 32;
/** Cost 1 gas */

View File

@ -5,78 +5,78 @@ package org.ethereum.vm;
* This can either be a normal CALL, STATELESS call or POST call.
*/
public class MessageCall {
public enum MsgType {
CALL,
STATELESS,
POST;
}
/** Type of internal call. Either CALL, STATELESS or POST */
private MsgType type;
public enum MsgType {
CALL,
STATELESS,
POST;
}
/** Type of internal call. Either CALL, STATELESS or POST */
private MsgType type;
/** gas to pay for the call, remaining gas will be refunded to the caller */
private DataWord gas;
private DataWord gas;
/** address of account which code to call */
private DataWord codeAddress;
private DataWord codeAddress;
/** the value that can be transfer along with the code execution */
private DataWord endowment;
private DataWord endowment;
/** start of memory to be input data to the call */
private DataWord inDataOffs;
private DataWord inDataOffs;
/** size of memory to be input data to the call */
private DataWord inDataSize;
private DataWord inDataSize;
/** start of memory to be output of the call */
private DataWord outDataOffs;
private DataWord outDataOffs;
/** size of memory to be output data to the call */
private DataWord outDataSize;
private DataWord outDataSize;
public MessageCall(MsgType type, DataWord gas, DataWord codeAddress,
DataWord endowment, DataWord inDataOffs, DataWord inDataSize) {
this.type = type;
this.gas = gas;
this.codeAddress = codeAddress;
this.endowment = endowment;
this.inDataOffs = inDataOffs;
this.inDataSize = inDataSize;
}
public MessageCall(MsgType type, DataWord gas, DataWord codeAddress,
DataWord endowment, DataWord inDataOffs, DataWord inDataSize,
DataWord outDataOffs, DataWord outDataSize) {
this(type, gas, codeAddress, endowment, inDataOffs, inDataSize);
this.outDataOffs = outDataOffs;
this.outDataSize = outDataSize;
}
public MessageCall(MsgType type, DataWord gas, DataWord codeAddress,
DataWord endowment, DataWord inDataOffs, DataWord inDataSize) {
this.type = type;
this.gas = gas;
this.codeAddress = codeAddress;
this.endowment = endowment;
this.inDataOffs = inDataOffs;
this.inDataSize = inDataSize;
}
public MessageCall(MsgType type, DataWord gas, DataWord codeAddress,
DataWord endowment, DataWord inDataOffs, DataWord inDataSize,
DataWord outDataOffs, DataWord outDataSize) {
this(type, gas, codeAddress, endowment, inDataOffs, inDataSize);
this.outDataOffs = outDataOffs;
this.outDataSize = outDataSize;
}
public MsgType getType() {
return type;
}
public MsgType getType() {
return type;
}
public DataWord getGas() {
return gas;
}
public DataWord getGas() {
return gas;
}
public DataWord getCodeAddress() {
return codeAddress;
}
public DataWord getCodeAddress() {
return codeAddress;
}
public DataWord getEndowment() {
return endowment;
}
public DataWord getEndowment() {
return endowment;
}
public DataWord getInDataOffs() {
return inDataOffs;
}
public DataWord getInDataOffs() {
return inDataOffs;
}
public DataWord getInDataSize() {
return inDataSize;
}
public DataWord getInDataSize() {
return inDataSize;
}
public DataWord getOutDataOffs() {
return outDataOffs;
}
public DataWord getOutDataOffs() {
return outDataOffs;
}
public DataWord getOutDataSize() {
return outDataSize;
}
public DataWord getOutDataSize() {
return outDataSize;
}
}

View File

@ -10,287 +10,287 @@ import java.util.Map;
*/
public enum OpCode {
/** Halts execution (0x00) */
STOP(0x00, 0),
/** Halts execution (0x00) */
STOP(0x00, 0),
/* Arithmetic Operations */
/* Arithmetic Operations */
/** (0x01) Addition operation */
ADD(0x01, 2),
/** (0x02) Multiplication operation */
MUL(0x02, 2),
/** (0x03) Subtraction operations */
SUB(0x03, 2),
/** (0x04) Integer division operation */
DIV(0x04, 2),
/** (0x05) Signed integer division operation*/
SDIV(0x05, 2),
/** (0x06) Modulo remainder operation */
MOD(0x06, 2),
/** (0x07) Signed modulo remainder operation*/
SMOD(0x07, 2),
/** (0x08) Addition combined with modulo
* remainder operation */
ADDMOD(0x08, 3),
/** (0x09) Multiplication combined with modulo
* remainder operation */
MULMOD(0x09, 3),
/** (0x0a) Exponential operation */
EXP(0x0a, 2),
/** (0x0b) Extend length of signed integer */
SIGNEXTEND(0x0b, 2),
/** (0x01) Addition operation */
ADD(0x01, 2),
/** (0x02) Multiplication operation */
MUL(0x02, 2),
/** (0x03) Subtraction operations */
SUB(0x03, 2),
/** (0x04) Integer division operation */
DIV(0x04, 2),
/** (0x05) Signed integer division operation*/
SDIV(0x05, 2),
/** (0x06) Modulo remainder operation */
MOD(0x06, 2),
/** (0x07) Signed modulo remainder operation*/
SMOD(0x07, 2),
/** (0x08) Addition combined with modulo
* remainder operation */
ADDMOD(0x08, 3),
/** (0x09) Multiplication combined with modulo
* remainder operation */
MULMOD(0x09, 3),
/** (0x0a) Exponential operation */
EXP(0x0a, 2),
/** (0x0b) Extend length of signed integer */
SIGNEXTEND(0x0b, 2),
/* Bitwise Logic & Comparison Operations */
/* Bitwise Logic & Comparison Operations */
/** (0x10) Less-than comparison */
LT(0X10, 2),
/** (0x11) Greater-than comparison */
/** (0x10) Less-than comparison */
LT(0X10, 2),
/** (0x11) Greater-than comparison */
GT(0X11, 2),
/** (0x12) Signed less-than comparison */
/** (0x12) Signed less-than comparison */
SLT(0X12, 2),
/** (0x13) Signed greater-than comparison */
/** (0x13) Signed greater-than comparison */
SGT(0X13, 2),
/** (0x14) Equality comparison */
EQ(0X14, 2),
/** (0x15) Negation operation */
ISZERO(0x15, 1),
/** (0x16) Bitwise AND operation */
AND(0x16, 2),
/** (0x17) Bitwise OR operation */
OR(0x17, 2),
/** (0x18) Bitwise XOR operation */
XOR(0x18, 2),
/** (0x19) Bitwise NOT operationr */
NOT(0x19, 1),
/** (0x1a) Retrieve single byte from word */
/** (0x14) Equality comparison */
EQ(0X14, 2),
/** (0x15) Negation operation */
ISZERO(0x15, 1),
/** (0x16) Bitwise AND operation */
AND(0x16, 2),
/** (0x17) Bitwise OR operation */
OR(0x17, 2),
/** (0x18) Bitwise XOR operation */
XOR(0x18, 2),
/** (0x19) Bitwise NOT operationr */
NOT(0x19, 1),
/** (0x1a) Retrieve single byte from word */
BYTE(0x1a, 2),
/* Cryptographic Operations */
/* Cryptographic Operations */
/** (0x20) Compute SHA3-256 hash */
SHA3(0x20, 2),
/** (0x20) Compute SHA3-256 hash */
SHA3(0x20, 2),
/* Environmental Information */
/* Environmental Information */
/** (0x30) Get address of currently
* executing account */
ADDRESS(0x30, 0),
/** (0x31) Get balance of the given account */
BALANCE(0x31, 1),
/** (0x32) Get execution origination address*/
ORIGIN(0x32, 0),
/** (0x33) Get caller address */
CALLER(0x33, 0),
/** (0x34) Get deposited value by the
* instruction/transaction responsible
* for this execution */
CALLVALUE(0x34, 0),
/** (0x35) Get input data of current
* environment */
CALLDATALOAD(0x35, 1),
/** (0x36) Get size of input data in current
* environment */
CALLDATASIZE(0x36, 0),
/** (0x37) Copy input data in current
* environment to memory */
CALLDATACOPY(0x37, 3),
/** (0x38) Get size of code running in
* current environment */
CODESIZE(0x38, 0),
/** (0x39) Copy code running in current
* environment to memory */
CODECOPY(0x39, 3), // [len code_start mem_start CODECOPY]
/** (0x3a) Get price of gas in current
* environment */
GASPRICE(0x3a, 0),
/** (0x3b) Get size of code running in
* current environment with given offset */
EXTCODESIZE(0x3b, 1),
/** (0x3c) Copy code running in current
* environment to memory with given offset */
EXTCODECOPY(0x3c, 4),
/** (0x30) Get address of currently
* executing account */
ADDRESS(0x30, 0),
/** (0x31) Get balance of the given account */
BALANCE(0x31, 1),
/** (0x32) Get execution origination address*/
ORIGIN(0x32, 0),
/** (0x33) Get caller address */
CALLER(0x33, 0),
/** (0x34) Get deposited value by the
* instruction/transaction responsible
* for this execution */
CALLVALUE(0x34, 0),
/** (0x35) Get input data of current
* environment */
CALLDATALOAD(0x35, 1),
/** (0x36) Get size of input data in current
* environment */
CALLDATASIZE(0x36, 0),
/** (0x37) Copy input data in current
* environment to memory */
CALLDATACOPY(0x37, 3),
/** (0x38) Get size of code running in
* current environment */
CODESIZE(0x38, 0),
/** (0x39) Copy code running in current
* environment to memory */
CODECOPY(0x39, 3), // [len code_start mem_start CODECOPY]
/** (0x3a) Get price of gas in current
* environment */
GASPRICE(0x3a, 0),
/** (0x3b) Get size of code running in
* current environment with given offset */
EXTCODESIZE(0x3b, 1),
/** (0x3c) Copy code running in current
* environment to memory with given offset */
EXTCODECOPY(0x3c, 4),
/* Block Information */
/* Block Information */
/** (0x40) Get hash of most recent
* complete block */
PREVHASH(0x40, 0),
/** (0x41) Get the blocks coinbase address */
COINBASE(0x41, 0),
/** (x042) Get the blocks timestamp */
TIMESTAMP(0x42, 0),
/** (0x43) Get the blocks number */
NUMBER(0x43, 0),
/** (0x44) Get the blocks difficulty */
DIFFICULTY(0x44, 0),
/** (0x45) Get the blocks gas limit */
GASLIMIT(0x45, 0),
/** (0x40) Get hash of most recent
* complete block */
PREVHASH(0x40, 0),
/** (0x41) Get the blocks coinbase address */
COINBASE(0x41, 0),
/** (x042) Get the blocks timestamp */
TIMESTAMP(0x42, 0),
/** (0x43) Get the blocks number */
NUMBER(0x43, 0),
/** (0x44) Get the blocks difficulty */
DIFFICULTY(0x44, 0),
/** (0x45) Get the blocks gas limit */
GASLIMIT(0x45, 0),
/* Memory, Storage and Flow Operations */
/* Memory, Storage and Flow Operations */
/** (0x50) Remove item from stack */
POP(0x50, 1),
/** (0x51) Load word from memory */
MLOAD(0x51, 1),
/** (0x52) Save word to memory */
MSTORE(0x52, 2),
/** (0x53) Save byte to memory */
MSTORE8(0x53, 2),
/** (0x54) Load word from storage */
SLOAD(0x54, 1),
/** (0x55) Save word to storage */
SSTORE(0x55, 2),
/** (0x56) Alter the program counter */
JUMP(0x56, 1),
/** (0x57) Conditionally alter the program
* counter */
JUMPI(0x57, 2),
/** (0x58) Get the program counter */
PC(0x58, 0),
/** (0x59) Get the size of active memory */
MSIZE(0x59, 0),
/** (0x5a) Get the amount of available gas */
GAS(0x5a, 0),
/** (0x5b) */
JUMPDEST(0x5b, 0),
/** (0x50) Remove item from stack */
POP(0x50, 1),
/** (0x51) Load word from memory */
MLOAD(0x51, 1),
/** (0x52) Save word to memory */
MSTORE(0x52, 2),
/** (0x53) Save byte to memory */
MSTORE8(0x53, 2),
/** (0x54) Load word from storage */
SLOAD(0x54, 1),
/** (0x55) Save word to storage */
SSTORE(0x55, 2),
/** (0x56) Alter the program counter */
JUMP(0x56, 1),
/** (0x57) Conditionally alter the program
* counter */
JUMPI(0x57, 2),
/** (0x58) Get the program counter */
PC(0x58, 0),
/** (0x59) Get the size of active memory */
MSIZE(0x59, 0),
/** (0x5a) Get the amount of available gas */
GAS(0x5a, 0),
/** (0x5b) */
JUMPDEST(0x5b, 0),
/* Push Operations */
/* Push Operations */
/** (0x60) Place 1-byte item on stack */
PUSH1(0x60, 0),
/** (0x61) Place 2-byte item on stack */
PUSH2(0x61, 0),
/** (0x62) Place 3-byte item on stack */
PUSH3(0x62, 0),
/** (0x63) Place 4-byte item on stack */
PUSH4(0x63, 0),
/** (0x64) Place 5-byte item on stack */
PUSH5(0x64, 0),
/** (0x65) Place 6-byte item on stack */
PUSH6(0x65, 0),
/** (0x66) Place 7-byte item on stack */
PUSH7(0x66, 0),
/** (0x67) Place 8-byte item on stack */
PUSH8(0x67, 0),
/** (0x68) Place 9-byte item on stack */
PUSH9(0x68, 0),
/** (0x69) Place 10-byte item on stack */
PUSH10(0x69, 0),
/** (0x6a) Place 11-byte item on stack */
PUSH11(0x6a, 0),
/** (0x6b) Place 12-byte item on stack */
PUSH12(0x6b, 0),
/** (0x6c) Place 13-byte item on stack */
PUSH13(0x6c, 0),
/** (0x6d) Place 14-byte item on stack */
PUSH14(0x6d, 0),
/** (0x6e) Place 15-byte item on stack */
PUSH15(0x6e, 0),
/** (0x6f) Place 16-byte item on stack */
PUSH16(0x6f, 0),
/** (0x70) Place 17-byte item on stack */
PUSH17(0x70, 0),
/** (0x71) Place 18-byte item on stack */
PUSH18(0x71, 0),
/** (0x72) Place 19-byte item on stack */
PUSH19(0x72, 0),
/** (0x73) Place 20-byte item on stack */
PUSH20(0x73, 0),
/** (0x74) Place 21-byte item on stack */
PUSH21(0x74, 0),
/** (0x75) Place 22-byte item on stack */
PUSH22(0x75, 0),
/** (0x76) Place 23-byte item on stack */
PUSH23(0x76, 0),
/** (0x77) Place 24-byte item on stack */
PUSH24(0x77, 0),
/** (0x78) Place 25-byte item on stack */
PUSH25(0x78, 0),
/** (0x79) Place 26-byte item on stack */
PUSH26(0x79, 0),
/** (0x7a) Place 27-byte item on stack */
PUSH27(0x7a, 0),
/** (0x7b) Place 28-byte item on stack */
PUSH28(0x7b, 0),
/** (0x7c) Place 29-byte item on stack */
PUSH29(0x7c, 0),
/** (0x7d) Place 30-byte item on stack */
PUSH30(0x7d, 0),
/** (0x7e) Place 31-byte item on stack */
PUSH31(0x7e, 0),
/** (0x7f) Place 32-byte (full word)
* item on stack */
PUSH32(0x7f, 0),
/** (0x60) Place 1-byte item on stack */
PUSH1(0x60, 0),
/** (0x61) Place 2-byte item on stack */
PUSH2(0x61, 0),
/** (0x62) Place 3-byte item on stack */
PUSH3(0x62, 0),
/** (0x63) Place 4-byte item on stack */
PUSH4(0x63, 0),
/** (0x64) Place 5-byte item on stack */
PUSH5(0x64, 0),
/** (0x65) Place 6-byte item on stack */
PUSH6(0x65, 0),
/** (0x66) Place 7-byte item on stack */
PUSH7(0x66, 0),
/** (0x67) Place 8-byte item on stack */
PUSH8(0x67, 0),
/** (0x68) Place 9-byte item on stack */
PUSH9(0x68, 0),
/** (0x69) Place 10-byte item on stack */
PUSH10(0x69, 0),
/** (0x6a) Place 11-byte item on stack */
PUSH11(0x6a, 0),
/** (0x6b) Place 12-byte item on stack */
PUSH12(0x6b, 0),
/** (0x6c) Place 13-byte item on stack */
PUSH13(0x6c, 0),
/** (0x6d) Place 14-byte item on stack */
PUSH14(0x6d, 0),
/** (0x6e) Place 15-byte item on stack */
PUSH15(0x6e, 0),
/** (0x6f) Place 16-byte item on stack */
PUSH16(0x6f, 0),
/** (0x70) Place 17-byte item on stack */
PUSH17(0x70, 0),
/** (0x71) Place 18-byte item on stack */
PUSH18(0x71, 0),
/** (0x72) Place 19-byte item on stack */
PUSH19(0x72, 0),
/** (0x73) Place 20-byte item on stack */
PUSH20(0x73, 0),
/** (0x74) Place 21-byte item on stack */
PUSH21(0x74, 0),
/** (0x75) Place 22-byte item on stack */
PUSH22(0x75, 0),
/** (0x76) Place 23-byte item on stack */
PUSH23(0x76, 0),
/** (0x77) Place 24-byte item on stack */
PUSH24(0x77, 0),
/** (0x78) Place 25-byte item on stack */
PUSH25(0x78, 0),
/** (0x79) Place 26-byte item on stack */
PUSH26(0x79, 0),
/** (0x7a) Place 27-byte item on stack */
PUSH27(0x7a, 0),
/** (0x7b) Place 28-byte item on stack */
PUSH28(0x7b, 0),
/** (0x7c) Place 29-byte item on stack */
PUSH29(0x7c, 0),
/** (0x7d) Place 30-byte item on stack */
PUSH30(0x7d, 0),
/** (0x7e) Place 31-byte item on stack */
PUSH31(0x7e, 0),
/** (0x7f) Place 32-byte (full word)
* item on stack */
PUSH32(0x7f, 0),
/* Duplicate Nth item from the stack */
/* Duplicate Nth item from the stack */
/** (0x80) Duplicate 1st item on stack */
DUP1(0x80, 1),
/** (0x81) Duplicate 2nd item on stack */
DUP2(0x81, 2),
/** (0x82) Duplicate 3rd item on stack */
DUP3(0x82, 3),
/** (0x83) Duplicate 4th item on stack */
DUP4(0x83, 4),
/** (0x84) Duplicate 5th item on stack */
DUP5(0x84, 5),
/** (0x85) Duplicate 6th item on stack */
DUP6(0x85, 6),
/** (0x86) Duplicate 7th item on stack */
DUP7(0x86, 7),
/** (0x87) Duplicate 8th item on stack */
DUP8(0x87, 8),
/** (0x88) Duplicate 9th item on stack */
DUP9(0x88, 9),
/** (0x89) Duplicate 10th item on stack */
DUP10(0x89, 10),
/** (0x8a) Duplicate 11th item on stack */
DUP11(0x8a, 11),
/** (0x8b) Duplicate 12th item on stack */
DUP12(0x8b, 12),
/** (0x8c) Duplicate 13th item on stack */
DUP13(0x8c, 13),
/** (0x8d) Duplicate 14th item on stack */
DUP14(0x8d, 14),
/** (0x8e) Duplicate 15th item on stack */
DUP15(0x8e, 15),
/** (0x8f) Duplicate 16th item on stack */
DUP16(0x8f, 16),
/** (0x80) Duplicate 1st item on stack */
DUP1(0x80, 1),
/** (0x81) Duplicate 2nd item on stack */
DUP2(0x81, 2),
/** (0x82) Duplicate 3rd item on stack */
DUP3(0x82, 3),
/** (0x83) Duplicate 4th item on stack */
DUP4(0x83, 4),
/** (0x84) Duplicate 5th item on stack */
DUP5(0x84, 5),
/** (0x85) Duplicate 6th item on stack */
DUP6(0x85, 6),
/** (0x86) Duplicate 7th item on stack */
DUP7(0x86, 7),
/** (0x87) Duplicate 8th item on stack */
DUP8(0x87, 8),
/** (0x88) Duplicate 9th item on stack */
DUP9(0x88, 9),
/** (0x89) Duplicate 10th item on stack */
DUP10(0x89, 10),
/** (0x8a) Duplicate 11th item on stack */
DUP11(0x8a, 11),
/** (0x8b) Duplicate 12th item on stack */
DUP12(0x8b, 12),
/** (0x8c) Duplicate 13th item on stack */
DUP13(0x8c, 13),
/** (0x8d) Duplicate 14th item on stack */
DUP14(0x8d, 14),
/** (0x8e) Duplicate 15th item on stack */
DUP15(0x8e, 15),
/** (0x8f) Duplicate 16th item on stack */
DUP16(0x8f, 16),
/* Swap the Nth item from the stack with the top */
/* Swap the Nth item from the stack with the top */
/** (0x90) Exchange 2nd item from stack with the top */
SWAP1(0x90, 2),
/** (0x91) Exchange 3rd item from stack with the top */
SWAP2(0x91, 3),
/** (0x92) Exchange 4th item from stack with the top */
SWAP3(0x92, 4),
/** (0x93) Exchange 5th item from stack with the top */
SWAP4(0x93, 5),
/** (0x94) Exchange 6th item from stack with the top */
SWAP5(0x94, 6),
/** (0x95) Exchange 7th item from stack with the top */
SWAP6(0x95, 7),
/** (0x96) Exchange 8th item from stack with the top */
SWAP7(0x96, 8),
/** (0x97) Exchange 9th item from stack with the top */
SWAP8(0x97, 9),
/** (0x98) Exchange 10th item from stack with the top */
SWAP9(0x98, 10),
/** (0x99) Exchange 11th item from stack with the top */
SWAP10(0x99, 11),
/** (0x9a) Exchange 12th item from stack with the top */
SWAP11(0x9a, 12),
/** (0x9b) Exchange 13th item from stack with the top */
SWAP12(0x9b, 13),
/** (0x9c) Exchange 14th item from stack with the top */
SWAP13(0x9c, 14),
/** (0x9d) Exchange 15th item from stack with the top */
SWAP14(0x9d, 15),
/** (0x9e) Exchange 16th item from stack with the top */
SWAP15(0x9e, 16),
/** (0x9f) Exchange 17th item from stack with the top */
SWAP16(0x9f, 17),
/** (0x90) Exchange 2nd item from stack with the top */
SWAP1(0x90, 2),
/** (0x91) Exchange 3rd item from stack with the top */
SWAP2(0x91, 3),
/** (0x92) Exchange 4th item from stack with the top */
SWAP3(0x92, 4),
/** (0x93) Exchange 5th item from stack with the top */
SWAP4(0x93, 5),
/** (0x94) Exchange 6th item from stack with the top */
SWAP5(0x94, 6),
/** (0x95) Exchange 7th item from stack with the top */
SWAP6(0x95, 7),
/** (0x96) Exchange 8th item from stack with the top */
SWAP7(0x96, 8),
/** (0x97) Exchange 9th item from stack with the top */
SWAP8(0x97, 9),
/** (0x98) Exchange 10th item from stack with the top */
SWAP9(0x98, 10),
/** (0x99) Exchange 11th item from stack with the top */
SWAP10(0x99, 11),
/** (0x9a) Exchange 12th item from stack with the top */
SWAP11(0x9a, 12),
/** (0x9b) Exchange 13th item from stack with the top */
SWAP12(0x9b, 13),
/** (0x9c) Exchange 14th item from stack with the top */
SWAP13(0x9c, 14),
/** (0x9d) Exchange 15th item from stack with the top */
SWAP14(0x9d, 15),
/** (0x9e) Exchange 16th item from stack with the top */
SWAP15(0x9e, 16),
/** (0x9f) Exchange 17th item from stack with the top */
SWAP16(0x9f, 17),
/** (0xa[n]) log some data for some addres with 0..n tags [addr [tag0..tagn] data] */
LOG0(0xa0, 2),
@ -299,23 +299,23 @@ public enum OpCode {
LOG3(0xa3, 5),
LOG4(0xa4, 6),
/* System operations */
/* System operations */
/** (0xf0) Create a new account with associated code */
CREATE(0xf0, 3), // [in_size] [in_offs] [gas_val] CREATE
/** (cxf1) Message-call into an account */
CALL(0xf1, 7), // [out_data_size] [out_data_start] [in_data_size] [in_data_start] [value] [to_addr] [gas] CALL
/** (0xf2) Calls self, but grabbing the code from the
* TO argument instead of from one's own address */
CALLCODE(0xf2, 7),
/** (0xf3) Halt execution returning output data */
/** (0xf0) Create a new account with associated code */
CREATE(0xf0, 3), // [in_size] [in_offs] [gas_val] CREATE
/** (cxf1) Message-call into an account */
CALL(0xf1, 7), // [out_data_size] [out_data_start] [in_data_size] [in_data_start] [value] [to_addr] [gas] CALL
/** (0xf2) Calls self, but grabbing the code from the
* TO argument instead of from one's own address */
CALLCODE(0xf2, 7),
/** (0xf3) Halt execution returning output data */
RETURN(0xf3, 2),
/** (0xff) Halt execution and register account for
* later deletion */
SUICIDE(0xff, 1);
/** (0xff) Halt execution and register account for
* later deletion */
SUICIDE(0xff, 1);
private byte opcode;
private int require;
private byte opcode;
private int require;
private static final Map<Byte, OpCode> intToTypeMap = new HashMap<>();
private static final Map<String, Byte> stringToByteMap = new HashMap<>();
@ -342,11 +342,11 @@ public enum OpCode {
* @return minimum amount of expected items on the stack
*/
public int require() {
return require;
return require;
}
public int asInt() {
return opcode;
return opcode;
}
public static boolean contains(String code) {
@ -358,6 +358,6 @@ public enum OpCode {
}
public static OpCode code(byte code) {
return intToTypeMap.get(code);
return intToTypeMap.get(code);
}
}

View File

@ -32,7 +32,7 @@ import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
* Created on: 01/06/2014 10:45
*/
public class Program {
private static final Logger logger = LoggerFactory.getLogger("VM");
private static final Logger gasLogger = LoggerFactory.getLogger("gas");
@ -51,33 +51,33 @@ public class Program {
byte[] ops;
int pc = 0;
byte lastOp = 0;
byte previouslyExecutedOp = 0;
byte previouslyExecutedOp = 0;
boolean stopped = false;
ProgramInvoke invokeData;
public Program(byte[] ops, ProgramInvoke invokeData) {
if (ops == null) ops = EMPTY_BYTE_ARRAY;
this.ops = ops;
if (invokeData != null) {
this.invokeData = invokeData;
this.programAddress = invokeData.getOwnerAddress();
this.invokeHash = invokeData.hashCode();
this.result.setRepository(invokeData.getRepository());
}
}
public Program(byte[] ops, ProgramInvoke invokeData) {
if (ops == null) ops = EMPTY_BYTE_ARRAY;
this.ops = ops;
if (invokeData != null) {
this.invokeData = invokeData;
this.programAddress = invokeData.getOwnerAddress();
this.invokeHash = invokeData.hashCode();
this.result.setRepository(invokeData.getRepository());
}
}
public byte getOp(int pc) {
if (ops.length <= pc)
return 0;
return ops[pc];
}
public byte getOp(int pc) {
if (ops.length <= pc)
return 0;
return ops[pc];
}
public byte getCurrentOp() {
if(ops.length == 0)
return 0;
if(ops.length == 0)
return 0;
return ops[pc];
}
@ -94,7 +94,7 @@ public class Program {
* @param op
*/
public void setPreviouslyExecutedOp(byte op) {
this.previouslyExecutedOp = op;
this.previouslyExecutedOp = op;
}
/**
@ -102,7 +102,7 @@ public class Program {
* @return
*/
public byte getPreviouslyExecutedOp() {
return this.previouslyExecutedOp;
return this.previouslyExecutedOp;
}
public void stackPush(byte[] data) {
@ -125,7 +125,7 @@ public class Program {
}
public Stack<DataWord> getStack() {
return this.stack;
return this.stack;
}
public int getPC() {
@ -180,13 +180,13 @@ public class Program {
* Verifies that the stack is at least <code>stackSize</code>
* @param stackSize int
* @throws StackTooSmallException If the stack is
* smaller than <code>stackSize</code>
* smaller than <code>stackSize</code>
*/
public void stackRequire(int stackSize) {
if (stack.size() < stackSize) {
throw new StackTooSmallException("Expected: " + stackSize
+ ", found: " + stack.size());
}
if (stack.size() < stackSize) {
throw new StackTooSmallException("Expected: " + stackSize
+ ", found: " + stack.size());
}
}
public int getMemSize() {
@ -198,7 +198,7 @@ public class Program {
}
public void memorySave(int addr, byte[] value) {
memorySave(addr, value.length, value);
memorySave(addr, value.length, value);
}
/**
@ -215,7 +215,7 @@ public class Program {
}
public DataWord memoryLoad(DataWord addr) {
return memoryLoad(addr.intValue());
return memoryLoad(addr.intValue());
}
public DataWord memoryLoad(int address) {
@ -229,7 +229,7 @@ public class Program {
}
public ByteBuffer memoryChunk(DataWord offsetData, DataWord sizeData) {
return memoryChunk(offsetData.intValue(), sizeData.intValue());
return memoryChunk(offsetData.intValue(), sizeData.intValue());
}
/**
@ -246,9 +246,9 @@ public class Program {
allocateMemory(offset, size);
byte[] chunk;
if (memory != null && size != 0)
chunk = Arrays.copyOfRange(memory.array(), offset, offset+size);
chunk = Arrays.copyOfRange(memory.array(), offset, offset+size);
else
chunk = new byte[size];
chunk = new byte[size];
return ByteBuffer.wrap(chunk);
}
@ -262,11 +262,11 @@ public class Program {
public void allocateMemory(int offset, int size) {
int memSize = memory != null ? memory.limit() : 0;
double newMemSize = Math.max(memSize, size != 0 ?
Math.ceil((double) (offset + size) / 32) * 32 : 0);
double newMemSize = Math.max(memSize, size != 0 ?
Math.ceil((double) (offset + size) / 32) * 32 : 0);
ByteBuffer tmpMem = ByteBuffer.allocate((int)newMemSize);
if (memory != null)
tmpMem.put(memory.array(), 0, memory.limit());
tmpMem.put(memory.array(), 0, memory.limit());
memory = tmpMem;
}
@ -276,9 +276,9 @@ public class Program {
DataWord balance = getBalance(this.getOwnerAddress());
// 1) pass full endowment to the obtainer
if (logger.isInfoEnabled())
logger.info("Transfer to: [{}] heritage: [{}]",
Hex.toHexString(obtainer.getLast20Bytes()),
balance.longValue());
logger.info("Transfer to: [{}] heritage: [{}]",
Hex.toHexString(obtainer.getLast20Bytes()),
balance.longValue());
this.result.getRepository().addBalance(obtainer.getLast20Bytes(), balance.value());
this.result.getRepository().addBalance(this.getOwnerAddress().getLast20Bytes(), balance.value().negate());
@ -305,12 +305,12 @@ public class Program {
byte[] newAddress = HashUtil.calcNewAddr(this.getOwnerAddress().getLast20Bytes(), nonce);
result.getRepository().createAccount(newAddress);
if (invokeData.byTestingSuite()) {
// This keeps track of the contracts created for a test
this.getResult().addCallCreate(programCode, newAddress,
gasLimit.getNoLeadZeroesData(),
value.getNoLeadZeroesData());
}
if (invokeData.byTestingSuite()) {
// This keeps track of the contracts created for a test
this.getResult().addCallCreate(programCode, newAddress,
gasLimit.getNoLeadZeroesData(),
value.getNoLeadZeroesData());
}
// [4] TRANSFER THE BALANCE
BigInteger endowment = value.value();
@ -329,10 +329,10 @@ public class Program {
Repository track = result.getRepository().startTracking();
// [5] COOK THE INVOKE AND EXECUTE
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
this, new DataWord(newAddress), DataWord.ZERO, gasLimit,
newBalance, null, track);
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
this, new DataWord(newAddress), DataWord.ZERO, gasLimit,
newBalance, null, track);
ProgramResult result = null;
if (programCode != null && programCode.length != 0) {
@ -345,7 +345,7 @@ public class Program {
}
if (result != null &&
result.getException() != null &&
result.getException() != null &&
result.getException() instanceof Program.OutOfGasException) {
logger.debug("contract run halted by Exception: contract: [{}], exception: [{}]",
Hex.toHexString(newAddress),
@ -397,7 +397,7 @@ public class Program {
* @param msg is the message call object
*/
public void callToAddress(MessageCall msg) {
byte[] data = memoryChunk(msg.getInDataOffs(), msg.getInDataSize()).array();
// FETCH THE SAVED STORAGE
@ -432,7 +432,7 @@ public class Program {
if (invokeData.byTestingSuite()) {
// This keeps track of the calls created for a test
this.getResult().addCallCreate(data, contextAddress,
this.getResult().addCallCreate(data, contextAddress,
msg.getGas().getNoLeadZeroesData(),
msg.getEndowment().getNoLeadZeroesData());
}
@ -441,10 +441,10 @@ public class Program {
this.spendGas(msg.getGas().longValue(), "internal call");
Repository trackRepository = result.getRepository().startTracking();
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
this, new DataWord(contextAddress), msg.getEndowment(),
msg.getGas(), contextBalance, data, trackRepository);
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
this, new DataWord(contextAddress), msg.getEndowment(),
msg.getGas(), contextBalance, data, trackRepository);
ProgramResult result = null;
if (programCode != null && programCode.length != 0) {
@ -458,8 +458,8 @@ public class Program {
}
if (result != null &&
result.getException() != null &&
result.getException() instanceof Program.OutOfGasException) {
result.getException() != null &&
result.getException() instanceof Program.OutOfGasException) {
gasLogger.debug("contract run halted by Exception: contract: [{}], exception: [{}]",
Hex.toHexString(contextAddress),
result.getException());
@ -494,9 +494,9 @@ public class Program {
if (refundGas.signum() == 1) {
this.refundGas(refundGas.longValue(), "remaining gas from the internal call");
if(gasLogger.isInfoEnabled())
gasLogger.info("The remaining gas refunded, account: [{}], gas: [{}] ",
Hex.toHexString(senderAddress),
refundGas.toString());
gasLogger.info("The remaining gas refunded, account: [{}], gas: [{}] ",
Hex.toHexString(senderAddress),
refundGas.toString());
}
} else {
this.refundGas(msg.getGas().longValue(), "remaining gas from the internal call");
@ -513,7 +513,7 @@ public class Program {
}
public void spendAllGas() {
spendGas(invokeData.getGas().longValue() - result.getGasUsed(), "Spending all remaining");
spendGas(invokeData.getGas().longValue() - result.getGasUsed(), "Spending all remaining");
}
public void refundGas(long gasValue, String cause) {
@ -536,7 +536,7 @@ public class Program {
}
public byte[] getCode() {
return ops;
return ops;
}
public byte[] getCodeAt(DataWord address) {
@ -544,7 +544,7 @@ public class Program {
byte[] code = invokeData.getRepository().getCode(address.getLast20Bytes());
if (code == null) code = ByteUtil.EMPTY_BYTE_ARRAY;
return code;
return code;
}
public DataWord getOwnerAddress() {
@ -646,7 +646,7 @@ public class Program {
byte value = memory.get(i);
// Check if value is ASCII
String character = ((byte) 0x20 <= value && value <= (byte) 0x7e) ? new String(new byte[] { value }) : "?";
String character = ((byte) 0x20 <= value && value <= (byte) 0x7e) ? new String(new byte[] { value }) : "?";
firstLine.append(character).append("");
secondLine.append(ByteUtil.oneByteToHexString(value)).append(" ");
@ -679,7 +679,7 @@ public class Program {
StringBuilder storageData = new StringBuilder();
if(contractDetails != null) {
List<DataWord> storageKeys = new ArrayList<>(contractDetails.getStorage().keySet());
Collections.sort((List<DataWord>) storageKeys);
Collections.sort((List<DataWord>) storageKeys);
for (DataWord key : storageKeys) {
storageData.append(" ").append(key).append(" -> ").
append(contractDetails.getStorage().get(key)).append("\n");
@ -741,18 +741,18 @@ public class Program {
globalOutput.append(" -- STORAGE -- ").append(storageData).append("\n");
if (result.getHReturn() != null)
globalOutput.append("\n HReturn: ").append(
Hex.toHexString(result.getHReturn().array()));
globalOutput.append("\n HReturn: ").append(
Hex.toHexString(result.getHReturn().array()));
// sophisticated assumption that msg.data != codedata
// means we are calling the contract not creating it
byte[] txData = invokeData.getDataCopy(DataWord.ZERO, getDataSize());
if (!Arrays.equals(txData, ops))
globalOutput.append("\n msg.data: ").append(Hex.toHexString(txData));
globalOutput.append("\n msg.data: ").append(Hex.toHexString(txData));
globalOutput.append("\n\n Spent Gas: ").append(result.getGasUsed());
if (listener != null)
listener.output(globalOutput.toString());
if (listener != null)
listener.output(globalOutput.toString());
}
}
@ -818,57 +818,57 @@ public class Program {
}
public static String stringify(byte[] code, int index, String result) {
if(code == null || code.length == 0)
return result;
OpCode op = OpCode.code(code[index]);
byte[] continuedCode = null;
switch(op) {
case PUSH1: case PUSH2: case PUSH3: case PUSH4: case PUSH5: case PUSH6: case PUSH7: case PUSH8:
case PUSH9: case PUSH10: case PUSH11: case PUSH12: case PUSH13: case PUSH14: case PUSH15: case PUSH16:
case PUSH17: case PUSH18: case PUSH19: case PUSH20: case PUSH21: case PUSH22: case PUSH23: case PUSH24:
case PUSH25: case PUSH26: case PUSH27: case PUSH28: case PUSH29: case PUSH30: case PUSH31: case PUSH32:
result += ' ' + op.name() + ' ';
int nPush = op.val() - OpCode.PUSH1.val() + 1;
byte[] data = Arrays.copyOfRange(code, index+1, index + nPush + 1);
result += new BigInteger(1, data).toString() + ' ';
continuedCode = Arrays.copyOfRange(code, index + nPush + 1, code.length);
break;
default:
result += ' ' + op.name();
continuedCode = Arrays.copyOfRange(code, index + 1, code.length);
break;
}
return stringify(continuedCode, 0, result);
if(code == null || code.length == 0)
return result;
OpCode op = OpCode.code(code[index]);
byte[] continuedCode = null;
switch(op) {
case PUSH1: case PUSH2: case PUSH3: case PUSH4: case PUSH5: case PUSH6: case PUSH7: case PUSH8:
case PUSH9: case PUSH10: case PUSH11: case PUSH12: case PUSH13: case PUSH14: case PUSH15: case PUSH16:
case PUSH17: case PUSH18: case PUSH19: case PUSH20: case PUSH21: case PUSH22: case PUSH23: case PUSH24:
case PUSH25: case PUSH26: case PUSH27: case PUSH28: case PUSH29: case PUSH30: case PUSH31: case PUSH32:
result += ' ' + op.name() + ' ';
int nPush = op.val() - OpCode.PUSH1.val() + 1;
byte[] data = Arrays.copyOfRange(code, index+1, index + nPush + 1);
result += new BigInteger(1, data).toString() + ' ';
continuedCode = Arrays.copyOfRange(code, index + nPush + 1, code.length);
break;
default:
result += ' ' + op.name();
continuedCode = Arrays.copyOfRange(code, index + 1, code.length);
break;
}
return stringify(continuedCode, 0, result);
}
public void addListener(ProgramListener listener) {
this.listener = listener;
}
public void addListener(ProgramListener listener) {
this.listener = listener;
}
public interface ProgramListener {
public void output(String out);
}
public interface ProgramListener {
public void output(String out);
}
@SuppressWarnings("serial")
public class OutOfGasException extends RuntimeException {}
@SuppressWarnings("serial")
public class OutOfGasException extends RuntimeException {}
@SuppressWarnings("serial")
public class IllegalOperationException extends RuntimeException {}
@SuppressWarnings("serial")
public class BadJumpDestinationException extends RuntimeException {}
@SuppressWarnings("serial")
public class StackTooSmallException extends RuntimeException {
public StackTooSmallException(String message) {
super(message);
}
}
@SuppressWarnings("serial")
public class StackTooSmallException extends RuntimeException {
public StackTooSmallException(String message) {
super(message);
}
}
/**
* used mostly for testing reasons

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