Strip trailing whitespace
This commit is contained in:
parent
0827fb5c8f
commit
e5fcf5b48e
12
README.md
12
README.md
|
@ -1,7 +1,7 @@
|
|||
[![ScreenShot](http://i.imgur.com/lJw1Tui.jpg)]
|
||||
|
||||
|
||||
# Welcome to ethereumj
|
||||
# Welcome to ethereumj
|
||||
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/ethereum/ethereumj?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Build Status](https://travis-ci.org/ethereum/ethereumj.svg?branch=master)](https://travis-ci.org/ethereum/ethereumj) [![Coverage Status](https://coveralls.io/repos/ethereum/ethereumj/badge.png?branch=master)](https://coveralls.io/r/ethereum/ethereumj?branch=master)
|
||||
[![Stories in Progress](https://badge.waffle.io/ethereum/ethereumj.png?title=In%20Progress&label=in_progress)](https://waffle.io/ethereum/ethereumj)
|
||||
|
@ -10,18 +10,18 @@
|
|||
|
||||
The ethereumj library is a Java implementation of the Ethereum protocol.
|
||||
|
||||
This repository currently contains:
|
||||
This repository currently contains:
|
||||
* [core](ethereumj-core): the core library which can be included into your own Java project.
|
||||
* [studio](ethereumj-studio): a simple graphic interface for Ethereum functionality and set of showcases for core usage.
|
||||
* [studio](ethereumj-studio): a simple graphic interface for Ethereum functionality and set of showcases for core usage.
|
||||
|
||||
For an early peek, have a looki at this [video](https://youtu.be/D5ok7jh7AOg)
|
||||
|
||||
# Todo
|
||||
|
||||
The Ethereum protocol is currenty heavily in development, thus so is this implementation.
|
||||
You can find a todo-list right [here](TODO.md) and the [milestone schedule](https://github.com/ethereum/ethereumj/milestones).
|
||||
You can find a todo-list right [here](TODO.md) and the [milestone schedule](https://github.com/ethereum/ethereumj/milestones).
|
||||
For questions you can reach us in #ethereumj on Freenode.
|
||||
|
||||
|
||||
# Documentation
|
||||
|
||||
To start you can visit [Ethereum.org](https://www.ethereum.org) and if you are looking for more information on the concept, the [ethereum white paper](https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-White-Paper) is a good place to start as it outlines the vision. For the more technical minded, a protocol description can be found in the [yellow paper](http://gavwood.com/Paper.pdf) by Gavin Wood.
|
||||
|
@ -34,6 +34,6 @@ https://bintray.com/ethereum/maven/org.ethereum/view
|
|||
|
||||
For building ethereumj-core or ethereumj-studio look in their own individual README
|
||||
|
||||
# License
|
||||
# License
|
||||
|
||||
This software is released under the MIT license, read it [here](LICENSE)
|
||||
|
|
28
TODO.md
28
TODO.md
|
@ -4,26 +4,26 @@
|
|||
----------------
|
||||
|
||||
- [ ] **GUI screen** a screen that will hold table with full state representation
|
||||
- [ ] **SerpentCompiler** compile create(gas, mem_start, import("examples/mul2.se"))
|
||||
- [ ] **SerpentCompiler** compile create(gas, mem_start, import("examples/mul2.se"))
|
||||
https://github.com/ethereum/wiki/wiki/Serpent
|
||||
- [ ] **SerpentCompiler** compile return(array) correct
|
||||
- [ ] **ProgramPlayDialog** support internal calls
|
||||
- [ ] **Performance:** BigInteger math change for constant arrays implementation
|
||||
- [ ] **Performance:** BigInteger math change for constant arrays implementation
|
||||
economy for memory allocation
|
||||
- [ ] **Command Line:** add the headless run option
|
||||
- [ ] **SerpentCompiler** Serpent new syntax:
|
||||
(@> @< @/ @%) - unsigned operations
|
||||
> < / % - default are all signed operations
|
||||
+= -= *= /= %= @/= @%= - short form operations
|
||||
- [ ] **Command Line:** add the headless run option
|
||||
- [ ] **SerpentCompiler** Serpent new syntax:
|
||||
(@> @< @/ @%) - unsigned operations
|
||||
> < / % - default are all signed operations
|
||||
+= -= *= /= %= @/= @%= - short form operations
|
||||
share - code section
|
||||
|
||||
- [ ] **LLL_to_ASM compiler** list style language to EVM assembly compiler:
|
||||
|
||||
- [ ] **LLL_to_ASM compiler** list style language to EVM assembly compiler:
|
||||
- [ ] **Use home-directory** Create .ethereumj in home-directory for blockchain, state & details database. Make configurable in system.properties so developer can choose user.dir without the creation of .ethereumj directory.
|
||||
|
||||
##### UnitTest:
|
||||
##### UnitTest:
|
||||
----------------
|
||||
|
||||
- [ ] **VM complex:** CREATE testing
|
||||
- [ ] **VM complex:** CREATE testing
|
||||
- [ ] **VM complex:** SUICIDE testing
|
||||
- [ ] **SerpentCompiler** compile return(array) correct
|
||||
- [ ] **WorldManager** apply transactions
|
||||
|
@ -36,14 +36,14 @@ share - code section
|
|||
- [X] ** Block Queue ** separate net layer and block processing layer, net layer should continue get
|
||||
blocks in time the vm layer process them (not stuck for it)
|
||||
- [X] **Build:** extract core module and studio application
|
||||
- [x] **VM execution:** support CALL op
|
||||
- [x] **VM execution:** support CALL op with in/out data
|
||||
- [x] **VM execution:** support CALL op
|
||||
- [x] **VM execution:** support CALL op with in/out data
|
||||
- [x] **VM execution:** support CREATE op
|
||||
- [x] **SerpentCompiler** compile create(gas, mem_start, mem_size)
|
||||
|
||||
- [x] **VM complex:** CALL testing for in arrays
|
||||
- [x] **VM complex:** CALL testing for out result
|
||||
- [x] **State management** trie for storage hash calculation
|
||||
- [x] **State management** trie for storage hash calculation
|
||||
and update hash into AccountState
|
||||
- [x] **VM execution:** SUICIDE op adjust
|
||||
- [x] **Testing by JSON files:** follow cpp client performs test case by getting json file contains the test describe
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
The core library API for Ethereum project can be included
|
||||
into any other Java/Scala project by simple maven
|
||||
script include:
|
||||
into any other Java/Scala project by simple maven
|
||||
script include:
|
||||
|
||||
```
|
||||
<dependency>
|
||||
|
@ -13,20 +13,20 @@ script include:
|
|||
```
|
||||
|
||||
|
||||
EthereumJ release repository can be found here:
|
||||
EthereumJ release repository can be found here:
|
||||
* https://bintray.com/ethereum/maven/org.ethereum/view
|
||||
|
||||
|
||||
The showcase for ethereumj-core usage can be found in [ethereumj-studio](../ethereumj-studio)
|
||||
|
||||
|
||||
###### :small_blue_diamond: Build instructions (maven)
|
||||
1. build_1: [no test run] , [released to local repository] : ~> ` mvn clean install -Dmaven.test.skip=true `
|
||||
2. build_2: [include test run] , [released to local repository] : ~> ` mvn clean install `
|
||||
|
||||
1. build_1: [no test run] , [released to local repository] : ~> ` mvn clean install -Dmaven.test.skip=true `
|
||||
2. build_2: [include test run] , [released to local repository] : ~> ` mvn clean install `
|
||||
|
||||
###### :small_blue_diamond: release instructions (ant) (!) credential required
|
||||
1. ` mvn install ` - which release the lib to a local repositroy
|
||||
2. after the release - ` ant -f bintray-publish-version.xml `
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -446,5 +446,5 @@
|
|||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.springframework.stereotype.Component;
|
|||
/**
|
||||
* Utility class to retrieve property values from the system.properties files
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 22/05/2014 19:22
|
||||
*/
|
||||
public class SystemProperties {
|
||||
|
@ -46,7 +46,7 @@ public class SystemProperties {
|
|||
private static Boolean DEFAULT_VM_TRACE = false;
|
||||
private static String DEFAULT_VM_TRACE_DIR = "dmp";
|
||||
private static int DEFAULT_PEER_LISTEN_PORT = 30303;
|
||||
|
||||
|
||||
/* Testing */
|
||||
private static Boolean DEFAULT_VMTEST_LOAD_LOCAL = false;
|
||||
|
||||
|
@ -281,17 +281,17 @@ public class SystemProperties {
|
|||
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();
|
||||
|
|
|
@ -12,32 +12,32 @@ import static org.ethereum.crypto.HashUtil.EMPTY_TRIE_HASH;
|
|||
public class AccountState {
|
||||
|
||||
private byte[] rlpEncoded;
|
||||
|
||||
|
||||
/* A value equal to the number of transactions sent
|
||||
* from this address, or, in the case of contract accounts,
|
||||
* from this address, or, in the case of contract accounts,
|
||||
* the number of contract-creations made by this account */
|
||||
private BigInteger nonce;
|
||||
|
||||
|
||||
/* A scalar value equal to the number of Wei owned by this address */
|
||||
private BigInteger balance;
|
||||
|
||||
/* A 256-bit hash of the root node of a trie structure
|
||||
* that encodes the storage contents of the contract,
|
||||
* itself a simple mapping between byte arrays of size 32.
|
||||
* The hash is formally denoted σ[a] s .
|
||||
*
|
||||
* Since I typically wish to refer not to the trie’s root hash
|
||||
|
||||
/* A 256-bit hash of the root node of a trie structure
|
||||
* that encodes the storage contents of the contract,
|
||||
* itself a simple mapping between byte arrays of size 32.
|
||||
* The hash is formally denoted σ[a] s .
|
||||
*
|
||||
* Since I typically wish to refer not to the trie’s root hash
|
||||
* but to the underlying set of key/value pairs stored within,
|
||||
* I define a convenient equivalence TRIE (σ[a] s ) ≡ σ[a] s .
|
||||
* It shall be understood that σ[a] s is not a ‘physical’ member
|
||||
* I define a convenient equivalence TRIE (σ[a] s ) ≡ σ[a] s .
|
||||
* It shall be understood that σ[a] s is not a ‘physical’ member
|
||||
* of the account and does not contribute to its later serialisation */
|
||||
private byte[] stateRoot = EMPTY_TRIE_HASH;
|
||||
|
||||
/* The hash of the EVM code of this contract—this is the code
|
||||
* that gets executed should this address receive a message call;
|
||||
* it is immutable and thus, unlike all other fields, cannot be changed
|
||||
* after construction. All such code fragments are contained in
|
||||
* the state database under their corresponding hashes for later
|
||||
|
||||
/* The hash of the EVM code of this contract—this is the code
|
||||
* that gets executed should this address receive a message call;
|
||||
* it is immutable and thus, unlike all other fields, cannot be changed
|
||||
* after construction. All such code fragments are contained in
|
||||
* the state database under their corresponding hashes for later
|
||||
* retrieval */
|
||||
private byte[] codeHash = EMPTY_DATA_HASH;
|
||||
|
||||
|
@ -53,7 +53,7 @@ public class AccountState {
|
|||
this.nonce = nonce;
|
||||
this.balance = balance;
|
||||
}
|
||||
|
||||
|
||||
public AccountState(byte[] rlpData) {
|
||||
this.rlpEncoded = rlpData;
|
||||
|
||||
|
@ -115,7 +115,7 @@ public class AccountState {
|
|||
this.balance = balance.subtract(value);
|
||||
setDirty(true);
|
||||
}
|
||||
|
||||
|
||||
public byte[] getEncoded() {
|
||||
if(rlpEncoded == null) {
|
||||
byte[] nonce = RLP.encodeBigInteger(this.nonce);
|
||||
|
|
|
@ -16,10 +16,10 @@ import java.util.List;
|
|||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* The block in Ethereum is the collection of relevant pieces of information
|
||||
* The block in Ethereum is the collection of relevant pieces of information
|
||||
* (known as the blockheader), H, together with information corresponding to
|
||||
* the comprised transactions, R, and a set of other blockheaders U that are known
|
||||
* to have a parent equal to the present block’s parent’s parent
|
||||
* the comprised transactions, R, and a set of other blockheaders U that are known
|
||||
* to have a parent equal to the present block’s parent’s parent
|
||||
* (such blocks are known as uncles).
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
|
@ -30,7 +30,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||
public class 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));
|
||||
|
@ -38,28 +38,28 @@ public class Block {
|
|||
.divide(BigInteger.valueOf(32));
|
||||
|
||||
private BlockHeader header;
|
||||
|
||||
|
||||
/* Transactions */
|
||||
private List<Transaction> transactionsList = new CopyOnWriteArrayList<>();
|
||||
|
||||
|
||||
/* Uncles */
|
||||
private List<BlockHeader> uncleList = new CopyOnWriteArrayList<>();
|
||||
|
||||
/* Private */
|
||||
|
||||
/* Private */
|
||||
|
||||
private byte[] rlpEncoded;
|
||||
private boolean parsed = false;
|
||||
|
||||
|
||||
private Trie txsState;
|
||||
|
||||
|
||||
/* Constructors */
|
||||
|
||||
|
||||
public Block(byte[] 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,
|
||||
|
@ -85,11 +85,11 @@ public class Block {
|
|||
|
||||
RLPList params = RLP.decode2(rlpEncoded);
|
||||
RLPList block = (RLPList) params.get(0);
|
||||
|
||||
|
||||
// Parse Header
|
||||
RLPList header = (RLPList) block.get(0);
|
||||
this.header = new BlockHeader(header);
|
||||
|
||||
|
||||
// Parse Transactions
|
||||
RLPList txTransactions = (RLPList) block.get(1);
|
||||
this.parseTxs(this.header.getTxTrieRoot(), txTransactions);
|
||||
|
@ -131,7 +131,7 @@ public class Block {
|
|||
return FastByteComparisons.compareTo(result, 0, 32, target, 0, 32) < 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public byte[] getParentHash() {
|
||||
if (!parsed) parseRLP();
|
||||
return this.header.getParentHash();
|
||||
|
@ -151,7 +151,7 @@ public class Block {
|
|||
if (!parsed) parseRLP();
|
||||
return this.header.getStateRoot();
|
||||
}
|
||||
|
||||
|
||||
public void setStateRoot(byte[] stateRoot) {
|
||||
if (!parsed) parseRLP();
|
||||
this.header.setStateRoot(stateRoot);
|
||||
|
@ -180,12 +180,12 @@ public class Block {
|
|||
}
|
||||
return calcDifficulty;
|
||||
}
|
||||
|
||||
|
||||
public long getTimestamp() {
|
||||
if (!parsed) parseRLP();
|
||||
return this.header.getTimestamp();
|
||||
}
|
||||
|
||||
|
||||
public long getNumber() {
|
||||
if (!parsed) parseRLP();
|
||||
return this.header.getNumber();
|
||||
|
@ -210,7 +210,7 @@ public class Block {
|
|||
if (!parsed) parseRLP();
|
||||
return this.header.getNonce();
|
||||
}
|
||||
|
||||
|
||||
public void setNonce(byte[] nonce) {
|
||||
this.header.setNonce(nonce);
|
||||
rlpEncoded = null;
|
||||
|
@ -228,7 +228,7 @@ public class Block {
|
|||
|
||||
private StringBuffer toStringBuff = new StringBuffer();
|
||||
// [parent_hash, uncles_hash, coinbase, state_root, tx_trie_root,
|
||||
// difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp,
|
||||
// difficulty, number, minGasPrice, gasLimit, gasUsed, timestamp,
|
||||
// extradata, nonce]
|
||||
|
||||
@Override
|
||||
|
@ -260,7 +260,7 @@ public class Block {
|
|||
toStringBuff.append("BlockData [");
|
||||
toStringBuff.append("hash=" + ByteUtil.toHexString(this.getHash())).append("");
|
||||
toStringBuff.append(header.toFlatString());
|
||||
|
||||
|
||||
for (Transaction tx : getTransactionsList()) {
|
||||
toStringBuff.append("\n");
|
||||
toStringBuff.append(tx.toString());
|
||||
|
@ -318,7 +318,7 @@ public class Block {
|
|||
this.getHeader().setUnclesHash( SHA3Helper.sha3( getUnclesEncoded() ));
|
||||
rlpEncoded = null;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getEncoded() {
|
||||
if(rlpEncoded == null) {
|
||||
byte[] header = this.header.getEncoded();
|
||||
|
@ -328,7 +328,7 @@ public class Block {
|
|||
}
|
||||
return rlpEncoded;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getEncodedWithoutNonce() {
|
||||
if (!parsed) parseRLP();
|
||||
byte[] header = this.header.getEncodedWithoutNonce();
|
||||
|
|
|
@ -11,23 +11,23 @@ import static org.ethereum.crypto.HashUtil.EMPTY_TRIE_HASH;
|
|||
import static org.ethereum.util.ByteUtil.toHexString;
|
||||
|
||||
/**
|
||||
* Block header is a value object containing
|
||||
* the basic information of a block
|
||||
* Block header is a value object containing
|
||||
* the basic information of a block
|
||||
*/
|
||||
public class BlockHeader {
|
||||
|
||||
|
||||
|
||||
/* The SHA3 256-bit hash of the parent block, in its entirety */
|
||||
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
|
||||
/* The 160-bit address to which all fees collected from the
|
||||
* successful mining of this block be transferred; formally */
|
||||
private byte[] coinbase;
|
||||
/* The SHA3 256-bit hash of the root node of the state trie,
|
||||
/* The SHA3 256-bit hash of the root node of the state trie,
|
||||
* after all transactions are executed and finalisations applied */
|
||||
private byte[] stateRoot;
|
||||
/* The SHA3 256-bit hash of the root node of the trie structure
|
||||
/* The SHA3 256-bit hash of the root node of the trie structure
|
||||
* populated with each transaction in the transaction
|
||||
* list portion, the trie is populate by [key, val] --> [rlp(index), rlp(tx_reciepe)]
|
||||
* of the block */
|
||||
|
@ -41,33 +41,33 @@ public class BlockHeader {
|
|||
/*todo: comment it when you know what the fuck it is*/
|
||||
private byte[] logsBloom;
|
||||
/* A scalar value corresponding to the difficulty level of this block.
|
||||
* This can be calculated from the previous block’s difficulty level
|
||||
* This can be calculated from the previous block’s difficulty level
|
||||
* and the timestamp */
|
||||
private byte[] difficulty;
|
||||
/* A scalar value equal to the reasonable output of Unix's time()
|
||||
/* A scalar value equal to the reasonable output of Unix's time()
|
||||
* at this block's inception */
|
||||
private long timestamp;
|
||||
/* A scalar value equal to the number of ancestor blocks.
|
||||
private long timestamp;
|
||||
/* A scalar value equal to the number of ancestor blocks.
|
||||
* The genesis block has a number of zero */
|
||||
private long number;
|
||||
/* A scalar value equal to the current limit of gas expenditure per block */
|
||||
private long gasLimit;
|
||||
/* A scalar value equal to the total gas used in transactions in this block */
|
||||
private long gasUsed;
|
||||
/* An arbitrary byte array containing data relevant to this block.
|
||||
/* An arbitrary byte array containing data relevant to this block.
|
||||
* With the exception of the genesis block, this must be 32 bytes or fewer */
|
||||
private byte[] extraData;
|
||||
/* A 256-bit hash which proves that a sufficient amount
|
||||
/* A 256-bit hash which proves that a sufficient amount
|
||||
* of computation has been carried out on this block */
|
||||
private byte[] nonce;
|
||||
|
||||
|
||||
public BlockHeader(RLPList rlpHeader) {
|
||||
|
||||
this.parentHash = rlpHeader.get(0).getRLPData();
|
||||
this.unclesHash = rlpHeader.get(1).getRLPData();
|
||||
this.coinbase = rlpHeader.get(2).getRLPData();
|
||||
this.stateRoot = rlpHeader.get(3).getRLPData();
|
||||
|
||||
|
||||
this.txTrieRoot = rlpHeader.get(4).getRLPData();
|
||||
if(this.txTrieRoot == null)
|
||||
this.txTrieRoot = EMPTY_TRIE_HASH;
|
||||
|
@ -78,23 +78,23 @@ public class BlockHeader {
|
|||
|
||||
this.logsBloom = rlpHeader.get(6).getRLPData();
|
||||
this.difficulty = rlpHeader.get(7).getRLPData();
|
||||
|
||||
|
||||
byte[] nrBytes = rlpHeader.get(8).getRLPData();
|
||||
byte[] glBytes = rlpHeader.get(9).getRLPData();
|
||||
byte[] guBytes = rlpHeader.get(10).getRLPData();
|
||||
byte[] tsBytes = rlpHeader.get(11).getRLPData();
|
||||
|
||||
|
||||
this.number = nrBytes == null ? 0 : (new BigInteger(1, nrBytes)).longValue();
|
||||
|
||||
this.gasLimit = glBytes == null ? 0 : (new BigInteger(1, glBytes)).longValue();
|
||||
this.gasUsed = guBytes == null ? 0 : (new BigInteger(1, guBytes)).longValue();
|
||||
this.timestamp = tsBytes == null ? 0 : (new BigInteger(1, tsBytes)).longValue();
|
||||
|
||||
|
||||
this.extraData = rlpHeader.get(12).getRLPData();
|
||||
this.nonce = rlpHeader.get(13).getRLPData();
|
||||
|
||||
}
|
||||
|
||||
|
||||
public BlockHeader(byte[] parentHash, byte[] unclesHash, byte[] coinbase,
|
||||
byte[] logsBloom, byte[] difficulty, long number,
|
||||
long gasLimit, long gasUsed, long timestamp,
|
||||
|
@ -112,10 +112,10 @@ public class BlockHeader {
|
|||
this.nonce = nonce;
|
||||
this.stateRoot = HashUtil.EMPTY_TRIE_HASH;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Calculate Difficulty
|
||||
* Calculate Difficulty
|
||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf - page 5, 4.3.4 (24)
|
||||
* @return byte array value of the difficulty
|
||||
*/
|
||||
|
@ -217,15 +217,15 @@ public class BlockHeader {
|
|||
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);
|
||||
|
||||
|
@ -262,7 +262,7 @@ public class BlockHeader {
|
|||
|
||||
|
||||
private StringBuffer toStringBuff = new StringBuffer();
|
||||
|
||||
|
||||
public String toString() {
|
||||
|
||||
toStringBuff.setLength(0);
|
||||
|
@ -281,7 +281,7 @@ public class BlockHeader {
|
|||
toStringBuff.append(" nonce=" + toHexString(nonce)).append("\n");
|
||||
return toStringBuff.toString();
|
||||
}
|
||||
|
||||
|
||||
public String toFlatString() {
|
||||
toStringBuff.append(" parentHash=" + toHexString(parentHash)).append("");
|
||||
toStringBuff.append(" unclesHash=" + toHexString(unclesHash)).append("");
|
||||
|
|
|
@ -29,14 +29,14 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
|||
import static org.ethereum.core.Denomination.SZABO;
|
||||
|
||||
/**
|
||||
* The Ethereum blockchain is in many ways similar to the Bitcoin blockchain,
|
||||
* although it does have some differences.
|
||||
*
|
||||
* The main difference between Ethereum and Bitcoin with regard to the blockchain architecture
|
||||
* is that, unlike Bitcoin, Ethereum blocks contain a copy of both the transaction list
|
||||
* and the most recent state. Aside from that, two other values, the block number and
|
||||
* the difficulty, are also stored in the block.
|
||||
*
|
||||
* The Ethereum blockchain is in many ways similar to the Bitcoin blockchain,
|
||||
* although it does have some differences.
|
||||
*
|
||||
* The main difference between Ethereum and Bitcoin with regard to the blockchain architecture
|
||||
* is that, unlike Bitcoin, Ethereum blocks contain a copy of both the transaction list
|
||||
* and the most recent state. Aside from that, two other values, the block number and
|
||||
* the difficulty, are also stored in the block.
|
||||
*
|
||||
* The block validation algorithm in Ethereum is as follows:
|
||||
* <ol>
|
||||
* <li>Check if the previous block referenced exists and is valid.</li>
|
||||
|
@ -44,9 +44,9 @@ import static org.ethereum.core.Denomination.SZABO;
|
|||
* <li>Check that the block number, difficulty, transaction root, uncle root and gas limit (various low-level Ethereum-specific concepts) are valid.</li>
|
||||
* <li>Check that the proof of work on the block is valid.</li>
|
||||
* <li>Let S[0] be the STATE_ROOT of the previous block.</li>
|
||||
* <li>Let 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]).
|
||||
* If any applications returns an error, or if the total gas consumed in the block
|
||||
* <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]).
|
||||
* 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>
|
||||
* <li>Check if S_FINAL is the same as the STATE_ROOT. If it is, the block is valid; otherwise, it is not valid.</li>
|
||||
|
@ -66,7 +66,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
|
||||
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();
|
||||
|
||||
|
@ -107,7 +107,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
public byte[] getBestBlockHash() {
|
||||
return getBestBlock().getHash();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSize() {
|
||||
return bestBlock.getNumber() + 1;
|
||||
|
@ -313,7 +313,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
logger.warn("Invalid block with nr: {}", block.getNumber());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<TransactionReceipt> applyBlock(Block block) {
|
||||
|
||||
int i = 1;
|
||||
|
@ -363,15 +363,15 @@ public class BlockchainImpl implements Blockchain {
|
|||
/**
|
||||
* 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
|
||||
|
||||
// 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);
|
||||
|
@ -381,7 +381,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
}
|
||||
track.addBalance(block.getCoinbase(), totalBlockReward);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void storeBlock(Block block, List<TransactionReceipt> receipts) {
|
||||
|
||||
|
@ -408,8 +408,8 @@ public class BlockchainImpl implements Blockchain {
|
|||
logger.debug("block added to the blockChain: index: [{}]", block.getNumber());
|
||||
if (block.getNumber() % 100 == 0)
|
||||
logger.info("*** Last block added [ #{} ]", block.getNumber());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean hasParentOnTheChain(Block block){
|
||||
return getParent(block.getHeader()) != null;
|
||||
|
|
|
@ -12,10 +12,10 @@ public enum Denomination {
|
|||
FINNY(newBigInt(15)),
|
||||
ETHER(newBigInt(18)),
|
||||
EINSTEIN(newBigInt(21)),
|
||||
DOUGLAS(newBigInt(42));
|
||||
|
||||
DOUGLAS(newBigInt(42));
|
||||
|
||||
private BigInteger amount;
|
||||
|
||||
|
||||
private Denomination(BigInteger value) {
|
||||
this.amount = value;
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public enum Denomination {
|
|||
public BigInteger value() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
public long longValue() {
|
||||
return value().longValue();
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public enum Denomination {
|
|||
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";
|
||||
|
|
|
@ -10,26 +10,26 @@ import org.ethereum.trie.TrieImpl;
|
|||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* The genesis block is the first block in the chain and has fixed values according to
|
||||
* The genesis block is the first block in the chain and has fixed values according to
|
||||
* the protocol specification. The genesis block is 13 items, and is specified thus:
|
||||
*
|
||||
*
|
||||
* ( zerohash_256 , SHA3 RLP () , zerohash_160 , stateRoot, 0, 2^22 , 0, 0, 1000000, 0, 0, 0, SHA3 (42) , (), () )
|
||||
*
|
||||
* - Where zerohash_256 refers to the parent hash, a 256-bit hash which is all zeroes;
|
||||
* - zerohash_160 refers to the coinbase address, a 160-bit hash which is all zeroes;
|
||||
* - 2^22 refers to the difficulty;
|
||||
* - 0 refers to the timestamp (the Unix epoch);
|
||||
* - the transaction trie root and extradata are both 0, being equivalent to the empty byte array.
|
||||
* - The sequences of both uncles and transactions are empty and represented by ().
|
||||
* - SHA3 (42) refers to the SHA3 hash of a byte array of length one whose first and only byte is of value 42.
|
||||
*
|
||||
* - Where zerohash_256 refers to the parent hash, a 256-bit hash which is all zeroes;
|
||||
* - zerohash_160 refers to the coinbase address, a 160-bit hash which is all zeroes;
|
||||
* - 2^22 refers to the difficulty;
|
||||
* - 0 refers to the timestamp (the Unix epoch);
|
||||
* - the transaction trie root and extradata are both 0, being equivalent to the empty byte array.
|
||||
* - The sequences of both uncles and transactions are empty and represented by ().
|
||||
* - SHA3 (42) refers to the SHA3 hash of a byte array of length one whose first and only byte is of value 42.
|
||||
* - SHA3 RLP () value refers to the hash of the uncle lists in RLP, both empty lists.
|
||||
*
|
||||
*
|
||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf (Appendix I. Genesis Block)
|
||||
*/
|
||||
public class Genesis extends Block {
|
||||
|
||||
public final static BigInteger PREMINE_AMOUNT = BigInteger.valueOf(2).pow(200);
|
||||
|
||||
|
||||
private static String[] premine = new String[] {
|
||||
"51ba59315b3a95761d0863b05ccc7a7f54703d99",
|
||||
"e6716f9544a56c530d868e4bfbacb172315bdead", // # (J)
|
||||
|
@ -56,14 +56,14 @@ public class Genesis extends Block {
|
|||
public static long TIMESTAMP = 0;
|
||||
public static byte[] EXTRA_DATA = new byte[0];
|
||||
public static byte[] NONCE = sha3(new byte[]{42});
|
||||
|
||||
|
||||
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);
|
||||
// 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.
|
||||
|
@ -74,14 +74,14 @@ public class Genesis extends Block {
|
|||
|
||||
setStateRoot(state.getRootHash());
|
||||
}
|
||||
|
||||
|
||||
public static Block getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new Genesis();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
public final static String[] getPremine() {
|
||||
return premine;
|
||||
}
|
||||
|
|
|
@ -16,17 +16,17 @@ import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
|||
import static org.ethereum.util.ByteUtil.ZERO_BYTE_ARRAY;
|
||||
|
||||
/**
|
||||
* A transaction (formally, T) is a single cryptographically
|
||||
* signed instruction sent by an actor external to Ethereum.
|
||||
* An external actor can be a person (via a mobile device or desktop computer)
|
||||
* or could be from a piece of automated software running on a server.
|
||||
* There are two types of transactions: those which result in message calls
|
||||
* A transaction (formally, T) is a single cryptographically
|
||||
* signed instruction sent by an actor external to Ethereum.
|
||||
* An external actor can be a person (via a mobile device or desktop computer)
|
||||
* or could be from a piece of automated software running on a server.
|
||||
* There are two types of transactions: those which result in message calls
|
||||
* and those which result in the creation of new contracts.
|
||||
*/
|
||||
public class Transaction {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Transaction.class);
|
||||
|
||||
|
||||
/* SHA3 hash of the RLP encoded transaction */
|
||||
private byte[] hash;
|
||||
|
||||
|
@ -64,7 +64,7 @@ public class Transaction {
|
|||
/* Tx in encoded form */
|
||||
private byte[] rlpEncoded;
|
||||
private byte[] rlpRaw;
|
||||
/* Indicates if this transaction has been parsed
|
||||
/* Indicates if this transaction has been parsed
|
||||
* from the RLP-encoded data */
|
||||
private boolean parsed = false;
|
||||
|
||||
|
@ -295,7 +295,7 @@ public class Transaction {
|
|||
byte[] data = RLP.encodeElement(this.data);
|
||||
|
||||
byte[] v, r, s;
|
||||
|
||||
|
||||
if(signature != null) {
|
||||
v = RLP.encodeByte( signature.v );
|
||||
r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r));
|
||||
|
|
|
@ -13,9 +13,9 @@ import java.util.List;
|
|||
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
/**
|
||||
* The transaction receipt is a tuple of three items
|
||||
* comprising the transaction, together with the post-transaction state,
|
||||
* and the cumulative gas used in the block containing the transaction receipt
|
||||
* The transaction receipt is a tuple of three items
|
||||
* comprising the transaction, together with the post-transaction state,
|
||||
* and the cumulative gas used in the block containing the transaction receipt
|
||||
* as of immediately after the transaction has happened,
|
||||
*
|
||||
*
|
||||
|
|
|
@ -40,7 +40,7 @@ public class 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<>();
|
||||
|
@ -141,13 +141,13 @@ public class Wallet {
|
|||
|
||||
return walletTransaction;
|
||||
}
|
||||
|
||||
|
||||
public void addTransactions(List<Transaction> transactions) {
|
||||
for (Transaction transaction : transactions) {
|
||||
this.addTransaction(transaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void removeTransactions(List<Transaction> transactions) {
|
||||
for (Transaction tx : transactions) {
|
||||
if (logger.isDebugEnabled())
|
||||
|
@ -182,7 +182,7 @@ public class Wallet {
|
|||
Account receiver = rows.get(Hex.toHexString(receiveAddress));
|
||||
if (receiver != null) {
|
||||
receiver.addPendingTransaction(transaction);
|
||||
|
||||
|
||||
logger.info("Pending transaction added to " +
|
||||
"\n account: [{}], " +
|
||||
"\n tx: [{}]",
|
||||
|
@ -221,7 +221,7 @@ public class Wallet {
|
|||
<value>900099909<value/>
|
||||
</row>
|
||||
</wallet>
|
||||
|
||||
|
||||
*/
|
||||
|
||||
String dir = System.getProperty("user.dir");
|
||||
|
|
|
@ -50,7 +50,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
* Creating a new ECKey with the empty constructor will generate a new random keypair. Other static methods can be used
|
||||
* when you already have the public or private parts. If you create a key with only the public part, you can check
|
||||
* signatures but not create them.</p>
|
||||
*
|
||||
*
|
||||
* <p>The ECDSA algorithm supports <i>key recovery</i> in which a signature plus a couple of discriminator bits can
|
||||
* be reversed to find the public key used to calculate it. This can be convenient when you have a message and a
|
||||
* signature and want to find out who signed it, rather than requiring the user to provide the expected identity.</p>
|
||||
|
@ -70,7 +70,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
*/
|
||||
public class ECKey implements Serializable {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ECKey.class);
|
||||
|
||||
|
||||
/** The parameters of the secp256k1 curve that Ethereum uses. */
|
||||
public static final ECDomainParameters CURVE;
|
||||
|
||||
|
@ -90,7 +90,7 @@ public class ECKey implements Serializable {
|
|||
HALF_CURVE_ORDER = params.getN().shiftRight(1);
|
||||
secureRandom = new SecureRandom();
|
||||
}
|
||||
|
||||
|
||||
// The two parts of the key. If "priv" is set, "pub" can always be calculated. If "pub" is set but not "priv", we
|
||||
// can only verify signatures not make them.
|
||||
// TODO: Redesign this class to use consistent internals and more efficient serialization.
|
||||
|
@ -129,7 +129,7 @@ public class ECKey implements Serializable {
|
|||
throw new IllegalArgumentException("Public key may not be null");
|
||||
this.pub = pub;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility for compressing an elliptic curve point. Returns the same point if it's already compressed.
|
||||
* See the ECKey class docs for a discussion of point compression.
|
||||
|
@ -145,7 +145,7 @@ public class ECKey implements Serializable {
|
|||
public static ECPoint decompressPoint(ECPoint compressed) {
|
||||
return CURVE.getCurve().decodePoint(compressed.getEncoded(false));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates an ECKey given the private key only. The public key is calculated from it (this is slow). Note that
|
||||
* the resulting public key is compressed.
|
||||
|
@ -197,7 +197,7 @@ public class ECKey implements Serializable {
|
|||
public static ECKey fromPublicOnly(byte[] pub) {
|
||||
return new ECKey(null, CURVE.getCurve().decodePoint(pub));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a copy of this key, but with the public point represented in uncompressed form. Normally you would
|
||||
* never need this: it's for specialised scenarios or when backwards compatibility in encoded form is necessary.
|
||||
|
@ -224,7 +224,7 @@ public class ECKey implements Serializable {
|
|||
public boolean hasPrivKey() {
|
||||
return priv != null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns public key bytes from the given private key. To convert a byte array into a BigInteger, use <tt>
|
||||
* new BigInteger(1, bytes);</tt>
|
||||
|
@ -293,7 +293,7 @@ public class ECKey implements Serializable {
|
|||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Groups the two components that make up a signature, and provides a way to encode to Base64 form, which is
|
||||
* how ECDSA signatures are represented when embedded in other data structures in the Ethereum protocol. The raw
|
||||
|
@ -311,11 +311,11 @@ public class ECKey implements Serializable {
|
|||
this.r = r;
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
|
||||
private static ECDSASignature fromComponents(byte[] r, byte[] s) {
|
||||
return new ECDSASignature(new BigInteger(1, r), new BigInteger(1, s));
|
||||
}
|
||||
|
||||
|
||||
public static ECDSASignature fromComponents(byte[] r, byte[] s, byte v) {
|
||||
ECDSASignature signature = fromComponents(r, s);
|
||||
signature.v = v;
|
||||
|
@ -341,7 +341,7 @@ public class ECKey implements Serializable {
|
|||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String toBase64() {
|
||||
byte[] sigData = new byte[65]; // 1 header + 32 bytes for R + 32 bytes for S
|
||||
sigData[0] = v;
|
||||
|
@ -349,7 +349,7 @@ public class ECKey implements Serializable {
|
|||
System.arraycopy(bigIntegerToBytes(this.s, 32), 0, sigData, 33, 32);
|
||||
return new String(Base64.encode(sigData), Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
@ -370,11 +370,11 @@ public class ECKey implements Serializable {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Signs the given hash and returns the R and S components as BigIntegers
|
||||
* and put them in ECDSASignature
|
||||
*
|
||||
* Signs the given hash and returns the R and S components as BigIntegers
|
||||
* and put them in ECDSASignature
|
||||
*
|
||||
* @param input to sign
|
||||
* @return ECDSASignature signature that contains the R and S components
|
||||
*/
|
||||
|
@ -389,7 +389,7 @@ public class ECKey implements Serializable {
|
|||
BigInteger[] components = signer.generateSignature(input);
|
||||
return new ECDSASignature(components[0], components[1]).toCanonicalised();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Takes the sha3 hash (32 bytes) of data and returns the ECDSA signature
|
||||
*
|
||||
|
@ -413,12 +413,12 @@ public class ECKey implements Serializable {
|
|||
sig.v = (byte) (recId + 27 + (isCompressed() ? 4 : 0));
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Given a piece of text and a message signature encoded in base64, returns an ECKey
|
||||
* containing the public key that was used to sign it. This can then be compared to the expected public key to
|
||||
* determine if the signature was correct.
|
||||
*
|
||||
*
|
||||
* @param messageHash a piece of human readable text that was signed
|
||||
* @param signatureBase64 The Ethereum-format message signature in base64
|
||||
* @throws SignatureException If the public key could not be recovered or if there was a signature format error.
|
||||
|
@ -453,10 +453,10 @@ public class ECKey implements Serializable {
|
|||
throw new SignatureException("Could not recover public key from signature");
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Verifies the given ECDSA signature against the message bytes using the public key bytes.</p>
|
||||
*
|
||||
*
|
||||
* <p>When using native ECDSA verification, data must be 32 bytes, and no element may be
|
||||
* larger than 520 bytes.</p>
|
||||
*
|
||||
|
@ -471,7 +471,7 @@ public class ECKey implements Serializable {
|
|||
try {
|
||||
return signer.verifySignature(data, signature.r, signature.s);
|
||||
} catch (NullPointerException npe) {
|
||||
// Bouncy Castle contains a bug that can cause NPEs given specially crafted signatures.
|
||||
// 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.
|
||||
logger.error("Caught NPE inside bouncy castle", npe);
|
||||
return false;
|
||||
|
@ -637,7 +637,7 @@ public class ECKey implements Serializable {
|
|||
byte[] bits = getPubKey();
|
||||
return (bits[0] & 0xFF) | ((bits[1] & 0xFF) << 8) | ((bits[2] & 0xFF) << 16) | ((bits[3] & 0xFF) << 24);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class MissingPrivateKeyException extends RuntimeException {
|
||||
}
|
||||
|
|
|
@ -18,14 +18,14 @@ import org.ethereum.util.LRUMap;
|
|||
|
||||
public class HashUtil {
|
||||
|
||||
private static final int MAX_ENTRIES = 100; // Should contain most commonly hashed values
|
||||
private static final int MAX_ENTRIES = 100; // Should contain most commonly hashed values
|
||||
private static LRUMap<ByteArrayWrapper, byte[]> sha3Cache = new LRUMap<>(0, MAX_ENTRIES);
|
||||
public static final byte[] EMPTY_DATA_HASH = sha3(EMPTY_BYTE_ARRAY);
|
||||
public static final byte[] EMPTY_LIST_HASH = sha3(RLP.encodeList());
|
||||
public static final byte[] EMPTY_TRIE_HASH = sha3(RLP.encodeElement(EMPTY_BYTE_ARRAY));
|
||||
|
||||
private static final MessageDigest sha256digest;
|
||||
|
||||
|
||||
static {
|
||||
try {
|
||||
sha256digest = MessageDigest.getInstance("SHA-256");
|
||||
|
@ -33,7 +33,7 @@ public class HashUtil {
|
|||
throw new RuntimeException(e); // Can't happen.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static byte[] sha256(byte[] input) {
|
||||
return sha256digest.digest(input);
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class HashUtil {
|
|||
sha3Cache.put(inputByteArray, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static byte[] ripemd160(byte[] message) {
|
||||
Digest digest = new RIPEMD160Digest();
|
||||
if (message != null) {
|
||||
|
@ -83,7 +83,7 @@ public class HashUtil {
|
|||
|
||||
return newAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see #doubleDigest(byte[], int, int)
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
public static String sha3String(String message) {
|
||||
return sha3String(message, new SHA3Digest(DEFAULT_SIZE), true);
|
||||
}
|
||||
|
@ -75,23 +75,23 @@ public class SHA3Helper {
|
|||
digest.doFinal(hash, 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
public enum Size {
|
||||
|
||||
|
||||
S224(224),
|
||||
S256(256),
|
||||
S384(384),
|
||||
S512(512);
|
||||
|
||||
|
||||
int bits = 0;
|
||||
|
||||
|
||||
Size(int bits) {
|
||||
this.bits = bits;
|
||||
}
|
||||
|
||||
|
||||
public int getValue() {
|
||||
return this.bits;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {
|
|||
return false;
|
||||
byte[] otherData = ((ByteArrayWrapper) other).getData();
|
||||
return FastByteComparisons.compareTo(
|
||||
data, 0, data.length,
|
||||
data, 0, data.length,
|
||||
otherData, 0, otherData.length) == 0;
|
||||
}
|
||||
|
||||
|
@ -36,10 +36,10 @@ public class ByteArrayWrapper implements Comparable<ByteArrayWrapper> {
|
|||
@Override
|
||||
public int compareTo(ByteArrayWrapper o) {
|
||||
return FastByteComparisons.compareTo(
|
||||
data, 0, data.length,
|
||||
data, 0, data.length,
|
||||
o.getData(), 0, o.getData().length);
|
||||
}
|
||||
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public class ContractDetails {
|
|||
|
||||
public ContractDetails() {
|
||||
}
|
||||
|
||||
|
||||
public ContractDetails(byte[] rlpCode) {
|
||||
decode(rlpCode);
|
||||
}
|
||||
|
|
|
@ -4,26 +4,26 @@ 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);
|
||||
|
||||
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);
|
||||
|
|
|
@ -19,18 +19,18 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Generic interface for Ethereum database
|
||||
*
|
||||
*
|
||||
* LevelDB key/value pair DB implementation will be used.
|
||||
* Choice must be made between:
|
||||
* Pure Java: https://github.com/dain/leveldb
|
||||
* JNI binding: https://github.com/fusesource/leveldbjni
|
||||
*/
|
||||
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
|
||||
this.name = name;
|
||||
|
@ -69,9 +69,9 @@ public class DatabaseImpl implements Database {
|
|||
} 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();
|
||||
|
@ -81,12 +81,12 @@ public class DatabaseImpl implements Database {
|
|||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] get(byte[] key) {
|
||||
return db.get(key);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void put(byte[] key, byte[] value) {
|
||||
|
||||
|
@ -96,7 +96,7 @@ public class DatabaseImpl implements Database {
|
|||
Hex.toHexString(value));
|
||||
db.put(key, value);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void delete(byte[] key) {
|
||||
if(logger.isDebugEnabled())
|
||||
|
@ -104,11 +104,11 @@ public class DatabaseImpl implements Database {
|
|||
|
||||
db.delete(key);
|
||||
}
|
||||
|
||||
|
||||
public DBIterator iterator() {
|
||||
return db.iterator();
|
||||
}
|
||||
|
||||
|
||||
public DB getDb() {
|
||||
return this.db;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ public interface Repository {
|
|||
|
||||
/**
|
||||
* Create a new account in the database
|
||||
*
|
||||
*
|
||||
* @param addr of the contract
|
||||
* @return newly created account state
|
||||
*/
|
||||
|
@ -34,65 +34,65 @@ 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
|
||||
*/
|
||||
public AccountState getAccountState(byte[] addr);
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the account
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
*/
|
||||
public void delete(byte[] addr);
|
||||
|
||||
|
||||
/**
|
||||
* Increase the account nonce of the given account by one
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @return new value of the nonce
|
||||
*/
|
||||
public BigInteger increaseNonce(byte[] addr);
|
||||
|
||||
|
||||
/**
|
||||
* Get current nonce of a given account
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @return value of the nonce
|
||||
*/
|
||||
public BigInteger getNonce(byte[] addr);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve contract details for a given account from the database
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @return new contract details
|
||||
* @return new contract details
|
||||
*/
|
||||
public ContractDetails getContractDetails(byte[] addr);
|
||||
|
||||
|
||||
/**
|
||||
* Store code associated with an account
|
||||
*
|
||||
*
|
||||
* @param addr for the account
|
||||
* @param code that will be associated with this account
|
||||
*/
|
||||
public void saveCode(byte[] addr, byte[] code);
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the code associated with an account
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @return code in byte-array format
|
||||
*/
|
||||
public byte[] getCode(byte[] addr);
|
||||
|
||||
|
||||
/**
|
||||
* Put a value in storage of an account at a given key
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @param key of the data to store
|
||||
* @param value is the data to store
|
||||
|
@ -102,34 +102,34 @@ public interface Repository {
|
|||
|
||||
/**
|
||||
* Retrieve storage value from an account for a given key
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @param key associated with this value
|
||||
* @return data in the form of a <code>DataWord</code>
|
||||
*/
|
||||
public DataWord getStorageValue(byte[] addr, DataWord key);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve balance of an account
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @return balance of the account as a <code>BigInteger</code> value
|
||||
*/
|
||||
public BigInteger getBalance(byte[] addr);
|
||||
|
||||
|
||||
/**
|
||||
* Add value to the balance of an account
|
||||
*
|
||||
*
|
||||
* @param addr of the account
|
||||
* @param value to be added
|
||||
* @return new balance of the account
|
||||
*/
|
||||
public BigInteger addBalance(byte[] addr, BigInteger value);
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator over the accounts in this database in proper sequence
|
||||
*
|
||||
*
|
||||
* @return an iterator over the accounts in this database in proper sequence
|
||||
*/
|
||||
public DBIterator getAccountsIterator();
|
||||
|
@ -137,12 +137,12 @@ public interface Repository {
|
|||
|
||||
/**
|
||||
* Dump the full state of the current repository into a file with JSON format
|
||||
* It contains all the contracts/account, their attributes and
|
||||
*
|
||||
* It contains all the contracts/account, their attributes and
|
||||
*
|
||||
* @param block of the current state
|
||||
* @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.
|
||||
* @param txHash is the hash of the given transaction.
|
||||
* If null, the block state post coinbase reward is dumped.
|
||||
*/
|
||||
public void dumpState(Block block, long gasUsed, int txNumber, byte[] txHash);
|
||||
|
@ -158,13 +158,13 @@ public interface Repository {
|
|||
|
||||
|
||||
/**
|
||||
* Store all the temporary changes made
|
||||
* Store all the temporary changes made
|
||||
* to the repository in the actual database
|
||||
*/
|
||||
public void commit();
|
||||
|
||||
|
||||
/**
|
||||
* Undo all the changes made so far
|
||||
* Undo all the changes made so far
|
||||
* to a snapshot of the repository
|
||||
*/
|
||||
public void rollback();
|
||||
|
@ -175,13 +175,13 @@ public interface Repository {
|
|||
* @param root - new root
|
||||
*/
|
||||
public void syncToRoot(byte[] root);
|
||||
|
||||
|
||||
/**
|
||||
* Check to see if the current repository has an open connection to the database
|
||||
* @return <tt>true</tt> if connection to database is open
|
||||
*/
|
||||
public boolean isClosed();
|
||||
|
||||
|
||||
/**
|
||||
* Close the database
|
||||
*/
|
||||
|
|
|
@ -11,9 +11,9 @@ import com.fasterxml.jackson.databind.JsonMappingException;
|
|||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* An extended {@link com.fasterxml.jackson.databind.ObjectMapper ObjectMapper} class to
|
||||
* An extended {@link com.fasterxml.jackson.databind.ObjectMapper ObjectMapper} class to
|
||||
* customize ethereum state dumps.
|
||||
*
|
||||
*
|
||||
* @author Alon Muroch
|
||||
*
|
||||
*/
|
||||
|
@ -21,7 +21,7 @@ public class EtherObjectMapper extends ObjectMapper {
|
|||
|
||||
@Override
|
||||
public String writeValueAsString(Object value)
|
||||
throws JsonProcessingException {
|
||||
throws JsonProcessingException {
|
||||
// alas, we have to pull the recycler directly here...
|
||||
SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler());
|
||||
try {
|
||||
|
@ -29,7 +29,7 @@ public class EtherObjectMapper extends ObjectMapper {
|
|||
// set ethereum custom pretty printer
|
||||
EtherPrettyPrinter pp = new EtherPrettyPrinter();
|
||||
ge.setPrettyPrinter(pp);
|
||||
|
||||
|
||||
_configAndWriteValue(ge, value);
|
||||
} catch (JsonProcessingException e) { // to support [JACKSON-758]
|
||||
throw e;
|
||||
|
@ -38,11 +38,11 @@ public class EtherObjectMapper extends ObjectMapper {
|
|||
}
|
||||
return sw.getAndClear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An extended {@link com.fasterxml.jackson.core.util.DefaultPrettyPrinter} class to customize
|
||||
* An extended {@link com.fasterxml.jackson.core.util.DefaultPrettyPrinter} class to customize
|
||||
* an ethereum {@link com.fasterxml.jackson.core.PrettyPrinter Pretty Printer} Generator
|
||||
*
|
||||
*
|
||||
* @author Alon Muroch
|
||||
*
|
||||
*/
|
||||
|
@ -51,7 +51,7 @@ public class EtherObjectMapper extends ObjectMapper {
|
|||
public EtherPrettyPrinter() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void writeObjectFieldValueSeparator(JsonGenerator jg)
|
||||
throws IOException, JsonGenerationException {
|
||||
|
|
|
@ -16,26 +16,26 @@ import java.math.BigInteger;
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* JSON Helper class to format data into ObjectNodes
|
||||
* JSON Helper class to format data into ObjectNodes
|
||||
* 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
|
||||
*
|
||||
* @author: Roman Mandeleil
|
||||
|
@ -43,14 +43,14 @@ 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);
|
||||
|
||||
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()));
|
||||
|
@ -61,14 +61,14 @@ public class JSONHelper {
|
|||
account.put("nonce", state.getNonce() == null ? "0" : state.getNonce().toString());
|
||||
account.put("storage", storage);
|
||||
account.put("storage_root", state.getStateRoot() == null ? "" : Hex.toHexString(state.getStateRoot()));
|
||||
|
||||
|
||||
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");
|
||||
|
@ -76,25 +76,25 @@ public class JSONHelper {
|
|||
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) {
|
||||
byte[] keyBytes = key.getData();
|
||||
AccountState accountState = repository.getAccountState(keyBytes);
|
||||
ContractDetails details = repository.getContractDetails(keyBytes);
|
||||
JSONHelper.dumpState(statesNode, Hex.toHexString(keyBytes), accountState, details);
|
||||
}
|
||||
}
|
||||
blockNode.put("state", statesNode);
|
||||
|
||||
|
||||
blockNode.put("state_root", Hex.toHexString(state));
|
||||
blockNode.put("timestamp", String.valueOf(block.getTimestamp()));
|
||||
|
||||
|
||||
ArrayNode transactionsNode = blockNode.arrayNode();
|
||||
blockNode.put("transactions", transactionsNode);
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ public class JSONReader {
|
|||
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 {
|
||||
|
@ -36,7 +36,7 @@ public class JSONReader {
|
|||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
public static String getFromUrl(String urlToRead) {
|
||||
URL url;
|
||||
HttpURLConnection conn;
|
||||
|
|
|
@ -15,7 +15,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
public class Logs {
|
||||
List<LogInfo> logs = new ArrayList<>();
|
||||
|
||||
|
||||
public Logs(JSONArray jLogs) {
|
||||
|
||||
for (int i = 0; i < jLogs.size(); ++i){
|
||||
|
|
|
@ -23,7 +23,7 @@ public class TestCase {
|
|||
|
||||
// "env": { ... },
|
||||
private Env env;
|
||||
|
||||
|
||||
//
|
||||
private Logs logs;
|
||||
|
||||
|
@ -64,7 +64,7 @@ public class TestCase {
|
|||
JSONArray callCreates = new JSONArray();
|
||||
if(testCaseJSONObj.containsKey("callcreates"))
|
||||
callCreates = (JSONArray)testCaseJSONObj.get("callcreates");
|
||||
|
||||
|
||||
JSONArray logsJSON = new JSONArray();
|
||||
if(testCaseJSONObj.containsKey("logs"))
|
||||
logsJSON = (JSONArray)testCaseJSONObj.get("logs");
|
||||
|
@ -74,7 +74,7 @@ public class TestCase {
|
|||
if(testCaseJSONObj.containsKey("gas"))
|
||||
gasString = testCaseJSONObj.get("gas").toString();
|
||||
this.gas = ByteUtil.bigIntegerToBytes(new BigInteger(gasString));
|
||||
|
||||
|
||||
String outString = null;
|
||||
if(testCaseJSONObj.containsKey("out"))
|
||||
outString = testCaseJSONObj.get("out").toString();
|
||||
|
@ -122,7 +122,7 @@ public class TestCase {
|
|||
public Exec getExec() {
|
||||
return exec;
|
||||
}
|
||||
|
||||
|
||||
public Logs getLogs() {
|
||||
return logs;
|
||||
}
|
||||
|
|
|
@ -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<>();
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
|||
|
||||
/**
|
||||
* WorldManager is a singleton containing references to different parts of the system.
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 01/06/2014 10:44
|
||||
*/
|
||||
@Component
|
||||
|
@ -57,12 +57,12 @@ public class WorldManager {
|
|||
|
||||
@Autowired
|
||||
private AdminInfo adminInfo;
|
||||
|
||||
|
||||
private final Set<Transaction> pendingTransactions = Collections.synchronizedSet(new HashSet<Transaction>());
|
||||
|
||||
@Autowired
|
||||
private EthereumListener listener;
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
byte[] cowAddr = HashUtil.sha3("cow".getBytes());
|
||||
|
@ -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);
|
||||
|
@ -115,7 +115,7 @@ public class WorldManager {
|
|||
public EthereumListener getListener() {
|
||||
return listener;
|
||||
}
|
||||
|
||||
|
||||
public void setWallet(Wallet wallet) {
|
||||
this.wallet = wallet;
|
||||
}
|
||||
|
@ -123,11 +123,11 @@ public class WorldManager {
|
|||
public Repository getRepository() {
|
||||
return repository;
|
||||
}
|
||||
|
||||
|
||||
public Blockchain getBlockchain() {
|
||||
return blockchain;
|
||||
}
|
||||
|
||||
|
||||
public Wallet getWallet() {
|
||||
return wallet;
|
||||
}
|
||||
|
|
|
@ -14,18 +14,18 @@ import java.math.BigInteger;
|
|||
|
||||
/**
|
||||
* The Miner performs the proof-of-work needed for a valid block
|
||||
*
|
||||
*
|
||||
* The mining proof-of-work (PoW) exists as a cryptographically secure nonce
|
||||
* that proves beyond reasonable doubt that a particular amount of computation
|
||||
* has been expended in the determination of some token value n.
|
||||
* It is utilised to enforce the blockchain security by giving meaning
|
||||
* and credence to the notion of difficulty (and, by extension, total difficulty).
|
||||
*
|
||||
* However, since mining new blocks comes with an attached reward,
|
||||
* the proof-of-work not only functions as a method of securing confidence
|
||||
* that the blockchain will remain canonical into the future, but also as
|
||||
* that proves beyond reasonable doubt that a particular amount of computation
|
||||
* has been expended in the determination of some token value n.
|
||||
* It is utilised to enforce the blockchain security by giving meaning
|
||||
* and credence to the notion of difficulty (and, by extension, total difficulty).
|
||||
*
|
||||
* However, since mining new blocks comes with an attached reward,
|
||||
* the proof-of-work not only functions as a method of securing confidence
|
||||
* that the blockchain will remain canonical into the future, but also as
|
||||
* a wealth distribution mechanism.
|
||||
*
|
||||
*
|
||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf (chapter 11.5 Mining Proof-of-Work)
|
||||
*/
|
||||
public class Miner {
|
||||
|
@ -36,13 +36,13 @@ public class Miner {
|
|||
|
||||
/**
|
||||
* 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 header’s SHA3 hash to be
|
||||
*
|
||||
* 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 header’s SHA3 hash to be
|
||||
* sufficiently low. It is formally defined as PoW:
|
||||
*
|
||||
*
|
||||
* PoW(H, n) ≡ BE(SHA3(SHA3(RLP(H!n)) ◦ n))
|
||||
*
|
||||
* where:
|
||||
|
@ -54,7 +54,7 @@ public class Miner {
|
|||
* 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
|
||||
|
@ -76,7 +76,7 @@ public class Miner {
|
|||
|
||||
byte[] testNonce = new byte[32];
|
||||
byte[] concat;
|
||||
|
||||
|
||||
while(ByteUtil.increment(testNonce) && !stop) {
|
||||
|
||||
if (testNonce[31] == 0 && testNonce[30] == 0){
|
||||
|
|
|
@ -18,8 +18,8 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
* The processing queue for blocks to be validated and added to the blockchain.
|
||||
* This class also maintains the list of hashes from the peer with the heaviest sub-tree.
|
||||
* Based on these hashes, blocks are added to the queue.
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 27/07/2014 11:28
|
||||
*/
|
||||
@Component
|
||||
|
@ -27,13 +27,13 @@ public class BlockQueue {
|
|||
|
||||
private static final Logger logger = LoggerFactory.getLogger("blockqueue");
|
||||
|
||||
/** The list of hashes of 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;
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class BlockQueue {
|
|||
private void nudgeQueue() {
|
||||
if (blockReceivedQueue.isEmpty())
|
||||
return;
|
||||
|
||||
|
||||
logger.info("BlockQueue size: {}", blockReceivedQueue.size());
|
||||
while(!blockReceivedQueue.isEmpty()){
|
||||
Block block = blockReceivedQueue.poll();
|
||||
|
@ -74,10 +74,10 @@ public class BlockQueue {
|
|||
* 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) {
|
||||
|
@ -104,13 +104,13 @@ public class BlockQueue {
|
|||
blockReceivedQueue.size(),
|
||||
lastBlock.getNumber());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the last block in the queue. If the queue is empty,
|
||||
* 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
|
||||
* and will never return <code>null</code> as there is
|
||||
* always the Genesis block at the start of the chain.
|
||||
*/
|
||||
public Block getLastBlock() {
|
||||
|
@ -122,7 +122,7 @@ public class BlockQueue {
|
|||
/**
|
||||
* 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) {
|
||||
|
@ -131,9 +131,9 @@ public class BlockQueue {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the last added hash to the queue representing
|
||||
* 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() {
|
||||
|
@ -158,10 +158,10 @@ 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() {
|
||||
|
@ -195,7 +195,7 @@ public class BlockQueue {
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public BigInteger getHighestTotalDifficulty() {
|
||||
return highestTotalDifficulty;
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ public class BlockQueue {
|
|||
|
||||
/**
|
||||
* Returns the current number of blocks in the queue
|
||||
*
|
||||
*
|
||||
* @return the current number of blocks in the queue
|
||||
*/
|
||||
public int size() {
|
||||
|
@ -223,7 +223,7 @@ public class BlockQueue {
|
|||
}
|
||||
|
||||
/**
|
||||
* Cancel and purge the timer-thread that
|
||||
* Cancel and purge the timer-thread that
|
||||
* processes the blocks in the queue
|
||||
*/
|
||||
public void close() {
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.ethereum.net.message.Message;
|
|||
* been offered This class also contains the last time a message was offered and
|
||||
* is updated when an answer has been received to it can be removed from the
|
||||
* queue.
|
||||
*
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
*/
|
||||
public class MessageRoundtrip {
|
||||
|
|
|
@ -8,7 +8,7 @@ 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;
|
||||
|
||||
|
@ -16,7 +16,7 @@ public class Capability implements Comparable<Capability> {
|
|||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class Capability implements Comparable<Capability> {
|
|||
public byte getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
|
@ -41,7 +41,7 @@ public class Capability implements Comparable<Capability> {
|
|||
public int compareTo(Capability o) {
|
||||
return this.name.compareTo(o.name);
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return name + ":" + version;
|
||||
}
|
||||
|
|
|
@ -50,12 +50,12 @@ public class PeerClient {
|
|||
Bootstrap b = new Bootstrap();
|
||||
b.group(workerGroup);
|
||||
b.channel(NioSocketChannel.class);
|
||||
|
||||
|
||||
b.option(ChannelOption.SO_KEEPALIVE, true);
|
||||
b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT);
|
||||
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONFIG.peerConnectionTimeout());
|
||||
b.remoteAddress(host, port);
|
||||
|
||||
|
||||
b.handler(ethereumChannelInitializer);
|
||||
|
||||
// Start the client.
|
||||
|
|
|
@ -76,7 +76,7 @@ public class BlockHashesMessage extends EthMessage {
|
|||
@Override
|
||||
public String toString() {
|
||||
if (!parsed) parse();
|
||||
|
||||
|
||||
StringBuffer sb = Utils.getHashlistShort(this.blockHashes);
|
||||
return "[" + this.getCommand().name() + sb.toString() + "] (" + this.blockHashes.size() + ")";
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import org.ethereum.net.eth.EthMessageCodes;
|
|||
import org.ethereum.net.message.Message;
|
||||
|
||||
public abstract class EthMessage extends Message {
|
||||
|
||||
|
||||
public EthMessage() {}
|
||||
|
||||
public EthMessage(byte[] encoded) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.Map;
|
|||
* A list of commands for the Ethereum network protocol.
|
||||
* <br>
|
||||
* The codes for these commands are the first byte in every packet.
|
||||
*
|
||||
*
|
||||
* @see <a href="https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol">
|
||||
* https://github.com/ethereum/wiki/wiki/Ethereum-Wire-Protocol</a>
|
||||
*/
|
||||
|
@ -56,8 +56,8 @@ public enum EthMessageCodes {
|
|||
|
||||
/**
|
||||
* [+0x07 [blockHeader, transactionList, uncleList], totalDifficulty] <br>
|
||||
* Specify a single block that the peer should know about. The composite item
|
||||
* in the list (following the message ID) is a block in the format described
|
||||
* Specify a single block that the peer should know about. The composite item
|
||||
* in the list (following the message ID) is a block in the format described
|
||||
* in the main Ethereum specification. */
|
||||
NEW_BLOCK(0x07),
|
||||
|
||||
|
|
|
@ -9,15 +9,15 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum GetBlockHashes message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.eth.EthMessageCodes#GET_BLOCK_HASHES
|
||||
*/
|
||||
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.
|
||||
|
||||
/** The maximum number of blocks to return.
|
||||
* <b>Note:</b> the peer could return fewer. */
|
||||
private int maxBlocks;
|
||||
|
||||
|
@ -80,8 +80,8 @@ public class GetBlockHashesMessage extends EthMessage {
|
|||
@Override
|
||||
public String toString() {
|
||||
if (!parsed) parse();
|
||||
return "[" + this.getCommand().name() +
|
||||
" bestHash=" + Hex.toHexString(bestHash) +
|
||||
return "[" + this.getCommand().name() +
|
||||
" bestHash=" + Hex.toHexString(bestHash) +
|
||||
" maxBlocks=" + maxBlocks + "]";
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ import static org.ethereum.net.eth.EthMessageCodes.GET_BLOCKS;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum GetBlocks message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.eth.EthMessageCodes#GET_BLOCKS
|
||||
*/
|
||||
public class GetBlocksMessage extends EthMessage {
|
||||
|
|
|
@ -6,12 +6,12 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum GetTransactions message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.eth.EthMessageCodes#GET_TRANSACTIONS
|
||||
*/
|
||||
public class GetTransactionsMessage extends EthMessage {
|
||||
|
||||
/** GetTransactions message is always a the same single command payload */
|
||||
/** GetTransactions message is always a the same single command payload */
|
||||
private final static byte[] FIXED_PAYLOAD = Hex.decode("C116");
|
||||
|
||||
public byte[] getEncoded() {
|
||||
|
|
|
@ -7,7 +7,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum Blocks message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.eth.EthMessageCodes#NEW_BLOCK
|
||||
*/
|
||||
public class NewBlockMessage extends EthMessage {
|
||||
|
@ -48,7 +48,7 @@ public class NewBlockMessage extends EthMessage {
|
|||
if (!parsed) parse();
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getDifficulty(){
|
||||
if (!parsed) parse();
|
||||
return difficulty;
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.spongycastle.util.encoders.Hex;
|
|||
import static org.ethereum.net.eth.EthMessageCodes.STATUS;
|
||||
|
||||
/**
|
||||
* Wrapper around an Ethereum Status message on the network
|
||||
*
|
||||
* Wrapper around an Ethereum Status message on the network
|
||||
*
|
||||
* @see org.ethereum.net.eth.EthMessageCodes#STATUS
|
||||
*/
|
||||
public class StatusMessage extends EthMessage {
|
||||
|
|
|
@ -13,12 +13,12 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Wrapper around an Ethereum Transactions message on the network
|
||||
*
|
||||
* Wrapper around an Ethereum Transactions message on the network
|
||||
*
|
||||
* @see org.ethereum.net.eth.EthMessageCodes#TRANSACTIONS
|
||||
*/
|
||||
public class TransactionsMessage extends EthMessage {
|
||||
|
||||
|
||||
private Set<Transaction> transactions;
|
||||
|
||||
public TransactionsMessage(byte[] encoded) {
|
||||
|
@ -36,7 +36,7 @@ public class TransactionsMessage extends EthMessage {
|
|||
this.transactions = transactionList;
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
|
||||
private void parse() {
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class TransactionsMessage extends EthMessage {
|
|||
}
|
||||
parsed = true;
|
||||
}
|
||||
|
||||
|
||||
private void encode() {
|
||||
List<byte[]> encodedElements = new ArrayList<>();
|
||||
encodedElements.add(RLP.encodeByte(TRANSACTIONS.asByte()));
|
||||
|
@ -58,7 +58,7 @@ public class TransactionsMessage extends EthMessage {
|
|||
.toArray(new byte[encodedElements.size()][]);
|
||||
this.encoded = RLP.encodeList(encodedElementArray);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
if (encoded == null) encode();
|
||||
|
@ -80,7 +80,7 @@ public class TransactionsMessage extends EthMessage {
|
|||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
if(!parsed) parse();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
|
|
|
@ -2,7 +2,7 @@ package org.ethereum.net.message;
|
|||
|
||||
/**
|
||||
* Abstract message class for all messages on the Ethereum network
|
||||
*
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 06/04/14 14:58
|
||||
*/
|
||||
|
@ -18,19 +18,19 @@ public abstract class Message {
|
|||
this.encoded = encoded;
|
||||
parsed = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the RLP encoded byte array of this 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();
|
||||
|
|
|
@ -4,61 +4,61 @@ import java.util.HashMap;
|
|||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Reason is an optional integer specifying one
|
||||
* of a number of reasons for disconnect
|
||||
* Reason is an optional integer specifying one
|
||||
* of a number of reasons for disconnect
|
||||
*/
|
||||
public enum ReasonCode {
|
||||
|
||||
/** [0x00] Disconnect request by other peer */
|
||||
REQUESTED(0x00),
|
||||
|
||||
|
||||
/** [0x01] */
|
||||
TCP_ERROR(0x01),
|
||||
|
||||
|
||||
/** [0x02] Packets can not be parsed */
|
||||
BAD_PROTOCOL(0x02),
|
||||
|
||||
|
||||
/** [0x03] This peer is too slow or delivers unreliable data */
|
||||
USELESS_PEER(0x03),
|
||||
|
||||
|
||||
/** [0x04] Already too many connections with other peers */
|
||||
TOO_MANY_PEERS(0x04),
|
||||
|
||||
|
||||
/** [0x05] Already have a running connection with this peer */
|
||||
ALREADY_CONNECTED(0x05),
|
||||
|
||||
|
||||
/** [0x06] Version of the p2p protocol is not the same as ours */
|
||||
INCOMPATIBLE_PROTOCOL(0x06),
|
||||
|
||||
|
||||
/** [0x07] Peer identifies itself with the wrong networkId */
|
||||
INCOMPATIBLE_NETWORK(0x07),
|
||||
|
||||
|
||||
/** [0x08] Peer quit voluntarily */
|
||||
PEER_QUITING(0x08),
|
||||
|
||||
|
||||
/** [0xFF] Reason not specified */
|
||||
UNKNOWN(0xFF);
|
||||
|
||||
private int reason;
|
||||
|
||||
|
||||
private static final Map<Integer, ReasonCode> intToTypeMap = new HashMap<>();
|
||||
static {
|
||||
for (ReasonCode type : ReasonCode.values()) {
|
||||
intToTypeMap.put(type.reason, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ReasonCode(int reason) {
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
|
||||
public static ReasonCode fromInt(int i) {
|
||||
ReasonCode type = intToTypeMap.get(Integer.valueOf(i));
|
||||
if (type == null)
|
||||
if (type == null)
|
||||
return ReasonCode.UNKNOWN;
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
public byte asByte() {
|
||||
return (byte) reason;
|
||||
}
|
||||
|
|
|
@ -19,14 +19,14 @@ import org.spongycastle.util.encoders.Hex;
|
|||
/**
|
||||
* This class contains static values of messages on the network. These message
|
||||
* will always be the same and therefore don't need to be created each time.
|
||||
*
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 13/04/14 20:19
|
||||
*/
|
||||
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();
|
||||
|
@ -43,7 +43,7 @@ public class StaticMessages {
|
|||
new Capability(Capability.SHH, ShhHandler.VERSION));
|
||||
int listenPort = SystemProperties.CONFIG.listenPort();
|
||||
|
||||
return new HelloMessage(p2pVersion, helloAnnouncement,
|
||||
return new HelloMessage(p2pVersion, helloAnnouncement,
|
||||
capabilities, listenPort, PEER_ID);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum GetPeers message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.p2p.P2pMessageCodes#GET_PEERS
|
||||
*/
|
||||
public class GetPeersMessage extends P2pMessage {
|
||||
|
|
|
@ -15,7 +15,7 @@ import java.util.List;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum HelloMessage on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.p2p.P2pMessageCodes#HELLO
|
||||
*/
|
||||
public class HelloMessage extends P2pMessage {
|
||||
|
@ -24,7 +24,7 @@ public class HelloMessage extends P2pMessage {
|
|||
private byte p2pVersion;
|
||||
/** The underlying client. A user-readable string. */
|
||||
private String clientId;
|
||||
/** A peer-network capability code, readable ASCII and 3 letters.
|
||||
/** 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 */
|
||||
|
@ -64,10 +64,10 @@ public class HelloMessage extends P2pMessage {
|
|||
|
||||
RLPElement capId = ((RLPList)capabilityList.get(i)).get(0);
|
||||
RLPElement capVersion = ((RLPList)capabilityList.get(i)).get(1);
|
||||
|
||||
|
||||
String name = new String(capId.getRLPData());
|
||||
byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0];
|
||||
|
||||
|
||||
Capability cap = new Capability(name, version);
|
||||
this.capabilities.add(cap);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import org.springframework.stereotype.Component;
|
|||
|
||||
/**
|
||||
* Process the basic protocol messages between every peer on the network.
|
||||
*
|
||||
*
|
||||
* Peers can send/receive
|
||||
* <ul>
|
||||
* <li>HELLO : Announce themselves to the network</li>
|
||||
|
@ -48,7 +48,7 @@ import org.springframework.stereotype.Component;
|
|||
public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
||||
|
||||
public final static byte VERSION = 2;
|
||||
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger("net");
|
||||
|
||||
private final Timer timer = new Timer("MessageTimer");
|
||||
|
@ -69,7 +69,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
|||
|
||||
this.peerDiscoveryMode = false;
|
||||
}
|
||||
|
||||
|
||||
public P2pHandler(MessageQueue msgQueue, boolean peerDiscoveryMode) {
|
||||
this.msgQueue = msgQueue;
|
||||
this.peerDiscoveryMode = peerDiscoveryMode;
|
||||
|
@ -167,7 +167,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
|||
ctx.close();
|
||||
killTimers();
|
||||
}
|
||||
|
||||
|
||||
private void processPeers(ChannelHandlerContext ctx, PeersMessage peersMessage) {
|
||||
worldManager.getPeerDiscovery().addPeers(peersMessage.getPeers());
|
||||
}
|
||||
|
@ -264,7 +264,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
|||
if (capability.getName().equals(Capability.ETH)) {
|
||||
EthMessageCodes.setOffset(offset);
|
||||
offset += EthMessageCodes.values().length;
|
||||
}
|
||||
}
|
||||
|
||||
if (capability.getName().equals(Capability.SHH)) {
|
||||
ShhMessageCodes.setOffset(offset);
|
||||
|
@ -295,7 +295,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
|||
}, 500, 25000);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
public void killTimers(){
|
||||
timer.cancel();
|
||||
timer.purge();
|
||||
|
|
|
@ -57,7 +57,7 @@ public class Peer {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[ip=" + getAddress().getHostAddress() +
|
||||
return "[ip=" + getAddress().getHostAddress() +
|
||||
" port=" + getPort()
|
||||
+ " peerId=" + getPeerId() + "]";
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum Peers message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.p2p.P2pMessageCodes#PEERS
|
||||
*/
|
||||
public class PeersMessage extends P2pMessage {
|
||||
|
|
|
@ -4,7 +4,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum Ping message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.p2p.P2pMessageCodes#PING
|
||||
*/
|
||||
public class PingMessage extends P2pMessage {
|
||||
|
|
|
@ -5,7 +5,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
/**
|
||||
* Wrapper around an Ethereum Pong message on the network
|
||||
*
|
||||
*
|
||||
* @see org.ethereum.net.p2p.P2pMessageCodes#PONG
|
||||
*/
|
||||
public class PongMessage extends P2pMessage {
|
||||
|
|
|
@ -72,7 +72,7 @@ public class DiscoveryChannel {
|
|||
Bootstrap b = new Bootstrap();
|
||||
b.group(workerGroup);
|
||||
b.channel(NioSocketChannel.class);
|
||||
|
||||
|
||||
b.option(ChannelOption.SO_KEEPALIVE, true);
|
||||
b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT);
|
||||
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONFIG.peerConnectionTimeout());
|
||||
|
|
|
@ -25,7 +25,7 @@ public class 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;
|
||||
|
@ -77,11 +77,11 @@ public class PeerDiscovery {
|
|||
public boolean isStarted() {
|
||||
return started.get();
|
||||
}
|
||||
|
||||
|
||||
public Set<PeerInfo> getPeers() {
|
||||
return peers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update list of known peers with new peers
|
||||
* This method checks for duplicate peer id's and addresses
|
||||
|
|
|
@ -9,8 +9,8 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||
/**
|
||||
* A handler to log rejected threads when execution is blocked because the
|
||||
* thread bounds and queue capacities are reached
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
*
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 22/05/2014 10:31
|
||||
*/
|
||||
public class RejectionLogger implements RejectedExecutionHandler {
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.springframework.stereotype.Component;
|
|||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 22/05/2014 09:26
|
||||
*/
|
||||
@Component
|
||||
|
|
|
@ -57,7 +57,7 @@ public class PeerServer {
|
|||
|
||||
b.group(bossGroup, workerGroup);
|
||||
b.channel(NioServerSocketChannel.class);
|
||||
|
||||
|
||||
b.option(ChannelOption.SO_KEEPALIVE, true);
|
||||
b.option(ChannelOption.MESSAGE_SIZE_ESTIMATOR, DefaultMessageSizeEstimator.DEFAULT);
|
||||
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONFIG.peerConnectionTimeout());
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.springframework.stereotype.Component;
|
|||
|
||||
/**
|
||||
* Process the messages between peers with 'shh' capability on the network.
|
||||
*
|
||||
*
|
||||
* Peers with 'shh' capability can send/receive:
|
||||
*
|
||||
*
|
||||
|
@ -63,7 +63,7 @@ public class ShhHandler extends SimpleChannelInboundHandler<ShhMessage> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
logger.error(cause.getCause().toString());
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.Map;
|
|||
* A list of commands for the Whisper network protocol.
|
||||
* <br>
|
||||
* The codes for these commands are the first byte in every packet.
|
||||
*
|
||||
*
|
||||
* @see <a href="https://github.com/ethereum/wiki/wiki/Wire-Protocol">
|
||||
* https://github.com/ethereum/wiki/wiki/Wire-Protocol</a>
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ public class MessageDecoder extends ByteToMessageDecoder {
|
|||
|
||||
byte[] encoded = new byte[in.readInt()];
|
||||
in.readBytes(encoded);
|
||||
|
||||
|
||||
if (loggerWire.isDebugEnabled())
|
||||
loggerWire.debug("Encoded: [{}]", Hex.toHexString(encoded));
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class MessageDecoder extends ByteToMessageDecoder {
|
|||
out.add(msg);
|
||||
in.markReaderIndex();
|
||||
}
|
||||
|
||||
|
||||
private boolean isValidEthereumPacket(ByteBuf in) {
|
||||
// Ethereum message is at least 8 bytes
|
||||
if (in.readableBytes() < 8)
|
||||
|
|
|
@ -39,10 +39,10 @@ public class MessageEncoder extends MessageToByteEncoder<Message> {
|
|||
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);
|
||||
out.writeBytes(StaticMessages.SYNC_TOKEN);
|
||||
out.writeBytes(ByteUtil.calcPacketLength(encoded));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -15,7 +15,7 @@ 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;
|
||||
|
@ -26,8 +26,8 @@ public class Cache {
|
|||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param o the Node which could be a pair-, multi-item Node or single Value
|
||||
* @return sha3 hash of RLP encoded node if length > 32 otherwise return node itself
|
||||
*/
|
||||
public Object put(Object o) {
|
||||
|
|
|
@ -3,40 +3,40 @@ package org.ethereum.trie;
|
|||
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)
|
||||
*
|
||||
* 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
|
||||
* a [ key, value ] node, where the key gives the hexadecimal path
|
||||
* to descend, in the compact encoding described above, and the value
|
||||
*
|
||||
* 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
|
||||
* a [ key, value ] node, where the key gives the hexadecimal path
|
||||
* 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
|
||||
* *
|
||||
* Also, we add another conceptual change: internal nodes can no longer
|
||||
* have values, only leaves with no children of their own can; however,
|
||||
* since to be fully generic we want the key/value store to be able to
|
||||
* store keys like 'dog' and 'doge' at the same time, we simply add
|
||||
* a terminator symbol (16) to the alphabet so there is never a value
|
||||
* "en-route" to another value.
|
||||
*
|
||||
* *
|
||||
* Also, we add another conceptual change: internal nodes can no longer
|
||||
* have values, only leaves with no children of their own can; however,
|
||||
* since to be fully generic we want the key/value store to be able to
|
||||
* store keys like 'dog' and 'doge' at the same time, we simply add
|
||||
* a terminator symbol (16) to the alphabet so there is never a value
|
||||
* "en-route" to another 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) >= 32 else x
|
||||
*
|
||||
* Note that when updating a trie, you will need to store the key/value pair (sha3(x), 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 >= 32,
|
||||
* but if the node is shorter than that then you do not need to store anything
|
||||
* but if the node is shorter than that then you do not need to store anything
|
||||
* when length < 32 for the obvious reason that the function f(x) = x is reversible.
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
|
@ -52,7 +52,7 @@ public class Node {
|
|||
public Node(Value val) {
|
||||
this(val, false);
|
||||
}
|
||||
|
||||
|
||||
public Node(Value val, boolean dirty) {
|
||||
this.value = val;
|
||||
this.dirty = dirty;
|
||||
|
@ -65,11 +65,11 @@ public class Node {
|
|||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
|
||||
public void setDirty(boolean ditry) {
|
||||
this.dirty = ditry;
|
||||
}
|
||||
|
||||
|
||||
public Value getValue() {
|
||||
return value;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package org.ethereum.trie;
|
||||
|
||||
/**
|
||||
* Trie interface for the main data structure in Ethereum
|
||||
* Trie interface for the main data structure in Ethereum
|
||||
* which is used to store both the account state and storage of each account.
|
||||
*/
|
||||
public interface Trie {
|
||||
|
||||
|
||||
/**
|
||||
* Gets a value from the trie for a given key
|
||||
*
|
||||
*
|
||||
* @param key - any length byte array
|
||||
* @return an rlp encoded byte array of the stored object
|
||||
*/
|
||||
|
@ -16,43 +16,43 @@ public interface Trie {
|
|||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
* Deletes a key/value from the trie for a given key
|
||||
*
|
||||
*
|
||||
* @param key - any length byte array
|
||||
*/
|
||||
public void delete(byte[] key);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a SHA-3 hash from the top node of the trie
|
||||
*
|
||||
* @return 32-byte SHA-3 hash representing the entire contents of the trie.
|
||||
*
|
||||
* @return 32-byte SHA-3 hash representing the entire contents of the trie.
|
||||
*/
|
||||
public byte[] getRootHash();
|
||||
|
||||
|
||||
/**
|
||||
* Set the top node of the trie
|
||||
*
|
||||
*
|
||||
* @param root - 32-byte SHA-3 hash of the root node
|
||||
*/
|
||||
public void setRoot(byte[] root);
|
||||
|
||||
|
||||
/**
|
||||
* Commit all the changes until now
|
||||
*/
|
||||
public void sync();
|
||||
|
||||
|
||||
/**
|
||||
* Discard all the changes until now
|
||||
*/
|
||||
public void undo();
|
||||
|
||||
|
||||
public String getTrieDump();
|
||||
|
||||
public boolean validate();
|
||||
|
|
|
@ -19,19 +19,19 @@ import org.slf4j.LoggerFactory;
|
|||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* The modified Merkle Patricia tree (trie) provides a persistent data structure
|
||||
* to map between arbitrary-length binary data (byte arrays). It is defined in terms of
|
||||
* a mutable data structure to map between 256-bit binary fragments and arbitrary-length
|
||||
* binary data, typically implemented as a database. The core of the trie, and its sole
|
||||
* requirement in terms of the protocol specification is to provide a single value that
|
||||
* identifies a given set of key-value pairs, which may either a 32 byte sequence or
|
||||
* the empty byte sequence. It is left as an implementation consideration to store and
|
||||
* maintain the structure of the trie in a manner the allows effective and efficient
|
||||
* The modified Merkle Patricia tree (trie) provides a persistent data structure
|
||||
* to map between arbitrary-length binary data (byte arrays). It is defined in terms of
|
||||
* a mutable data structure to map between 256-bit binary fragments and arbitrary-length
|
||||
* binary data, typically implemented as a database. The core of the trie, and its sole
|
||||
* requirement in terms of the protocol specification is to provide a single value that
|
||||
* identifies a given set of key-value pairs, which may either a 32 byte sequence or
|
||||
* the empty byte sequence. It is left as an implementation consideration to store and
|
||||
* maintain the structure of the trie in a manner the allows effective and efficient
|
||||
* realisation of the protocol.
|
||||
*
|
||||
* The trie implements a caching mechanism and will use cached values if they are present.
|
||||
* If a node is not present in the cache it will try to fetch it from the database and
|
||||
* store the cached value.
|
||||
* The trie implements a caching mechanism and will use cached values if they are present.
|
||||
* If a node is not present in the cache it will try to fetch it from the database and
|
||||
* store the cached value.
|
||||
*
|
||||
* <b>Note:</b> the data isn't persisted unless `sync` is explicitly called.
|
||||
*
|
||||
|
@ -63,7 +63,7 @@ public class TrieImpl implements Trie {
|
|||
public TrieIterator getIterator() {
|
||||
return new TrieIterator(this);
|
||||
}
|
||||
|
||||
|
||||
public void setCache(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
@ -101,14 +101,14 @@ public class TrieImpl implements Trie {
|
|||
|
||||
@Override
|
||||
public byte[] get(byte[] key) {
|
||||
if (logger.isDebugEnabled())
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Retrieving key {}", Hex.toHexString(key));
|
||||
byte[] k = binToNibbles(key);
|
||||
Value c = new Value(this.get(this.root, k));
|
||||
|
||||
return (c == null)? null : c.asBytes();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert key/value pair into trie
|
||||
*
|
||||
|
@ -140,7 +140,7 @@ public class TrieImpl implements Trie {
|
|||
public void delete(String key) {
|
||||
this.update(key.getBytes(), "".getBytes());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void delete(byte[] key) {
|
||||
delete(new String(key));
|
||||
|
@ -149,7 +149,7 @@ public class TrieImpl implements Trie {
|
|||
logger.debug("New root-hash: {}", Hex.toHexString(this.getRootHash()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] getRootHash() {
|
||||
if (root == null
|
||||
|
|
|
@ -11,7 +11,7 @@ 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;
|
||||
|
@ -73,9 +73,9 @@ public class TrieIterator {
|
|||
|
||||
public int purge() {
|
||||
List<byte[]> shas = this.collect();
|
||||
|
||||
|
||||
for (byte[] sha : shas) {
|
||||
this.trie.getCache().delete(sha);
|
||||
this.trie.getCache().delete(sha);
|
||||
}
|
||||
return this.values.size();
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ public class ByteUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* The regular {@link java.math.BigInteger#toByteArray()} method isn't quite what we often need:
|
||||
* The regular {@link java.math.BigInteger#toByteArray()} method isn't quite what we often need:
|
||||
* it appends a leading zero to indicate that the number is positive and may need padding.
|
||||
*
|
||||
* @param b the integer to format into a byte array
|
||||
|
@ -39,23 +39,23 @@ public class ByteUtil {
|
|||
int start = (biBytes.length == numBytes + 1) ? 1 : 0;
|
||||
int length = Math.min(biBytes.length, numBytes);
|
||||
System.arraycopy(biBytes, start, bytes, numBytes - length, length);
|
||||
return bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Omitting sign indication byte.
|
||||
* <br><br>
|
||||
* Instead of {@link org.spongycastle.util.BigIntegers#asUnsignedByteArray(BigInteger)}
|
||||
* Instead of {@link org.spongycastle.util.BigIntegers#asUnsignedByteArray(BigInteger)}
|
||||
* <br>we use this custom method to avoid an empty array in case of BigInteger.ZERO
|
||||
*
|
||||
* @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.
|
||||
* @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.
|
||||
*/
|
||||
public static byte[] bigIntegerToBytes(BigInteger value) {
|
||||
if (value == null)
|
||||
return null;
|
||||
|
||||
|
||||
byte[] data = value.toByteArray();
|
||||
|
||||
if (data.length != 1 && data[0] == 0) {
|
||||
|
@ -66,10 +66,10 @@ public class ByteUtil {
|
|||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Returns the amount of nibbles that match each other from 0 ...
|
||||
* amount will never be larger than smallest input
|
||||
*
|
||||
*
|
||||
* @param a - first input
|
||||
* @param b - second input
|
||||
* @return Number of bytes that match
|
||||
|
@ -84,22 +84,22 @@ public class ByteUtil {
|
|||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts a long value into a byte array.
|
||||
*
|
||||
*
|
||||
* @param val - long value to convert
|
||||
* @return <code>byte[]</code> of length 8, representing the long value
|
||||
*/
|
||||
public static byte[] longToBytes(long val) {
|
||||
return ByteBuffer.allocate(8).putLong(val).array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert a byte-array into a hex String.<br>
|
||||
* Works similar to {@link Hex#toHexString}
|
||||
* Works similar to {@link Hex#toHexString}
|
||||
* but allows for <code>null</code>
|
||||
*
|
||||
*
|
||||
* @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>
|
||||
|
@ -109,7 +109,7 @@ public class ByteUtil {
|
|||
public static String toHexString(byte[] data) {
|
||||
return data == null ? "" : Hex.toHexString(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calculate packet length
|
||||
* @param msg byte[]
|
||||
|
@ -124,14 +124,14 @@ public class ByteUtil {
|
|||
(byte)((msgLen ) & 0xFF)};
|
||||
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.
|
||||
* @return unsigned positive int value.
|
||||
*/
|
||||
public static int byteArrayToInt(byte[] b) {
|
||||
if (b == null || b.length == 0)
|
||||
|
@ -153,10 +153,10 @@ 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'
|
||||
*
|
||||
* @param nibbles - getting byte of data [ 04 ] and turning
|
||||
|
@ -171,7 +171,7 @@ public class ByteUtil {
|
|||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String oneByteToHexString(byte value) {
|
||||
String retVal = Integer.toString(value & 0xFF, 16);
|
||||
if (retVal.length() == 1) retVal = "0" + retVal;
|
||||
|
@ -197,7 +197,7 @@ public class ByteUtil {
|
|||
if (bytes == 0) ++bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param arg - not more that 32 bits
|
||||
* @return - bytes of the value pad with complete to 32 zeroes
|
||||
|
@ -215,7 +215,7 @@ public class ByteUtil {
|
|||
else
|
||||
data = arg.toString().trim().getBytes();
|
||||
|
||||
|
||||
|
||||
if (data.length > 32)
|
||||
throw new RuntimeException("values can't be more than 32 byte");
|
||||
|
||||
|
@ -304,9 +304,9 @@ public class ByteUtil {
|
|||
|
||||
/**
|
||||
* Utility function to copy a byte array into a new byte array with given size.
|
||||
* If the src length is smaller than the given size, the result will be left-padded
|
||||
* If the src length is smaller than the given size, the result will be left-padded
|
||||
* with zeros.
|
||||
*
|
||||
*
|
||||
* @param value - a BigInteger with a maximum value of 2^256-1
|
||||
* @return Byte array of given size with a copy of the <code>src</code>
|
||||
*/
|
||||
|
|
|
@ -12,29 +12,29 @@ import java.nio.ByteBuffer;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
/**
|
||||
* Compact encoding of hex sequence with optional terminator
|
||||
*
|
||||
* The traditional compact way of encoding a hex string is to convert it into binary
|
||||
* - that is, a string like 0f1248 would become three bytes 15, 18, 72. However,
|
||||
* this approach has one slight problem: what if the length of the hex string is odd?
|
||||
* In that case, there is no way to distinguish between, say, 0f1248 and f1248.
|
||||
*
|
||||
* Additionally, our application in the Merkle Patricia tree requires the additional feature
|
||||
* that a hex string can also have a special "terminator symbol" at the end (denoted by the 'T').
|
||||
* A terminator symbol can occur only once, and only at the end.
|
||||
*
|
||||
* An alternative way of thinking about this to not think of there being a terminator symbol,
|
||||
* but instead treat bit specifying the existence of the terminator symbol as a bit specifying
|
||||
*
|
||||
* The traditional compact way of encoding a hex string is to convert it into binary
|
||||
* - that is, a string like 0f1248 would become three bytes 15, 18, 72. However,
|
||||
* this approach has one slight problem: what if the length of the hex string is odd?
|
||||
* In that case, there is no way to distinguish between, say, 0f1248 and f1248.
|
||||
*
|
||||
* Additionally, our application in the Merkle Patricia tree requires the additional feature
|
||||
* that a hex string can also have a special "terminator symbol" at the end (denoted by the 'T').
|
||||
* A terminator symbol can occur only once, and only at the end.
|
||||
*
|
||||
* An alternative way of thinking about this to not think of there being a terminator symbol,
|
||||
* but instead treat bit specifying the existence of the terminator symbol as a bit specifying
|
||||
* that the given node encodes a final node, where the value is an actual value, rather than
|
||||
* the hash of yet another node.
|
||||
*
|
||||
* To solve both of these issues, we force the first nibble of the final byte-stream to encode
|
||||
* two flags, specifying oddness of length (ignoring the 'T' symbol) and terminator status;
|
||||
* these are placed, respectively, into the two lowest significant bits of the first nibble.
|
||||
*
|
||||
* To solve both of these issues, we force the first nibble of the final byte-stream to encode
|
||||
* two flags, specifying oddness of length (ignoring the 'T' symbol) and terminator status;
|
||||
* these are placed, respectively, into the two lowest significant bits of the first nibble.
|
||||
* In the case of an even-length hex string, we must introduce a second nibble (of value zero)
|
||||
* to ensure the hex-string is even in length and thus is representable by a whole number of bytes.
|
||||
*
|
||||
* to ensure the hex-string is even in length and thus is representable by a whole number of bytes.
|
||||
*
|
||||
* Examples:
|
||||
* > [ 1, 2, 3, 4, 5 ]
|
||||
* '\x11\x23\x45'
|
||||
|
@ -77,7 +77,7 @@ public class CompactEncoder {
|
|||
*/
|
||||
public static byte[] packNibbles(byte[] nibbles) {
|
||||
int terminator = 0;
|
||||
|
||||
|
||||
if (nibbles[nibbles.length-1] == TERMINATOR) {
|
||||
terminator = 1;
|
||||
nibbles = copyOf(nibbles, nibbles.length-1);
|
||||
|
@ -100,9 +100,9 @@ public class CompactEncoder {
|
|||
|
||||
/**
|
||||
* Unpack a binary string to its nibbles equivalent
|
||||
*
|
||||
*
|
||||
* @param str of binary data
|
||||
* @return array of nibbles in byte-format
|
||||
* @return array of nibbles in byte-format
|
||||
*/
|
||||
public static byte[] unpackToNibbles(byte[] str) {
|
||||
byte[] base = binToNibbles(str);
|
||||
|
@ -122,7 +122,7 @@ public class CompactEncoder {
|
|||
* Transforms a binary array to hexadecimal format + terminator
|
||||
*
|
||||
* @param str byte[]
|
||||
* @return array with each individual nibble adding a terminator at the end
|
||||
* @return array with each individual nibble adding a terminator at the end
|
||||
*/
|
||||
public static byte[] binToNibbles(byte[] str) {
|
||||
byte[] hexEncoded = encode(str);
|
||||
|
|
|
@ -9,23 +9,23 @@ 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;
|
||||
|
@ -37,7 +37,7 @@ public class DecodeResult implements Serializable {
|
|||
result += asString(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Not a valid type. Should not occur");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ public abstract class FastByteComparisons {
|
|||
private static class LexicographicalComparerHolder {
|
||||
static final String UNSAFE_COMPARER_NAME =
|
||||
LexicographicalComparerHolder.class.getName() + "$UnsafeComparer";
|
||||
|
||||
|
||||
static final Comparer<byte[]> BEST_COMPARER = getBestComparer();
|
||||
/**
|
||||
* Returns the Unsafe-using Comparer, or falls back to the pure-Java
|
||||
|
@ -91,7 +91,7 @@ public abstract class FastByteComparisons {
|
|||
return lexicographicalComparerJavaImpl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private enum PureJavaComparer implements Comparer<byte[]> {
|
||||
INSTANCE;
|
||||
|
||||
|
@ -116,7 +116,7 @@ public abstract class FastByteComparisons {
|
|||
return length1 - length2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused") // used via reflection
|
||||
private enum UnsafeComparer implements Comparer<byte[]> {
|
||||
INSTANCE;
|
||||
|
|
|
@ -10,7 +10,7 @@ public class LRUMap<K,V> extends ConcurrentHashMap<K,V> {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected final int maxEntries;
|
||||
|
||||
|
||||
public LRUMap(int initialEntries, int maxEntries) {
|
||||
super(initialEntries, 0.8f, 3);
|
||||
this.maxEntries = maxEntries;
|
||||
|
|
|
@ -19,8 +19,8 @@ import org.ethereum.util.RLPList;
|
|||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* Recursive Length Prefix (RLP) encoding.
|
||||
*
|
||||
* Recursive Length Prefix (RLP) encoding.
|
||||
*
|
||||
* The purpose of RLP is to encode arbitrarily nested arrays of binary data, and
|
||||
* RLP is the main encoding method used to serialize objects in Ethereum. The
|
||||
* only purpose of RLP is to encode structure; encoding specific atomic data
|
||||
|
@ -30,18 +30,18 @@ import org.spongycastle.util.encoders.Hex;
|
|||
* canonical forms are to either use [[k1,v1],[k2,v2]...] with keys in
|
||||
* lexicographic order or to use the higher-level Patricia Tree encoding as
|
||||
* Ethereum does.
|
||||
*
|
||||
*
|
||||
* The RLP encoding function takes in an item. An item is defined as follows:
|
||||
*
|
||||
*
|
||||
* - A string (ie. byte array) is an item - A list of items is an item
|
||||
*
|
||||
*
|
||||
* For example, an empty string is an item, as is the string containing the word
|
||||
* "cat", a list containing any number of strings, as well as more complex data
|
||||
* structures like ["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]. Note
|
||||
* that in the context of the rest of this article, "string" will be used as a
|
||||
* synonym for "a certain number of bytes of binary data"; no special encodings
|
||||
* are used and no knowledge about the content of the strings is implied.
|
||||
*
|
||||
*
|
||||
* See: https://github.com/ethereum/wiki/wiki/%5BEnglish%5D-RLP
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
|
@ -57,16 +57,16 @@ public class RLP {
|
|||
/**
|
||||
* Reason for threshold according to Vitalik Buterin:
|
||||
* - 56 bytes maximizes the benefit of both options
|
||||
* - if we went with 60 then we would have only had 4 slots for long strings
|
||||
* - if we went with 60 then we would have only had 4 slots for long strings
|
||||
* so RLP would not have been able to store objects above 4gb
|
||||
* - if we went with 48 then RLP would be fine for 2^128 space, but that's way too much
|
||||
* - so 56 and 2^64 space seems like the right place to put the cutoff
|
||||
* - also, that's where Bitcoin's varint does the cutof
|
||||
**/
|
||||
private static int SIZE_THRESHOLD = 56;
|
||||
|
||||
|
||||
/** RLP encoding rules are defined as follows: */
|
||||
|
||||
|
||||
/*
|
||||
* For a single byte whose value is in the [0x00, 0x7f] range, that byte is
|
||||
* its own RLP encoding.
|
||||
|
@ -110,12 +110,12 @@ public class RLP {
|
|||
* range of the first byte is thus [0xf8, 0xff].
|
||||
*/
|
||||
private static int OFFSET_LONG_LIST = 0xf7;
|
||||
|
||||
|
||||
|
||||
|
||||
/* ******************************************************
|
||||
* DECODING *
|
||||
* ******************************************************/
|
||||
|
||||
|
||||
private static byte decodeOneByteItem(byte[] data, int index) {
|
||||
// null item
|
||||
if ((data[index] & 0xFF) == OFFSET_SHORT_ITEM) {
|
||||
|
@ -183,7 +183,7 @@ public class RLP {
|
|||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
private static String decodeStringItem(byte[] data, int index) {
|
||||
|
||||
String value = null;
|
||||
|
@ -281,7 +281,7 @@ public class RLP {
|
|||
value = valueBytes;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
private static int nextItemLength(byte[] data, int index) {
|
||||
|
||||
if (index >= data.length)
|
||||
|
@ -517,7 +517,7 @@ public class RLP {
|
|||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
private static int calcLengthRaw(int lengthOfLength, byte[] msgData, int index) {
|
||||
byte pow = (byte) (lengthOfLength - 1);
|
||||
int length = 0;
|
||||
|
@ -527,7 +527,7 @@ public class RLP {
|
|||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
public static byte getCommandCode(byte[] data) {
|
||||
byte command = 0;
|
||||
int index = getFirstListElement(data, 0);
|
||||
|
@ -535,7 +535,7 @@ public class RLP {
|
|||
command = ((int) (command & 0xFF) == OFFSET_SHORT_ITEM) ? 0 : command;
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Parse wire byte[] message into RLP elements
|
||||
*
|
||||
|
@ -671,11 +671,11 @@ public class RLP {
|
|||
throw new RuntimeException("RLP wrong encoding", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reads any RLP encoded byte-array and returns all objects as byte-array or list of byte-arrays
|
||||
*
|
||||
* @param data RLP encoded byte-array
|
||||
*
|
||||
* @param data RLP encoded byte-array
|
||||
* @param pos position in the array to start reading
|
||||
* @return DecodeResult encapsulates the decoded items as a single Object and the final read position
|
||||
*/
|
||||
|
@ -709,7 +709,7 @@ public class RLP {
|
|||
throw new RuntimeException("Only byte values between 0x00 and 0xFF are supported, but got: " + prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static DecodeResult decodeList(byte[] data, int pos, int prevPos, int len) {
|
||||
List<Object> slice = new ArrayList<>();
|
||||
for (int i = 0; i < len;) {
|
||||
|
@ -723,17 +723,17 @@ public class RLP {
|
|||
}
|
||||
return new DecodeResult(pos, slice.toArray());
|
||||
}
|
||||
|
||||
|
||||
/* ******************************************************
|
||||
* ENCODING *
|
||||
* ******************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Turn Object into its RLP encoded equivalent of a byte-array
|
||||
* Support for String, Integer, BigInteger and Lists of any of these types.
|
||||
*
|
||||
*
|
||||
* @param input as object or List of objects
|
||||
* @return byte[] RLP encoded
|
||||
* @return byte[] RLP encoded
|
||||
*/
|
||||
public static byte[] encode(Object input) {
|
||||
Value val = new Value(input);
|
||||
|
@ -749,16 +749,16 @@ public class RLP {
|
|||
byte[] prefix = encodeLength(output.length, OFFSET_SHORT_LIST);
|
||||
return concatenate(prefix, output);
|
||||
} else {
|
||||
byte[] inputAsBytes = toBytes(input);
|
||||
byte[] inputAsBytes = toBytes(input);
|
||||
if (inputAsBytes.length == 1) {
|
||||
return inputAsBytes;
|
||||
} else {
|
||||
byte[] firstByte = encodeLength(inputAsBytes.length, OFFSET_SHORT_ITEM);
|
||||
byte[] firstByte = encodeLength(inputAsBytes.length, OFFSET_SHORT_ITEM);
|
||||
return concatenate(firstByte, inputAsBytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Integer limitation goes up to 2^31-1 so length can never be bigger than MAX_ITEM_LENGTH */
|
||||
public static byte[] encodeLength(int length, int offset) {
|
||||
if (length < SIZE_THRESHOLD) {
|
||||
|
@ -796,7 +796,7 @@ public class RLP {
|
|||
(byte) (singleShort >> 0 & 0xFF) };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static byte[] encodeInt(int singleInt) {
|
||||
if (singleInt <= 0xFF)
|
||||
return encodeByte((byte) singleInt);
|
||||
|
@ -821,9 +821,9 @@ public class RLP {
|
|||
}
|
||||
|
||||
public static byte[] encodeBigInteger(BigInteger srcBigInteger) {
|
||||
if(srcBigInteger == BigInteger.ZERO)
|
||||
if(srcBigInteger == BigInteger.ZERO)
|
||||
return encodeByte((byte)0);
|
||||
else
|
||||
else
|
||||
return encodeElement(asUnsignedByteArray(srcBigInteger));
|
||||
}
|
||||
|
||||
|
@ -910,9 +910,9 @@ public class RLP {
|
|||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Utility function to convert Objects into byte arrays
|
||||
* Utility function to convert Objects into byte arrays
|
||||
*/
|
||||
private static byte[] toBytes(Object input) {
|
||||
if (input instanceof byte[]) {
|
||||
|
@ -921,10 +921,10 @@ public class RLP {
|
|||
String inputString = (String) input;
|
||||
return inputString.getBytes();
|
||||
} else if(input instanceof Long) {
|
||||
Long inputLong = (Long) input;
|
||||
Long inputLong = (Long) input;
|
||||
return (inputLong == 0) ? ByteUtil.EMPTY_BYTE_ARRAY : asUnsignedByteArray(BigInteger.valueOf(inputLong));
|
||||
} else if(input instanceof Integer) {
|
||||
Integer inputInt = (Integer) input;
|
||||
Integer inputInt = (Integer) input;
|
||||
return (inputInt == 0) ? ByteUtil.EMPTY_BYTE_ARRAY : asUnsignedByteArray(BigInteger.valueOf(inputInt.intValue()));
|
||||
} else if(input instanceof BigInteger) {
|
||||
BigInteger inputBigInt = (BigInteger) input;
|
||||
|
|
|
@ -2,18 +2,18 @@ package org.ethereum.util;
|
|||
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 21/04/14 16:26
|
||||
*/
|
||||
public class RLPItem implements RLPElement {
|
||||
|
||||
byte[] rlpData;
|
||||
|
||||
|
||||
public RLPItem(byte[] rlpData) {
|
||||
this.rlpData = rlpData;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getRLPData() {
|
||||
if (rlpData.length == 0)
|
||||
return null;
|
||||
|
|
|
@ -26,7 +26,7 @@ public class RLPList extends ArrayList<RLPElement> implements RLPElement {
|
|||
if (element instanceof RLPList) {
|
||||
|
||||
RLPList rlpList = (RLPList) element;
|
||||
System.out.print("[");
|
||||
System.out.print("[");
|
||||
for (RLPElement singleElement : rlpList) {
|
||||
recursivePrint(singleElement);
|
||||
}
|
||||
|
|
|
@ -29,11 +29,11 @@ public class Utils {
|
|||
byte[] numberBytes = Hex.decode(hexNum.substring(2));
|
||||
return (new BigInteger(1, numberBytes)).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Return formatted Date String: yyyy.MM.dd HH:mm:ss
|
||||
* Based on Unix's time() input in seconds
|
||||
*
|
||||
*
|
||||
* @param timestamp seconds since start of Unix-time
|
||||
* @return String formatted as - yyyy.MM.dd HH:mm:ss
|
||||
*/
|
||||
|
@ -42,7 +42,7 @@ public class Utils {
|
|||
DateFormat formatter = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
|
||||
return formatter.format(date);
|
||||
}
|
||||
|
||||
|
||||
public static ImageIcon getImageIcon(String resource) {
|
||||
URL imageURL = ClassLoader.getSystemResource(resource);
|
||||
ImageIcon image = new ImageIcon(imageURL);
|
||||
|
@ -59,10 +59,10 @@ public class Utils {
|
|||
}
|
||||
return result.toString() + "·(" + "10^" + pow + ")";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes a hex string to address bytes and checks validity
|
||||
*
|
||||
* Decodes a hex string to address bytes and checks validity
|
||||
*
|
||||
* @param hex - a hex string of the address, e.g., 6c386a4b26f73c802f34673f7248bb118f97424a
|
||||
* @return - decode and validated address byte[]
|
||||
*/
|
||||
|
@ -70,12 +70,12 @@ public class Utils {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ public class Value {
|
|||
this.value = obj;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* *****************
|
||||
* Convert
|
||||
* *****************/
|
||||
|
@ -102,7 +102,7 @@ public class Value {
|
|||
// If this wasn't a slice you probably shouldn't be using this function
|
||||
return new Value(null);
|
||||
}
|
||||
|
||||
|
||||
/* *****************
|
||||
* Utility
|
||||
* *****************/
|
||||
|
@ -114,7 +114,7 @@ public class Value {
|
|||
public boolean cmp(Value o) {
|
||||
return DeepEquals.deepEquals(this, o);
|
||||
}
|
||||
|
||||
|
||||
/* *****************
|
||||
* Checks
|
||||
* *****************/
|
||||
|
|
|
@ -50,7 +50,7 @@ public class DataWord implements Comparable<DataWord> {
|
|||
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);
|
||||
throw new RuntimeException("Data word can't exit 32 bytes: " + data);
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
|
@ -67,12 +67,12 @@ public class DataWord implements Comparable<DataWord> {
|
|||
public BigInteger value() {
|
||||
return new BigInteger(1, data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts this DataWord to an int, checking for lost information.
|
||||
* If this DataWord is out of the possible range for an int result
|
||||
* Converts this DataWord to an int, checking for lost information.
|
||||
* If this DataWord is out of the possible range for an int result
|
||||
* then an ArithmeticException is thrown.
|
||||
*
|
||||
*
|
||||
* @return this DataWord converted to an int.
|
||||
* @throws ArithmeticException - if this will not fit in an int.
|
||||
*/
|
||||
|
@ -82,12 +82,12 @@ public class DataWord implements Comparable<DataWord> {
|
|||
return Integer.MAX_VALUE;
|
||||
return tmpValue.intValueExact();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts this DataWord to a long, checking for lost information.
|
||||
* If this DataWord is out of the possible range for a long result
|
||||
* Converts this DataWord to a long, checking for lost information.
|
||||
* If this DataWord is out of the possible range for a long result
|
||||
* then an ArithmeticException is thrown.
|
||||
*
|
||||
*
|
||||
* @return this DataWord converted to a long.
|
||||
* @throws ArithmeticException - if this will not fit in a long.
|
||||
*/
|
||||
|
@ -153,7 +153,7 @@ public class DataWord implements Comparable<DataWord> {
|
|||
if (this.data[i] != 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void bnot() {
|
||||
if (this.isZero()) return;
|
||||
this.data = ByteUtil.copyToArray(MAX_VALUE.subtract(this.value()));
|
||||
|
@ -170,13 +170,13 @@ public class DataWord implements Comparable<DataWord> {
|
|||
}
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
// TODO: mul can be done in more efficient way
|
||||
// TODO: with shift left shift right trick
|
||||
// TODO without BigInteger quick hack
|
||||
|
@ -212,7 +212,7 @@ public class DataWord implements Comparable<DataWord> {
|
|||
|
||||
// TODO: improve with no BigInteger
|
||||
public void sub(DataWord word) {
|
||||
BigInteger result = value().subtract(word.value());
|
||||
BigInteger result = value().subtract(word.value());
|
||||
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
|
||||
}
|
||||
|
||||
|
@ -244,22 +244,22 @@ public class DataWord implements Comparable<DataWord> {
|
|||
BigInteger result = sValue().remainder(word.sValue());
|
||||
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
|
||||
}
|
||||
|
||||
|
||||
public void addmod(DataWord word1, DataWord word2) {
|
||||
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());
|
||||
this.data = ByteUtil.copyToArray(result.and(MAX_VALUE));
|
||||
}
|
||||
|
||||
|
||||
public String toString() {
|
||||
return Hex.toHexString(data);
|
||||
}
|
||||
|
||||
|
||||
public String shortHex() {
|
||||
String hexValue = Hex.toHexString(getNoLeadZeroesData()).toUpperCase();
|
||||
return "0x" + hexValue.replaceFirst("^0+(?!$)", "");
|
||||
|
@ -280,7 +280,7 @@ public class DataWord implements Comparable<DataWord> {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return java.util.Arrays.hashCode(data);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package org.ethereum.vm;
|
||||
|
||||
/**
|
||||
* The fundamental network cost unit. Paid for exclusively by Ether, which is converted
|
||||
* freely to and from Gas as required. Gas does not exist outside of the internal Ethereum
|
||||
* computation engine; its price is set by the Transaction and miners are free to
|
||||
* The fundamental network cost unit. Paid for exclusively by Ether, which is converted
|
||||
* freely to and from Gas as required. Gas does not exist outside of the internal Ethereum
|
||||
* computation engine; its price is set by the Transaction and miners are free to
|
||||
* ignore Transactions whose Gas price is too low.
|
||||
*/
|
||||
public class GasCost {
|
||||
|
|
|
@ -5,13 +5,13 @@ package org.ethereum.vm;
|
|||
* This can either be a normal CALL, STATELESS call or POST call.
|
||||
*/
|
||||
public class MessageCall {
|
||||
|
||||
public enum MsgType {
|
||||
CALL,
|
||||
STATELESS,
|
||||
|
||||
public enum MsgType {
|
||||
CALL,
|
||||
STATELESS,
|
||||
POST;
|
||||
}
|
||||
|
||||
|
||||
/** Type of internal call. Either CALL, STATELESS or POST */
|
||||
private MsgType type;
|
||||
|
||||
|
@ -39,7 +39,7 @@ public class MessageCall {
|
|||
this.inDataOffs = inDataOffs;
|
||||
this.inDataSize = inDataSize;
|
||||
}
|
||||
|
||||
|
||||
public MessageCall(MsgType type, DataWord gas, DataWord codeAddress,
|
||||
DataWord endowment, DataWord inDataOffs, DataWord inDataSize,
|
||||
DataWord outDataOffs, DataWord outDataSize) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import java.util.Map;
|
|||
|
||||
/**
|
||||
* Instruction set for the Ethereum Virtual Machine
|
||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf
|
||||
* See Yellow Paper: http://www.gavwood.com/Paper.pdf
|
||||
* - Appendix G. Virtual Machine Specification
|
||||
*/
|
||||
public enum OpCode {
|
||||
|
@ -29,10 +29,10 @@ public enum OpCode {
|
|||
MOD(0x06, 2),
|
||||
/** (0x07) Signed modulo remainder operation*/
|
||||
SMOD(0x07, 2),
|
||||
/** (0x08) Addition combined with modulo
|
||||
/** (0x08) Addition combined with modulo
|
||||
* remainder operation */
|
||||
ADDMOD(0x08, 3),
|
||||
/** (0x09) Multiplication combined with modulo
|
||||
/** (0x09) Multiplication combined with modulo
|
||||
* remainder operation */
|
||||
MULMOD(0x09, 3),
|
||||
/** (0x0a) Exponential operation */
|
||||
|
@ -72,7 +72,7 @@ public enum OpCode {
|
|||
|
||||
/* Environmental Information */
|
||||
|
||||
/** (0x30) Get address of currently
|
||||
/** (0x30) Get address of currently
|
||||
* executing account */
|
||||
ADDRESS(0x30, 0),
|
||||
/** (0x31) Get balance of the given account */
|
||||
|
@ -81,38 +81,38 @@ public enum OpCode {
|
|||
ORIGIN(0x32, 0),
|
||||
/** (0x33) Get caller address */
|
||||
CALLER(0x33, 0),
|
||||
/** (0x34) Get deposited value by the
|
||||
* instruction/transaction responsible
|
||||
/** (0x34) Get deposited value by the
|
||||
* instruction/transaction responsible
|
||||
* for this execution */
|
||||
CALLVALUE(0x34, 0),
|
||||
/** (0x35) Get input data of current
|
||||
/** (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
|
||||
/** (0x37) Copy input data in current
|
||||
* environment to memory */
|
||||
CALLDATACOPY(0x37, 3),
|
||||
/** (0x38) Get size of code running in
|
||||
/** (0x38) Get size of code running in
|
||||
* current environment */
|
||||
CODESIZE(0x38, 0),
|
||||
/** (0x39) Copy code running in current
|
||||
/** (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
|
||||
/** (0x3a) Get price of gas in current
|
||||
* environment */
|
||||
GASPRICE(0x3a, 0),
|
||||
/** (0x3b) Get size of code running in
|
||||
/** (0x3b) Get size of code running in
|
||||
* current environment with given offset */
|
||||
EXTCODESIZE(0x3b, 1),
|
||||
/** (0x3c) Copy code running in current
|
||||
/** (0x3c) Copy code running in current
|
||||
* environment to memory with given offset */
|
||||
EXTCODECOPY(0x3c, 4),
|
||||
|
||||
/* Block Information */
|
||||
|
||||
/** (0x40) Get hash of most recent
|
||||
/** (0x40) Get hash of most recent
|
||||
* complete block */
|
||||
PREVHASH(0x40, 0),
|
||||
/** (0x41) Get the block’s coinbase address */
|
||||
|
@ -142,7 +142,7 @@ public enum OpCode {
|
|||
SSTORE(0x55, 2),
|
||||
/** (0x56) Alter the program counter */
|
||||
JUMP(0x56, 1),
|
||||
/** (0x57) Conditionally alter the program
|
||||
/** (0x57) Conditionally alter the program
|
||||
* counter */
|
||||
JUMPI(0x57, 2),
|
||||
/** (0x58) Get the program counter */
|
||||
|
@ -218,7 +218,7 @@ public enum OpCode {
|
|||
PUSH30(0x7d, 0),
|
||||
/** (0x7e) Place 31-byte item on stack */
|
||||
PUSH31(0x7e, 0),
|
||||
/** (0x7f) Place 32-byte (full word)
|
||||
/** (0x7f) Place 32-byte (full word)
|
||||
* item on stack */
|
||||
PUSH32(0x7f, 0),
|
||||
|
||||
|
@ -316,7 +316,7 @@ public enum OpCode {
|
|||
|
||||
private byte opcode;
|
||||
private int require;
|
||||
|
||||
|
||||
private static final Map<Byte, OpCode> intToTypeMap = new HashMap<>();
|
||||
private static final Map<String, Byte> stringToByteMap = new HashMap<>();
|
||||
|
||||
|
@ -326,19 +326,19 @@ public enum OpCode {
|
|||
stringToByteMap.put(type.name(), type.opcode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private OpCode(int op, int require) {
|
||||
this.opcode = (byte) op;
|
||||
this.require = require;
|
||||
}
|
||||
|
||||
|
||||
public byte val() {
|
||||
return opcode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the mininum amount of items required on the stack for this operation
|
||||
*
|
||||
*
|
||||
* @return minimum amount of expected items on the stack
|
||||
*/
|
||||
public int require() {
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
@ -57,10 +57,10 @@ public class Program {
|
|||
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();
|
||||
|
@ -88,7 +88,7 @@ public class Program {
|
|||
public void setLastOp(byte op) {
|
||||
this.lastOp = op;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Should be set only after the OP is fully executed
|
||||
* @param op
|
||||
|
@ -96,7 +96,7 @@ public class Program {
|
|||
public void setPreviouslyExecutedOp(byte op) {
|
||||
this.previouslyExecutedOp = op;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* returns the last fully executed OP
|
||||
* @return
|
||||
|
@ -104,7 +104,7 @@ public class Program {
|
|||
public byte getPreviouslyExecutedOp() {
|
||||
return this.previouslyExecutedOp;
|
||||
}
|
||||
|
||||
|
||||
public void stackPush(byte[] data) {
|
||||
DataWord stackWord = new DataWord(data);
|
||||
stack.push(stackWord);
|
||||
|
@ -123,7 +123,7 @@ public class Program {
|
|||
public void stackPush(DataWord stackWord) {
|
||||
stack.push(stackWord);
|
||||
}
|
||||
|
||||
|
||||
public Stack<DataWord> getStack() {
|
||||
return this.stack;
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ public class Program {
|
|||
|
||||
public void setPC(int pc) {
|
||||
this.pc = pc;
|
||||
|
||||
|
||||
if (this.pc >= ops.length)
|
||||
stop();
|
||||
}
|
||||
|
@ -175,11 +175,11 @@ public class Program {
|
|||
public DataWord stackPop() {
|
||||
return stack.pop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that the stack is at least <code>stackSize</code>
|
||||
* @param stackSize int
|
||||
* @throws StackTooSmallException If the stack is
|
||||
* @throws StackTooSmallException If the stack is
|
||||
* smaller than <code>stackSize</code>
|
||||
*/
|
||||
public void stackRequire(int stackSize) {
|
||||
|
@ -203,7 +203,7 @@ public class Program {
|
|||
|
||||
/**
|
||||
* Allocates a piece of memory and stores value at given offset address
|
||||
*
|
||||
*
|
||||
* @param addr is the offset address
|
||||
* @param allocSize size of memory needed to write
|
||||
* @param value the data to write to memory
|
||||
|
@ -213,11 +213,11 @@ public class Program {
|
|||
allocateMemory(addr, allocSize);
|
||||
System.arraycopy(value, 0, memory.array(), addr, value.length);
|
||||
}
|
||||
|
||||
|
||||
public DataWord memoryLoad(DataWord addr) {
|
||||
return memoryLoad(addr.intValue());
|
||||
}
|
||||
|
||||
|
||||
public DataWord memoryLoad(int address) {
|
||||
|
||||
allocateMemory(address, DataWord.ZERO.getData().length);
|
||||
|
@ -255,14 +255,14 @@ public class Program {
|
|||
/**
|
||||
* Allocates extra memory in the program for
|
||||
* a specified size, calculated from a given offset
|
||||
*
|
||||
*
|
||||
* @param offset the memory address offset
|
||||
* @param size the number of bytes to allocate
|
||||
*/
|
||||
public void allocateMemory(int offset, int size) {
|
||||
|
||||
int memSize = memory != null ? memory.limit() : 0;
|
||||
double newMemSize = Math.max(memSize, size != 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)
|
||||
|
@ -295,7 +295,7 @@ public class Program {
|
|||
byte[] senderAddress = this.getOwnerAddress().getLast20Bytes();
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("creating a new contract inside contract run: [{}]", Hex.toHexString(senderAddress));
|
||||
|
||||
|
||||
// actual gas subtract
|
||||
DataWord gasLimit = this.getGas();
|
||||
this.spendGas(gasLimit.longValue(), "internal call");
|
||||
|
@ -332,9 +332,9 @@ public class Program {
|
|||
ProgramInvoke programInvoke = programInvokeFactory.createProgramInvoke(
|
||||
this, new DataWord(newAddress), DataWord.ZERO, gasLimit,
|
||||
newBalance, null, track);
|
||||
|
||||
|
||||
ProgramResult result = null;
|
||||
|
||||
|
||||
if (programCode != null && programCode.length != 0) {
|
||||
VM vm = new VM();
|
||||
Program program = new Program(programCode, programInvoke);
|
||||
|
@ -343,8 +343,8 @@ public class Program {
|
|||
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
||||
this.result.addLogInfos(result.getLogInfoList());
|
||||
}
|
||||
|
||||
if (result != null &&
|
||||
|
||||
if (result != null &&
|
||||
result.getException() != null &&
|
||||
result.getException() instanceof Program.OutOfGasException) {
|
||||
logger.debug("contract run halted by Exception: contract: [{}], exception: [{}]",
|
||||
|
@ -374,7 +374,7 @@ public class Program {
|
|||
|
||||
// IN SUCCESS PUSH THE ADDRESS INTO THE STACK
|
||||
stackPush(new DataWord(newAddress));
|
||||
|
||||
|
||||
// 5. REFUND THE REMAIN GAS
|
||||
|
||||
long refundGas = gasLimit.longValue() - result.getGasUsed();
|
||||
|
@ -390,14 +390,14 @@ public class Program {
|
|||
|
||||
/**
|
||||
* That method is for internal code invocations
|
||||
*
|
||||
*
|
||||
* - Normal calls invoke a specified contract which updates itself
|
||||
* - Stateless calls invoke code from another contract, within the context of the caller
|
||||
*
|
||||
* @param msg is the message call object
|
||||
*/
|
||||
public void callToAddress(MessageCall msg) {
|
||||
|
||||
|
||||
byte[] data = memoryChunk(msg.getInDataOffs(), msg.getInDataSize()).array();
|
||||
|
||||
// FETCH THE SAVED STORAGE
|
||||
|
@ -420,7 +420,7 @@ public class Program {
|
|||
Hex.toHexString(senderAddress), Hex.toHexString(codeAddress));
|
||||
throw new OutOfGasException();
|
||||
}
|
||||
|
||||
|
||||
BigInteger endowment = msg.getEndowment().value();
|
||||
BigInteger senderBalance = result.getRepository().getBalance(senderAddress);
|
||||
if (senderBalance.compareTo(endowment) < 0) {
|
||||
|
@ -429,22 +429,22 @@ public class Program {
|
|||
}
|
||||
result.getRepository().addBalance(senderAddress, endowment.negate());
|
||||
BigInteger contextBalance = result.getRepository().addBalance(contextAddress, endowment);
|
||||
|
||||
|
||||
if (invokeData.byTestingSuite()) {
|
||||
// This keeps track of the calls created for a test
|
||||
this.getResult().addCallCreate(data, contextAddress,
|
||||
msg.getGas().getNoLeadZeroesData(),
|
||||
msg.getGas().getNoLeadZeroesData(),
|
||||
msg.getEndowment().getNoLeadZeroesData());
|
||||
}
|
||||
|
||||
|
||||
// actual gas subtract
|
||||
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);
|
||||
|
||||
|
||||
ProgramResult result = null;
|
||||
|
||||
if (programCode != null && programCode.length != 0) {
|
||||
|
@ -456,7 +456,7 @@ public class Program {
|
|||
this.result.addDeleteAccounts(result.getDeleteAccounts());
|
||||
this.result.addLogInfos(result.getLogInfoList());
|
||||
}
|
||||
|
||||
|
||||
if (result != null &&
|
||||
result.getException() != null &&
|
||||
result.getException() instanceof Program.OutOfGasException) {
|
||||
|
@ -483,11 +483,11 @@ public class Program {
|
|||
this.memorySave(offset, allocSize, buffer.array());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 4. THE FLAG OF SUCCESS IS ONE PUSHED INTO THE STACK
|
||||
trackRepository.commit();
|
||||
stackPushOne();
|
||||
|
||||
|
||||
// 5. REFUND THE REMAIN GAS
|
||||
if (result != null) {
|
||||
BigInteger refundGas = msg.getGas().value().subtract(BigInteger.valueOf(result.getGasUsed()));
|
||||
|
@ -511,7 +511,7 @@ public class Program {
|
|||
throw new OutOfGasException();
|
||||
result.spendGas(gasValue);
|
||||
}
|
||||
|
||||
|
||||
public void spendAllGas() {
|
||||
spendGas(invokeData.getGas().longValue() - result.getGasUsed(), "Spending all remaining");
|
||||
}
|
||||
|
@ -534,11 +534,11 @@ public class Program {
|
|||
DataWord valWord = new DataWord(val);
|
||||
result.getRepository().addStorageRow(this.programAddress.getLast20Bytes(), keyWord, valWord);
|
||||
}
|
||||
|
||||
|
||||
public byte[] getCode() {
|
||||
return ops;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getCodeAt(DataWord address) {
|
||||
|
||||
byte[] code = invokeData.getRepository().getCode(address.getLast20Bytes());
|
||||
|
@ -637,7 +637,7 @@ public class Program {
|
|||
public void setRuntimeFailure(RuntimeException e) {
|
||||
result.setException(e);
|
||||
}
|
||||
|
||||
|
||||
public String memoryToString() {
|
||||
StringBuilder memoryData = new StringBuilder();
|
||||
StringBuilder firstLine = new StringBuilder();
|
||||
|
@ -645,7 +645,7 @@ public class Program {
|
|||
for (int i = 0; memory != null && i < memory.limit(); ++i) {
|
||||
|
||||
byte value = memory.get(i);
|
||||
// Check if value is ASCII
|
||||
// Check if value is ASCII
|
||||
String character = ((byte) 0x20 <= value && value <= (byte) 0x7e) ? new String(new byte[] { value }) : "?";
|
||||
firstLine.append(character).append("");
|
||||
secondLine.append(ByteUtil.oneByteToHexString(value)).append(" ");
|
||||
|
@ -820,29 +820,29 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -856,13 +856,13 @@ public class Program {
|
|||
|
||||
@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) {
|
||||
|
|
|
@ -28,14 +28,14 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
|
|||
@Autowired
|
||||
private Blockchain blockchain;
|
||||
|
||||
/**
|
||||
/**
|
||||
* This attribute defines the number of recursive calls allowed in the EVM
|
||||
* Note: For the JVM to reach this level without a StackOverflow exception,
|
||||
* ethereumj may need to be started with a JVM argument to increase
|
||||
* ethereumj may need to be started with a JVM argument to increase
|
||||
* the stack size. For example: -Xss10m
|
||||
*/
|
||||
private static final int MAX_DEPTH = 1024;
|
||||
|
||||
private static final int MAX_DEPTH = 1024;
|
||||
|
||||
// Invocation by the wire tx
|
||||
@Override
|
||||
public ProgramInvoke createProgramInvoke(Transaction tx, Block block, Repository repository) {
|
||||
|
@ -188,7 +188,7 @@ public class ProgramInvokeFactoryImpl implements ProgramInvokeFactory {
|
|||
Hex.toHexString(difficulty.getNoLeadZeroesData()),
|
||||
gasLimit.longValue());
|
||||
}
|
||||
|
||||
|
||||
if (program.invokeData.getCallDeep() >= MAX_DEPTH)
|
||||
throw program.new OutOfGasException();
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
|||
byte[] msgData;
|
||||
|
||||
/*** BLOCK env ***/
|
||||
private DataWord prevHash, coinbase, timestamp,
|
||||
private DataWord prevHash, coinbase, timestamp,
|
||||
number, difficulty, gaslimit;
|
||||
|
||||
Map<DataWord, DataWord> storage;
|
||||
|
@ -151,7 +151,7 @@ public class ProgramInvokeImpl implements ProgramInvoke {
|
|||
return new DataWord();
|
||||
if (index + size > msgData.length)
|
||||
size = msgData.length - index;
|
||||
|
||||
|
||||
byte[] data = new byte[32];
|
||||
System.arraycopy(msgData, index, data, 0, size);
|
||||
return new DataWord(data);
|
||||
|
|
|
@ -22,7 +22,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
|||
|
||||
// default for most tests. This can be overwritten by the test
|
||||
private long gasLimit = 1000000;
|
||||
|
||||
|
||||
public ProgramInvokeMockImpl(byte[] msgDataRaw) {
|
||||
this();
|
||||
this.msgData = msgDataRaw;
|
||||
|
@ -31,9 +31,9 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
|||
public ProgramInvokeMockImpl() {
|
||||
this.repository = new RepositoryImpl("detailsMoc", "stateMoc");
|
||||
this.repository.createAccount(ownerAddress);
|
||||
|
||||
|
||||
this.repository.createAccount(contractAddress);
|
||||
this.repository.saveCode(contractAddress,
|
||||
this.repository.saveCode(contractAddress,
|
||||
Hex.decode("385E60076000396000605f556014600054601e60"
|
||||
+ "205463abcddcba6040545b51602001600a525451"
|
||||
+ "6040016014525451606001601e52545160800160"
|
||||
|
@ -84,7 +84,7 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
|||
|
||||
/* GAS op */
|
||||
public DataWord getGas() {
|
||||
|
||||
|
||||
return new DataWord(gasLimit);
|
||||
}
|
||||
|
||||
|
@ -190,10 +190,10 @@ public class ProgramInvokeMockImpl implements ProgramInvoke {
|
|||
public DataWord getGaslimit() {
|
||||
return new DataWord(gasLimit);
|
||||
}
|
||||
|
||||
|
||||
public void setGasLimit(long gasLimit) {
|
||||
this.gasLimit = gasLimit;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOwnerAddress(byte[] ownerAddress) {
|
||||
this.ownerAddress = ownerAddress;
|
||||
|
|
|
@ -26,35 +26,35 @@ import static org.ethereum.vm.OpCode.PUSH1;
|
|||
/**
|
||||
* The Ethereum Virtual Machine (EVM) is responsible for initialization
|
||||
* and executing a transaction on a contract.
|
||||
*
|
||||
* It is a quasi-Turing-complete machine; the quasi qualification
|
||||
* comes from the fact that the computation is intrinsically bounded
|
||||
*
|
||||
* It is a quasi-Turing-complete machine; the quasi qualification
|
||||
* comes from the fact that the computation is intrinsically bounded
|
||||
* through a parameter, gas, which limits the total amount of computation done.
|
||||
*
|
||||
* The EVM is a simple stack-based architecture. The word size of the machine
|
||||
* (and thus size of stack item) is 256-bit. This was chosen to facilitate
|
||||
* the SHA3-256 hash scheme and elliptic-curve computations. The memory model
|
||||
* is a simple word-addressed byte array. The stack has an unlimited size.
|
||||
* The machine also has an independent storage model; this is similar in concept
|
||||
* to the memory but rather than a byte array, it is a word-addressable word array.
|
||||
*
|
||||
* Unlike memory, which is volatile, storage is non volatile and is
|
||||
* maintained as part of the system state. All locations in both storage
|
||||
* The EVM is a simple stack-based architecture. The word size of the machine
|
||||
* (and thus size of stack item) is 256-bit. This was chosen to facilitate
|
||||
* the SHA3-256 hash scheme and elliptic-curve computations. The memory model
|
||||
* is a simple word-addressed byte array. The stack has an unlimited size.
|
||||
* The machine also has an independent storage model; this is similar in concept
|
||||
* to the memory but rather than a byte array, it is a word-addressable word array.
|
||||
*
|
||||
* Unlike memory, which is volatile, storage is non volatile and is
|
||||
* maintained as part of the system state. All locations in both storage
|
||||
* and memory are well-defined initially as zero.
|
||||
*
|
||||
* The machine does not follow the standard von Neumann architecture.
|
||||
* Rather than storing program code in generally-accessible memory or storage,
|
||||
* it is stored separately in a virtual ROM interactable only though
|
||||
*
|
||||
* The machine does not follow the standard von Neumann architecture.
|
||||
* Rather than storing program code in generally-accessible memory or storage,
|
||||
* it is stored separately in a virtual ROM interactable only though
|
||||
* a specialised instruction.
|
||||
*
|
||||
* The machine can have exceptional execution for several reasons,
|
||||
* including stack underflows and invalid instructions. These unambiguously
|
||||
* and validly result in immediate halting of the machine with all state changes
|
||||
* left intact. The one piece of exceptional execution that does not leave
|
||||
* state changes intact is the out-of-gas (OOG) exception.
|
||||
*
|
||||
* Here, the machine halts immediately and reports the issue to
|
||||
* the execution agent (either the transaction processor or, recursively,
|
||||
*
|
||||
* The machine can have exceptional execution for several reasons,
|
||||
* including stack underflows and invalid instructions. These unambiguously
|
||||
* and validly result in immediate halting of the machine with all state changes
|
||||
* left intact. The one piece of exceptional execution that does not leave
|
||||
* state changes intact is the out-of-gas (OOG) exception.
|
||||
*
|
||||
* Here, the machine halts immediately and reports the issue to
|
||||
* the execution agent (either the transaction processor or, recursively,
|
||||
* the spawning execution environment) and which will deal with it separately.
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
|
@ -62,22 +62,22 @@ import static org.ethereum.vm.OpCode.PUSH1;
|
|||
* Created on: 01/06/2014 10:44
|
||||
*/
|
||||
public class VM {
|
||||
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger("VM");
|
||||
private static final Logger dumpLogger = LoggerFactory.getLogger("dump");
|
||||
private static BigInteger _32_ = BigInteger.valueOf(32);
|
||||
private static String logString = "[{}]\t Op: [{}] Gas: [{}] Deep: [{}] Hint: [{}]";
|
||||
|
||||
|
||||
private static BigInteger MAX_GAS = BigInteger.valueOf(Long.MAX_VALUE);
|
||||
|
||||
|
||||
/* Keeps track of the number of steps performed in this VM */
|
||||
private int vmCounter = 0;
|
||||
|
||||
|
||||
public void step(Program program) {
|
||||
|
||||
if (CONFIG.vmTrace())
|
||||
program.saveOpTrace();
|
||||
|
||||
|
||||
try {
|
||||
OpCode op = OpCode.code(program.getCurrentOp());
|
||||
if (op == null)
|
||||
|
@ -96,7 +96,7 @@ public class VM {
|
|||
long gasCost = GasCost.STEP;
|
||||
long gasBefore = program.getGas().longValue();
|
||||
int stepBefore = program.getPC();
|
||||
|
||||
|
||||
// Calculate fees and spend gas
|
||||
switch (op) {
|
||||
case STOP: case SUICIDE:
|
||||
|
@ -123,7 +123,7 @@ public class VM {
|
|||
case BALANCE:
|
||||
gasCost = GasCost.BALANCE;
|
||||
break;
|
||||
|
||||
|
||||
// These all operate on memory and therefore potentially expand it:
|
||||
case MSTORE:
|
||||
newMemSize = memNeeded(stack.peek(), new DataWord(32));
|
||||
|
@ -196,13 +196,13 @@ public class VM {
|
|||
break;
|
||||
}
|
||||
program.spendGas(gasCost, op.name());
|
||||
|
||||
|
||||
// Avoid overflows
|
||||
if(newMemSize.compareTo(MAX_GAS) == 1)
|
||||
throw program.new OutOfGasException();
|
||||
|
||||
// memory gas calc
|
||||
long memoryUsage = (newMemSize.longValue() + 31) / 32 * 32;
|
||||
long memoryUsage = (newMemSize.longValue() + 31) / 32 * 32;
|
||||
if (memoryUsage > oldMemSize) {
|
||||
memWords = (memoryUsage - oldMemSize) / 32;
|
||||
long memGas = GasCost.MEMORY * memWords;
|
||||
|
@ -219,7 +219,7 @@ public class VM {
|
|||
// Log debugging line for VM
|
||||
if(program.getNumber().intValue() == CONFIG.dumpBlock())
|
||||
this.dumpLine(op, gasBefore, gasCost+callGas, memWords, program);
|
||||
|
||||
|
||||
// Execute operation
|
||||
switch (op) {
|
||||
/**
|
||||
|
@ -443,7 +443,7 @@ public class VM {
|
|||
/**
|
||||
* Bitwise Logic Operations
|
||||
*/
|
||||
case AND:{
|
||||
case AND:{
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
|
||||
|
@ -454,7 +454,7 @@ public class VM {
|
|||
program.stackPush(word1);
|
||||
program.step();
|
||||
} break;
|
||||
case OR: {
|
||||
case OR: {
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
|
||||
|
@ -465,7 +465,7 @@ public class VM {
|
|||
program.stackPush(word1);
|
||||
program.step();
|
||||
} break;
|
||||
case XOR: {
|
||||
case XOR: {
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
|
||||
|
@ -476,7 +476,7 @@ public class VM {
|
|||
program.stackPush(word1);
|
||||
program.step();
|
||||
} break;
|
||||
case BYTE:{
|
||||
case BYTE:{
|
||||
DataWord word1 = program.stackPop();
|
||||
DataWord word2 = program.stackPop();
|
||||
DataWord result = null;
|
||||
|
@ -515,7 +515,7 @@ public class VM {
|
|||
/**
|
||||
* SHA3
|
||||
*/
|
||||
case SHA3:{
|
||||
case SHA3:{
|
||||
DataWord memOffsetData = program.stackPop();
|
||||
DataWord lengthData = program.stackPop();
|
||||
ByteBuffer buffer = program.memoryChunk(memOffsetData, lengthData);
|
||||
|
@ -581,7 +581,7 @@ public class VM {
|
|||
program.stackPush(callValue);
|
||||
program.step();
|
||||
} break;
|
||||
case CALLDATALOAD:{
|
||||
case CALLDATALOAD:{
|
||||
DataWord dataOffs = program.stackPop();
|
||||
DataWord value = program.getDataValue(dataOffs);
|
||||
|
||||
|
@ -600,11 +600,11 @@ public class VM {
|
|||
program.stackPush(dataSize);
|
||||
program.step();
|
||||
} break;
|
||||
case CALLDATACOPY:{
|
||||
case CALLDATACOPY:{
|
||||
DataWord memOffsetData = program.stackPop();
|
||||
DataWord dataOffsetData = program.stackPop();
|
||||
DataWord lengthData = program.stackPop();
|
||||
|
||||
|
||||
byte[] msgData = program.getDataCopy(dataOffsetData, lengthData);
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
|
@ -614,7 +614,7 @@ public class VM {
|
|||
program.step();
|
||||
} break;
|
||||
case CODESIZE: case EXTCODESIZE: {
|
||||
|
||||
|
||||
int length;
|
||||
if (op == OpCode.CODESIZE)
|
||||
length = program.getCode().length;
|
||||
|
@ -629,7 +629,7 @@ public class VM {
|
|||
|
||||
program.stackPush(codeLength);
|
||||
program.step();
|
||||
} break;
|
||||
} break;
|
||||
case CODECOPY: case EXTCODECOPY: {
|
||||
|
||||
byte[] fullCode = ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
@ -733,19 +733,19 @@ public class VM {
|
|||
program.step();
|
||||
} break;
|
||||
case DUP1: case DUP2: case DUP3: case DUP4:
|
||||
case DUP5: case DUP6: case DUP7: case DUP8:
|
||||
case DUP9: case DUP10: case DUP11: case DUP12:
|
||||
case DUP5: case DUP6: case DUP7: case DUP8:
|
||||
case DUP9: case DUP10: case DUP11: case DUP12:
|
||||
case DUP13: case DUP14: case DUP15: case DUP16:{
|
||||
|
||||
int n = op.val() - OpCode.DUP1.val() + 1;
|
||||
DataWord word_1 = stack.get(stack.size() - n);
|
||||
program.stackPush(word_1.clone());
|
||||
program.step();
|
||||
|
||||
|
||||
} break;
|
||||
case SWAP1: case SWAP2: case SWAP3: case SWAP4:
|
||||
case SWAP5: case SWAP6: case SWAP7: case SWAP8:
|
||||
case SWAP9: case SWAP10: case SWAP11: case SWAP12:
|
||||
case SWAP5: case SWAP6: case SWAP7: case SWAP8:
|
||||
case SWAP9: case SWAP10: case SWAP11: case SWAP12:
|
||||
case SWAP13: case SWAP14: case SWAP15: case SWAP16:{
|
||||
|
||||
int n = op.val() - OpCode.SWAP1.val() + 2;
|
||||
|
@ -838,7 +838,7 @@ public class VM {
|
|||
if (nextPC != 0 && program.getOp(nextPC) != OpCode.JUMPDEST.val())
|
||||
throw program.new BadJumpDestinationException();
|
||||
}
|
||||
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "~> " + nextPC;
|
||||
|
||||
|
@ -848,7 +848,7 @@ public class VM {
|
|||
case JUMPI:{
|
||||
DataWord pos = program.stackPop();
|
||||
DataWord cond = program.stackPop();
|
||||
|
||||
|
||||
if (!cond.isZero()) {
|
||||
int nextPC = pos.intValue(); // possible overflow
|
||||
if(program.getPreviouslyExecutedOp() < OpCode.PUSH1.val() || program.getPreviouslyExecutedOp() > OpCode.PUSH32.val()) {
|
||||
|
@ -866,7 +866,7 @@ public class VM {
|
|||
} else {
|
||||
program.step();
|
||||
}
|
||||
|
||||
|
||||
} break;
|
||||
case PC:{
|
||||
int pc = program.getPC();
|
||||
|
@ -925,7 +925,7 @@ public class VM {
|
|||
String.format("%-12s", op.name()),
|
||||
program.getGas().value(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
|
||||
|
||||
program.createContract(value, inOffset, inSize);
|
||||
|
||||
program.step();
|
||||
|
@ -940,9 +940,9 @@ public class VM {
|
|||
|
||||
DataWord outDataOffs = program.stackPop();
|
||||
DataWord outDataSize = program.stackPop();
|
||||
|
||||
|
||||
if (logger.isInfoEnabled()) {
|
||||
hint = "addr: " + Hex.toHexString(codeAddress.getLast20Bytes())
|
||||
hint = "addr: " + Hex.toHexString(codeAddress.getLast20Bytes())
|
||||
+ " gas: " + gas.shortHex()
|
||||
+ " inOff: " + inDataOffs.shortHex()
|
||||
+ " inSize: " + inDataSize.shortHex();
|
||||
|
@ -951,7 +951,7 @@ public class VM {
|
|||
program.getGas().value(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
}
|
||||
|
||||
|
||||
MessageCall msg = new MessageCall(
|
||||
op.equals(CALL) ? MsgType.CALL : MsgType.STATELESS,
|
||||
gas, codeAddress, value, inDataOffs, inDataSize,
|
||||
|
@ -978,24 +978,24 @@ public class VM {
|
|||
case SUICIDE:{
|
||||
DataWord address = program.stackPop();
|
||||
program.suicide(address);
|
||||
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
hint = "address: " + Hex.toHexString(program.getOwnerAddress().getLast20Bytes());
|
||||
|
||||
|
||||
program.stop();
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
program.setPreviouslyExecutedOp(op.val());
|
||||
|
||||
|
||||
if (logger.isInfoEnabled() && !op.equals(CALL)
|
||||
&& !op.equals(CREATE))
|
||||
logger.info(logString, stepBefore, String.format("%-12s",
|
||||
op.name()), program.getGas().longValue(),
|
||||
program.invokeData.getCallDeep(), hint);
|
||||
|
||||
|
||||
vmCounter++;
|
||||
} catch (RuntimeException e) {
|
||||
logger.warn("VM halted: [{}]", e.toString());
|
||||
|
@ -1022,7 +1022,7 @@ public class VM {
|
|||
program.spendGas(GasCost.TX_NO_ZERO_DATA * nonZeroesVals, "DATA");
|
||||
program.spendGas(GasCost.TX_ZERO_DATA * zeroVals, "DATA");
|
||||
}
|
||||
|
||||
|
||||
while(!program.isStopped())
|
||||
this.step(program);
|
||||
|
||||
|
@ -1034,7 +1034,7 @@ public class VM {
|
|||
/**
|
||||
* Utility to calculate new total memory size needed for an operation.
|
||||
* <br/> Basically just offset + size, unless size is 0, in which case the result is also 0.
|
||||
*
|
||||
*
|
||||
* @param offset starting position of the memory
|
||||
* @param size number of bytes needed
|
||||
* @return offset + size, unless size is 0. In that case memNeeded is also 0.
|
||||
|
@ -1044,12 +1044,12 @@ public class VM {
|
|||
return BigInteger.ZERO;
|
||||
return offset.value().add(size.value());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Dumping the VM state at the current operation in various styles
|
||||
* - standard Not Yet Implemented
|
||||
* - standard+ (owner address, program counter, operation, gas left)
|
||||
* - pretty (stack, memory, storage, level, contract,
|
||||
* - pretty (stack, memory, storage, level, contract,
|
||||
* vmCounter, internalSteps, operation
|
||||
gasBefore, gasCost, memWords)
|
||||
*/
|
||||
|
@ -1057,12 +1057,12 @@ public class VM {
|
|||
if(CONFIG.dumpStyle().equals("standard+")) {
|
||||
switch (op) {
|
||||
case STOP: case RETURN: case SUICIDE:
|
||||
|
||||
|
||||
ContractDetails details = program.getResult().getRepository()
|
||||
.getContractDetails(program.getOwnerAddress().getLast20Bytes());
|
||||
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
|
||||
Collections.sort((List<DataWord>) storageKeys);
|
||||
|
||||
|
||||
for (DataWord key : storageKeys) {
|
||||
dumpLogger.trace("{} {}",
|
||||
Hex.toHexString(key.getNoLeadZeroesData()),
|
||||
|
@ -1086,25 +1086,25 @@ public class VM {
|
|||
String memoryString = program.memoryToString();
|
||||
if(!"".equals(memoryString))
|
||||
dumpLogger.trace("{}", memoryString);
|
||||
|
||||
|
||||
dumpLogger.trace(" STORAGE");
|
||||
ContractDetails details = program.getResult().getRepository()
|
||||
.getContractDetails(program.getOwnerAddress().getLast20Bytes());
|
||||
List<DataWord> storageKeys = new ArrayList<>(details.getStorage().keySet());
|
||||
Collections.sort((List<DataWord>) storageKeys);
|
||||
|
||||
|
||||
for (DataWord key : storageKeys) {
|
||||
dumpLogger.trace("{}: {}",
|
||||
key.shortHex(),
|
||||
details.getStorage().get(key).shortHex());
|
||||
}
|
||||
|
||||
|
||||
int level = program.invokeData.getCallDeep();
|
||||
String contract = Hex.toHexString(program.getOwnerAddress().getLast20Bytes());
|
||||
String internalSteps = String.format("%4s", Integer.toHexString(program.getPC())).replace(' ', '0').toUpperCase();
|
||||
dumpLogger.trace("{} | {} | #{} | {} : {} | {} | -{} | {}x32",
|
||||
level, contract, vmCounter, internalSteps, op,
|
||||
gasBefore, gasCost, memWords);
|
||||
gasBefore, gasCost, memWords);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ peer.connection.timeout = 2
|
|||
transaction.approve.timeout = 15
|
||||
|
||||
# the parameter specifies how much
|
||||
# time we will wait for a message
|
||||
# time we will wait for a message
|
||||
# to come before closing the channel
|
||||
peer.channel.read.timeout = 30
|
||||
|
||||
|
@ -52,8 +52,8 @@ peer.channel.read.timeout = 30
|
|||
samples.dir = samples
|
||||
|
||||
# everytime the application starts
|
||||
# the existing database will be
|
||||
# destroyed and all the data will be
|
||||
# the existing database will be
|
||||
# destroyed and all the data will be
|
||||
# downloaded from peers again
|
||||
database.reset = true
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ public class BlockTest {
|
|||
+ "9e262996493846a590c7011697dba07bb7680a256ede4034212b7a1ae6c7caea73190cb0"
|
||||
+ "7dedb91a07b72f34074e76a00cd22d78d556175604407dc6109797f5c8d990d05f1b352e"
|
||||
+ "10c71b3dd74bc70f8201f4c0";
|
||||
|
||||
|
||||
String block_32 = "f8f8f8f4a00a312c2b0a8f125c60a3976b6e508e740e095eb59943988d9bbfb8"
|
||||
+ "aa43922e31a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4"
|
||||
+ "934794e559de5527492bcb42ec68d07df0742a98ec3f1ea050188ab86bdf164ac90eb283"
|
||||
|
@ -104,7 +104,7 @@ public class BlockTest {
|
|||
assertEquals(Hex.toHexString(genesis.getParentHash()), Hex.toHexString(genesisFromRLP.getParentHash()));
|
||||
assertEquals(Hex.toHexString(genesis.getStateRoot()), Hex.toHexString(genesisFromRLP.getStateRoot()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGenesisFromNew() {
|
||||
Block genesis = Genesis.getInstance();
|
||||
|
@ -115,7 +115,7 @@ public class BlockTest {
|
|||
assertEquals(PoC7_GENESIS_HEX_HASH, Hex.toHexString(genesis.getHash()));
|
||||
assertEquals(PoC7_GENESIS_HEX_RLP_ENCODED, Hex.toHexString(genesis.getEncoded()));
|
||||
}
|
||||
|
||||
|
||||
@Test /* block without transactions - block#32 in PoC5 cpp-chain */
|
||||
public void testEmptyBlock() {
|
||||
byte[] payload = Hex.decode(block_32);
|
||||
|
@ -137,7 +137,7 @@ public class BlockTest {
|
|||
Block block = new Block(payload);
|
||||
logger.info(block.toString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCalcDifficulty() {
|
||||
|
||||
|
@ -157,7 +157,7 @@ public class BlockTest {
|
|||
logger.info("Block#1 calculated difficulty: [{}] ", calcDifficulty.toString());
|
||||
assertEquals(actualDifficulty, calcDifficulty);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCalcGasLimit() {
|
||||
BlockchainImpl blockchain = (BlockchainImpl)worldManager.getBlockchain();
|
||||
|
@ -240,14 +240,14 @@ public class BlockTest {
|
|||
// TODO
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testUncleInvalidGenerationGap() {
|
||||
// TODO
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testUncleInvalidParentGenerationGap() {
|
||||
|
|
|
@ -19,30 +19,30 @@ public class MinerTest {
|
|||
// Example block#32 from Poc5 chain - rlpEncoded without nonce
|
||||
private String rlpWithoutNonce = "f894f890a00a312c2b0a8f125c60a3976b6e508e740e095eb59943988d9bbfb8"
|
||||
+ "aa43922e31a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794e559de5527492bcb42ec68d07df0742a98ec3f1ea050188ab86bdf164ac90eb2835a04a8930aae5393c3a2ef1166fb95028f9456b880833ee248208609184e72a000830eca0080845387fd2080c0c0";
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void testMine() {
|
||||
boolean miningTestEnabled = false;
|
||||
|
||||
|
||||
if(miningTestEnabled) {
|
||||
Block block = createBlock(null);
|
||||
assertEquals(rlpWithoutNonce, Hex.toHexString(block.getEncodedWithoutNonce()));
|
||||
System.out.println("Searching for nonce of following block: \n" + block.toString());
|
||||
|
||||
|
||||
Miner miner = new Miner();
|
||||
boolean mined = miner.mine(block, block.getDifficulty());
|
||||
assertTrue(mined);
|
||||
boolean valid = block.validateNonce();
|
||||
assertTrue(valid);
|
||||
|
||||
|
||||
// expectedHash is the actual hash from block#32 in PoC5 chain based on nonce below
|
||||
String expectedHash = "ce7201f6cc5eb1a6f35c7dda8acda111647a0f8a5bf0518e46579b03e29fe14b";
|
||||
assertEquals(expectedHash, Hex.toHexString(block.getHash()));
|
||||
|
||||
// expectedNonce is the actual nonce from block#32 in Poc5 chain
|
||||
String expectedNonce = "0000000000000000000000000000000000000000000000001f52ebb192c4ea97"; // from Poc5 chain
|
||||
// Actual is "000000000000000000000000000000000000000000000000000000000098cc15"
|
||||
// Actual is "000000000000000000000000000000000000000000000000000000000098cc15"
|
||||
// but that might also be a valid nonce in compliance with PoW(H!n, n) < (2^256 / difficulty)
|
||||
assertEquals(expectedNonce, Hex.toHexString(block.getNonce()));
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public class StateTest {
|
|||
byte[] minerAddress = Hex.decode("4c5f4d519dff3c16f0d54b6866e256fbbbc1a600");
|
||||
AccountState account_3 = new AccountState(BigInteger.ZERO, new BigInteger("1506260000000000000"));
|
||||
trie.update(minerAddress, account_3.getEncoded());
|
||||
|
||||
|
||||
assertEquals(expected, Hex.toHexString(trie.getRootHash()));
|
||||
|
||||
|
||||
|
@ -116,7 +116,7 @@ public class StateTest {
|
|||
Trie trie = new TrieImpl(new MockDB());
|
||||
for (String address : Genesis.getPremine()) {
|
||||
AccountState acct = new AccountState(BigInteger.ZERO, BigInteger.valueOf(2).pow(200));
|
||||
trie.update(Hex.decode(address), acct.getEncoded());
|
||||
trie.update(Hex.decode(address), acct.getEncoded());
|
||||
}
|
||||
return trie;
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ public class TransactionTest {
|
|||
|
||||
ECKey ecKey = ECKey.fromPrivate(HashUtil.sha3("cat".getBytes()));
|
||||
byte[] senderPrivKey = HashUtil.sha3("cow".getBytes());
|
||||
|
||||
|
||||
byte[] nonce = { 0x01 };
|
||||
byte[] gasPrice = Hex.decode("09184e72a000");
|
||||
byte[] gasLimit = Hex.decode("4255");
|
||||
|
@ -152,14 +152,14 @@ public class TransactionTest {
|
|||
byte[] testValue = BigIntegers.asUnsignedByteArray(BigInteger.valueOf(10000000000000000L));
|
||||
byte[] testData = Hex.decode("");
|
||||
byte[] testInit = Hex.decode("");
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionFromSignedRLP() throws Exception {
|
||||
Transaction txSigned = new Transaction(Hex.decode(RLP_ENCODED_SIGNED_TX));
|
||||
|
||||
|
||||
assertEquals(HASH_TX, Hex.toHexString(txSigned.getHash()));
|
||||
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txSigned.getEncoded()));
|
||||
|
||||
|
||||
assertEquals(BigInteger.ZERO, new BigInteger(1, txSigned.getNonce()));
|
||||
assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txSigned.getGasPrice()));
|
||||
assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txSigned.getGasLimit()));
|
||||
|
@ -170,16 +170,16 @@ public class TransactionTest {
|
|||
assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txSigned.getSignature().r)));
|
||||
assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txSigned.getSignature().s)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionFromUnsignedRLP() throws Exception {
|
||||
Transaction txUnsigned = new Transaction(Hex.decode(RLP_ENCODED_UNSIGNED_TX));
|
||||
|
||||
|
||||
assertEquals(HASH_TX, Hex.toHexString(txUnsigned.getHash()));
|
||||
assertEquals(RLP_ENCODED_UNSIGNED_TX, Hex.toHexString(txUnsigned.getEncoded()));
|
||||
txUnsigned.sign(Hex.decode(KEY));
|
||||
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txUnsigned.getEncoded()));
|
||||
|
||||
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txUnsigned.getEncoded()));
|
||||
|
||||
assertEquals(BigInteger.ZERO, new BigInteger(1, txUnsigned.getNonce()));
|
||||
assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txUnsigned.getGasPrice()));
|
||||
assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txUnsigned.getGasLimit()));
|
||||
|
@ -190,11 +190,11 @@ public class TransactionTest {
|
|||
assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txUnsigned.getSignature().r)));
|
||||
assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txUnsigned.getSignature().s)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionFromNew1() throws MissingPrivateKeyException {
|
||||
Transaction txNew = new Transaction(testNonce, testGasPrice, testGasLimit, testReceiveAddress, testValue, testData);
|
||||
|
||||
|
||||
assertEquals("", Hex.toHexString(txNew.getNonce()));
|
||||
assertEquals(new BigInteger(1, testGasPrice), new BigInteger(1, txNew.getGasPrice()));
|
||||
assertEquals(new BigInteger(1, testGasLimit), new BigInteger(1, txNew.getGasLimit()));
|
||||
|
@ -202,35 +202,35 @@ public class TransactionTest {
|
|||
assertEquals(new BigInteger(1, testValue), new BigInteger(1, txNew.getValue()));
|
||||
assertEquals("", Hex.toHexString(txNew.getData()));
|
||||
assertNull(txNew.getSignature());
|
||||
|
||||
|
||||
assertEquals(RLP_ENCODED_RAW_TX, Hex.toHexString(txNew.getEncodedRaw()));
|
||||
assertEquals(HASH_TX, Hex.toHexString(txNew.getHash()));
|
||||
assertEquals(RLP_ENCODED_UNSIGNED_TX, Hex.toHexString(txNew.getEncoded()));
|
||||
txNew.sign(Hex.decode(KEY));
|
||||
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txNew.getEncoded()));
|
||||
|
||||
assertEquals(RLP_ENCODED_SIGNED_TX, Hex.toHexString(txNew.getEncoded()));
|
||||
|
||||
assertEquals(27, txNew.getSignature().v);
|
||||
assertEquals("eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4", Hex.toHexString(BigIntegers.asUnsignedByteArray(txNew.getSignature().r)));
|
||||
assertEquals("14a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1", Hex.toHexString(BigIntegers.asUnsignedByteArray(txNew.getSignature().s)));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTransactionFromNew2() throws MissingPrivateKeyException {
|
||||
byte[] privKeyBytes = Hex.decode("c85ef7d79691fe79573b1a7064c19c1a9819ebdbd1faaab1a8ec92344438aaf4");
|
||||
|
||||
|
||||
String RLP_TX_UNSIGNED = "eb8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc1000080808080";
|
||||
String RLP_TX_SIGNED = "f86b8085e8d4a510008227109413978aee95f38490e9769c39b2773ed763d9cd5f872386f26fc10000801ba0eab47c1a49bf2fe5d40e01d313900e19ca485867d462fe06e139e3a536c6d4f4a014a569d327dcda4b29f74f93c0e9729d2f49ad726e703f9cd90dbb0fbf6649f1";
|
||||
String HASH_TX_UNSIGNED = "328ea6d24659dec48adea1aced9a136e5ebdf40258db30d1b1d97ed2b74be34e";
|
||||
|
||||
|
||||
byte[] nonce = BigIntegers.asUnsignedByteArray(BigInteger.ZERO);
|
||||
byte[] gasPrice = Hex.decode("e8d4a51000"); // 1000000000000
|
||||
byte[] gas = Hex.decode("2710"); // 10000
|
||||
byte[] recieveAddress = Hex.decode("13978aee95f38490e9769c39b2773ed763d9cd5f");
|
||||
byte[] value = Hex.decode("2386f26fc10000"); //10000000000000000"
|
||||
byte[] data = new byte[0];
|
||||
|
||||
|
||||
Transaction tx = new Transaction(nonce, gasPrice, gas, recieveAddress, value, data);
|
||||
|
||||
|
||||
// Testing unsigned
|
||||
String encodedUnsigned = Hex.toHexString(tx.getEncoded());
|
||||
assertEquals(RLP_TX_UNSIGNED, encodedUnsigned);
|
||||
|
@ -238,7 +238,7 @@ public class TransactionTest {
|
|||
|
||||
// Testing signed
|
||||
tx.sign(privKeyBytes);
|
||||
String encodedSigned = Hex.toHexString(tx.getEncoded());
|
||||
String encodedSigned = Hex.toHexString(tx.getEncoded());
|
||||
assertEquals(RLP_TX_SIGNED, encodedSigned);
|
||||
assertEquals(HASH_TX_UNSIGNED, Hex.toHexString(tx.getHash()));
|
||||
}
|
||||
|
|
|
@ -28,19 +28,19 @@ import com.google.common.util.concurrent.MoreExecutors;
|
|||
|
||||
public class ECKeyTest {
|
||||
private static final Logger log = LoggerFactory.getLogger(ECKeyTest.class);
|
||||
|
||||
|
||||
private String privString = "3ecb44df2159c26e0f995712d4f39b6f6e499b40749b1cf1246c37f9516cb6a4";
|
||||
private BigInteger privateKey = new BigInteger(Hex.decode(privString));
|
||||
|
||||
|
||||
private String pubString = "0497466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce78549b514e4453d74ef11b0cd5e4e4c364effddac8b51bcfc8de80682f952896f";
|
||||
private String compressedPubString = "0397466f2b32bc3bb76d4741ae51cd1d8578b48d3f1e68da206d47321aec267ce7";
|
||||
private byte[] pubKey = Hex.decode(pubString);
|
||||
private byte[] compressedPubKey = Hex.decode(compressedPubString);
|
||||
private String address = "8a40bfaa73256b60764c1bf40675a99083efb075";
|
||||
|
||||
|
||||
private String exampleMessage = new String("This is an example of a signed message.");
|
||||
private String sigBase64 = "HD5AsBr4wuH6UU9tXuSJhUvgfGayfwoY0cKT03sFUjnpQsupHznd/3mCIRfLuNHlRCVGdAyHecdyM8IVZMtc1I8=";
|
||||
|
||||
|
||||
@Test
|
||||
public void testHashCode() {
|
||||
Assert.assertEquals(1866897155, ECKey.fromPrivate(privateKey).hashCode());
|
||||
|
@ -84,7 +84,7 @@ public class ECKeyTest {
|
|||
byte[] pubFromPriv = ECKey.publicKeyFromPrivate(privateKey, false);
|
||||
assertArrayEquals(pubKey, pubFromPriv);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPublicKeyFromPrivateCompressed() {
|
||||
byte[] pubFromPriv = ECKey.publicKeyFromPrivate(privateKey, true);
|
||||
|
@ -105,7 +105,7 @@ public class ECKeyTest {
|
|||
|
||||
@Test
|
||||
public void testEthereumSign() throws IOException {
|
||||
// TODO: Understand why key must be decompressed for this to work
|
||||
// TODO: Understand why key must be decompressed for this to work
|
||||
ECKey key = ECKey.fromPrivate(privateKey).decompress();
|
||||
System.out.println("Secret\t: " + Hex.toHexString(key.getPrivKeyBytes()));
|
||||
System.out.println("Pubkey\t: " + Hex.toHexString(key.getPubKey()));
|
||||
|
@ -116,7 +116,7 @@ public class ECKeyTest {
|
|||
System.out.println("Signtr\t: " + output + " (Base64, length: " + output.length() + ")");
|
||||
assertEquals(sigBase64, output);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testVerifySignature1() {
|
||||
ECKey key = ECKey.fromPublicOnly(pubKey);
|
||||
|
@ -125,7 +125,7 @@ public class ECKeyTest {
|
|||
ECDSASignature sig = ECDSASignature.fromComponents(r.toByteArray(), s.toByteArray(), (byte) 28);
|
||||
key.verify(HashUtil.sha3(exampleMessage.getBytes()), sig);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testVerifySignature2() {
|
||||
BigInteger r = new BigInteger("c52c114d4f5a3ba904a9b3036e5e118fe0dbb987fe3955da20f2cd8f6c21ab9c", 16);
|
||||
|
@ -158,7 +158,7 @@ public class ECKeyTest {
|
|||
// todo: add test assertion when the sign/verify part actually works.
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testSValue() throws Exception {
|
||||
// Check that we never generate an S value that is larger than half the curve order. This avoids a malleability
|
||||
|
@ -184,7 +184,7 @@ public class ECKeyTest {
|
|||
assertEquals(sigs.get(0), duplicate);
|
||||
assertEquals(sigs.get(0).hashCode(), duplicate.hashCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSignVerify() {
|
||||
ECKey key = ECKey.fromPrivate(privateKey);
|
||||
|
@ -192,7 +192,7 @@ public class ECKeyTest {
|
|||
ECDSASignature output = key.doSign(message.getBytes());
|
||||
assertTrue(key.verify(message.getBytes(), output));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsPubKeyCanonicalCorect() {
|
||||
// Test correct prefix 4, right length 65
|
||||
|
@ -205,7 +205,7 @@ public class ECKeyTest {
|
|||
byte[] canonicalPubkey3 = new byte[33]; canonicalPubkey3[0] = 0x03;
|
||||
assertTrue(ECKey.isPubKeyCanonical(canonicalPubkey3));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsPubKeyCanonicalWrongLength() {
|
||||
// Test correct prefix 4, but wrong length !65
|
||||
|
@ -218,7 +218,7 @@ public class ECKeyTest {
|
|||
byte[] nonCanonicalPubkey3 = new byte[32]; nonCanonicalPubkey3[0] = 0x03;
|
||||
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey3));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIsPubKeyCanonicalWrongPrefix() {
|
||||
// Test wrong prefix 4, right length 65
|
||||
|
@ -231,7 +231,7 @@ public class ECKeyTest {
|
|||
byte[] nonCanonicalPubkey6 = new byte[33];
|
||||
assertFalse(ECKey.isPubKeyCanonical(nonCanonicalPubkey6));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void keyRecovery() throws Exception {
|
||||
ECKey key = new ECKey();
|
||||
|
@ -250,7 +250,7 @@ public class ECKeyTest {
|
|||
}
|
||||
assertTrue(found);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSignedMessageToKey() throws SignatureException {
|
||||
byte[] messageHash = HashUtil.sha3(exampleMessage.getBytes());
|
||||
|
@ -258,7 +258,7 @@ public class ECKeyTest {
|
|||
assertNotNull(key);
|
||||
assertArrayEquals(pubKey, key.getPubKey());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetPrivKeyBytes() {
|
||||
ECKey key = new ECKey();
|
||||
|
@ -271,9 +271,9 @@ public class ECKeyTest {
|
|||
ECKey key0 = new ECKey();
|
||||
ECKey key1 = ECKey.fromPrivate(privateKey);
|
||||
ECKey key2 = ECKey.fromPrivate(privateKey);
|
||||
|
||||
|
||||
assertFalse(key0.equals(key1));
|
||||
assertTrue(key1.equals(key1));
|
||||
assertTrue(key1.equals(key2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,10 @@ public class ByteArrayWrapperTest {
|
|||
static ByteArrayWrapper wrapper2;
|
||||
static ByteArrayWrapper wrapper3;
|
||||
static ByteArrayWrapper wrapper4;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void loadByteArrays() {
|
||||
|
||||
|
||||
String block = "f9072df8d3a077ef4fdaf389dca53236bcf7f72698e154eab2828f86fbc4fc6c"
|
||||
+ "d9225d285c89a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0"
|
||||
+ "a142fd40d493479476f5eabe4b342ee56b8ceba6ab2a770c3e2198e7a0faa0ca"
|
||||
|
@ -81,18 +81,18 @@ public class ByteArrayWrapperTest {
|
|||
+ "2ba37af8e83c3741225da066ae0ec1217b0ca698a5369d4881e1c4cbde56af99"
|
||||
+ "31ebf9281580a23b659c08a051f947cb2315d0259f55848c630caa10cd91d6e4"
|
||||
+ "4ff8bad7758c65b25e2191308227d2c0";
|
||||
|
||||
|
||||
byte[] test1 = Hex.decode(block);
|
||||
byte[] test2 = Hex.decode(block);
|
||||
byte[] test3 = Hex.decode("4ff8bad7758c65b25e2191308227d2c0");
|
||||
byte[] test4 = Hex.decode("");
|
||||
|
||||
|
||||
wrapper1 = new ByteArrayWrapper(test1);
|
||||
wrapper2 = new ByteArrayWrapper(test2);
|
||||
wrapper3 = new ByteArrayWrapper(test3);
|
||||
wrapper4 = new ByteArrayWrapper(test4);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEqualsObject() {
|
||||
assertTrue(wrapper1.equals(wrapper2));
|
||||
|
@ -109,11 +109,11 @@ public class ByteArrayWrapperTest {
|
|||
assertTrue(wrapper1.compareTo(wrapper4) > 1);
|
||||
assertTrue(wrapper2.compareTo(wrapper3) > 1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEqualsPerformance() {
|
||||
boolean testEnabled = false;
|
||||
|
||||
|
||||
if(testEnabled) {
|
||||
final int ITERATIONS = 10000000;
|
||||
long start1 = System.currentTimeMillis();
|
||||
|
@ -125,18 +125,18 @@ public class ByteArrayWrapperTest {
|
|||
wrapper2.getData());
|
||||
}
|
||||
System.out.println(System.currentTimeMillis() - start1 + "ms");
|
||||
|
||||
|
||||
long start2 = System.currentTimeMillis();
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
Arrays.equals(wrapper1.getData(), wrapper2.getData());
|
||||
}
|
||||
System.out.println(System.currentTimeMillis() - start2 + "ms");
|
||||
|
||||
|
||||
long start3 = System.currentTimeMillis();
|
||||
for (int i = 0; i < ITERATIONS; i++) {
|
||||
FastByteComparisons.compareTo(wrapper1.getData(), 0, wrapper1.getData().length, wrapper2.getData(), 0, wrapper1.getData().length);
|
||||
}
|
||||
System.out.println(System.currentTimeMillis() - start3 + "ms");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ import org.spongycastle.util.encoders.Hex;
|
|||
* Created on: 11/06/2014 14:54
|
||||
*/
|
||||
public class TrackDatabaseTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void test1() {
|
||||
|
||||
|
@ -50,7 +50,7 @@ public class TrackDatabaseTest {
|
|||
|
||||
db1.close();
|
||||
}
|
||||
|
||||
|
||||
@AfterClass
|
||||
public static void destroyDB() {
|
||||
try {
|
||||
|
|
|
@ -18,9 +18,9 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Test file specific for tests maintained in the GitHub repository
|
||||
* Test file specific for tests maintained in the GitHub repository
|
||||
* by the Ethereum DEV team. <br/>
|
||||
*
|
||||
*
|
||||
* @see <a href="https://github.com/ethereum/tests/">https://github.com/ethereum/tests/</a>
|
||||
*/
|
||||
@RunWith(Suite.class)
|
||||
|
@ -31,7 +31,7 @@ public class GitHubJSONTestSuite {
|
|||
|
||||
private static Logger logger = LoggerFactory.getLogger("TCK-Test");
|
||||
|
||||
|
||||
|
||||
protected static void runGitHubJsonTest(String json) throws ParseException {
|
||||
Assume.assumeFalse("Online test is not available", json.equals(""));
|
||||
|
||||
|
@ -44,7 +44,7 @@ public class GitHubJSONTestSuite {
|
|||
while (testIterator.hasNext()){
|
||||
|
||||
TestCase testCase = testIterator.next();
|
||||
|
||||
|
||||
TestRunner runner = new TestRunner();
|
||||
List<String> result = runner.runTestCase(testCase);
|
||||
Assert.assertTrue(result.isEmpty());
|
||||
|
|
|
@ -97,6 +97,6 @@ public class GitHubStateTest {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -16,56 +16,56 @@ public class GitHubVMTest {
|
|||
String json = JSONReader.loadJSON("VMTests/vmArithmeticTest.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testBitwiseLogicOperationFromGitHub() throws ParseException {
|
||||
|
||||
String json = JSONReader.loadJSON("VMTests/vmBitwiseLogicOperationTest.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testBlockInfoFromGitHub() throws ParseException {
|
||||
|
||||
String json = JSONReader.loadJSON("VMTests/vmBlockInfoTest.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testEnvironmentalInfoFromGitHub() throws ParseException {
|
||||
|
||||
String json = JSONReader.loadJSON("VMTests/vmEnvironmentalInfoTest.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testIOandFlowOperationsFromGitHub() throws ParseException {
|
||||
|
||||
String json = JSONReader.loadJSON("VMTests/vmIOandFlowOperationsTest.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testPushDupSwapFromGitHub() throws ParseException {
|
||||
|
||||
String json = JSONReader.loadJSON("VMTests/vmPushDupSwapTest.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testShaFromGitHub() throws ParseException {
|
||||
|
||||
String json = JSONReader.loadJSON("VMTests/vmSha3Test.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testVMGitHub() throws ParseException {
|
||||
|
||||
String json = JSONReader.loadJSON("VMTests/vmtests.json");
|
||||
GitHubJSONTestSuite.runGitHubJsonTest(json);
|
||||
}
|
||||
|
||||
|
||||
@Test // testing full suite
|
||||
public void testVMLogGitHub() throws ParseException {
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Roman Mandeleil
|
||||
* @author Roman Mandeleil
|
||||
* Created on: 22/05/2014 09:26
|
||||
*/
|
||||
public class MinerThread implements Runnable {
|
||||
|
|
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue