Document Transaction and Block and add VM OpCode enum
This commit is contained in:
parent
1f3455f5c6
commit
6fca92b62f
|
@ -0,0 +1,144 @@
|
|||
package org.ethereum.crypto.vm;
|
||||
|
||||
/**
|
||||
* Instruction set for the Ethereum Virtual Machine
|
||||
*/
|
||||
public enum OpCode {
|
||||
|
||||
/**
|
||||
* Stop and Arithmetic Operations
|
||||
*/
|
||||
|
||||
STOP(0x00),
|
||||
ADD(0x01),
|
||||
MUL(0x02),
|
||||
SUB(0x03),
|
||||
DIV(0x04),
|
||||
SDIV(0x05),
|
||||
MOD(0x06),
|
||||
SMOD(0x07),
|
||||
EXP(0x08),
|
||||
NEG(0x09),
|
||||
LT(0x0a),
|
||||
GT(0x0b),
|
||||
EQ(0x0c),
|
||||
NOT(0x0d),
|
||||
|
||||
/**
|
||||
* Bitwise Logic Operations
|
||||
*/
|
||||
|
||||
AND(0x10),
|
||||
OR(0x11),
|
||||
XOR(0x12),
|
||||
BYTE(0x13),
|
||||
|
||||
/**
|
||||
* SHA3
|
||||
*/
|
||||
|
||||
SHA3(0x20),
|
||||
|
||||
/**
|
||||
* Environmental Information
|
||||
*/
|
||||
|
||||
ADDRESS(0x30),
|
||||
BALANCE(0x31),
|
||||
ORIGIN(0x32),
|
||||
CALLER(0x33),
|
||||
CALLVALUE(0x34),
|
||||
CALLDATALOAD(0x35),
|
||||
CALLDATASIZE(0x36),
|
||||
CALLDATACOPY(0x37),
|
||||
CODESIZE(0x38),
|
||||
CODECOPY(0x39),
|
||||
GASPRICE(0x3a),
|
||||
|
||||
/**
|
||||
* Block Information
|
||||
*/
|
||||
|
||||
PREVHASH(0x40),
|
||||
COINBASE(0x41),
|
||||
TIMESTAMP(0x42),
|
||||
NUMBER(0x43),
|
||||
DIFFICULTY(0x44),
|
||||
GASLIMIT(0x45),
|
||||
|
||||
/**
|
||||
* Memory, Storage and Flow Operations
|
||||
*/
|
||||
|
||||
POP(0x50),
|
||||
DUP(0x51),
|
||||
SWAP(0x52),
|
||||
MLOAD(0x53),
|
||||
MSTORE(0x54),
|
||||
MSTORE8(0x55),
|
||||
SLOAD(0x56),
|
||||
SSTORE(0x57),
|
||||
JUMP(0x58),
|
||||
JUMPI(0x59),
|
||||
PC(0x5a),
|
||||
MSIZE(0x5b),
|
||||
GAS(0x5c),
|
||||
|
||||
/**
|
||||
* Push Operations
|
||||
*/
|
||||
|
||||
PUSH1(0x60),
|
||||
PUSH2(0x61),
|
||||
PUSH3(0x62),
|
||||
PUSH4(0x63),
|
||||
PUSH5(0x64),
|
||||
PUSH6(0x65),
|
||||
PUSH7(0x66),
|
||||
PUSH8(0x67),
|
||||
PUSH9(0x68),
|
||||
PUSH10(0x69),
|
||||
PUSH11(0x6a),
|
||||
PUSH12(0x6b),
|
||||
PUSH13(0x6c),
|
||||
PUSH14(0x6d),
|
||||
PUSH15(0x6e),
|
||||
PUSH16(0x6f),
|
||||
PUSH17(0x70),
|
||||
PUSH18(0x71),
|
||||
PUSH19(0x72),
|
||||
PUSH20(0x73),
|
||||
PUSH21(0x74),
|
||||
PUSH22(0x75),
|
||||
PUSH23(0x76),
|
||||
PUSH24(0x77),
|
||||
PUSH25(0x78),
|
||||
PUSH26(0x79),
|
||||
PUSH27(0x7a),
|
||||
PUSH28(0x7b),
|
||||
PUSH29(0x7c),
|
||||
PUSH30(0x7d),
|
||||
PUSH31(0x7e),
|
||||
PUSH32(0x7f),
|
||||
|
||||
/**
|
||||
* System operations
|
||||
*/
|
||||
|
||||
CREATE(0xf0),
|
||||
CALL(0xf1),
|
||||
RETURN(0xf2),
|
||||
SUICIDE(0xff);
|
||||
|
||||
private int opcode;
|
||||
|
||||
private OpCode(int opcode) {
|
||||
this.opcode = opcode;
|
||||
}
|
||||
|
||||
public int getOpCode() {
|
||||
return this.opcode;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -11,21 +11,41 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 13/04/14 19:34
|
||||
* 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
|
||||
* (such blocks are known as uncles).
|
||||
*/
|
||||
public class Block {
|
||||
|
||||
private static int LIMIT_FACTOR = (int) Math.pow(2, 16);
|
||||
private static double EMA_FACTOR = 1.5;
|
||||
/* A scalar value equal to the current limit of gas expenditure per block */
|
||||
private static int GAS_LIMIT = (int) Math.pow(10, 6);
|
||||
|
||||
private RLPList rawData;
|
||||
private boolean parsed = false;
|
||||
|
||||
private byte[] hash;
|
||||
|
||||
/* 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
|
||||
* successful mining of this block be transferred; formally */
|
||||
private byte[] coinbase;
|
||||
/* The SHA3 256-bit hash of the root node of the state trie,
|
||||
* after all transactions are executed and finalisations applied */
|
||||
private byte[] stateHash;
|
||||
private byte[] txListHash;
|
||||
/* The SHA3 256-bit hash of the root node of the trie structure
|
||||
* populated with each transaction in the transactions list portion
|
||||
* of the block */
|
||||
private byte[] txTrieHash;
|
||||
/* A scalar value corresponding to the difficulty level of this block.
|
||||
* This can be calculated from the previous block’s difficulty level
|
||||
* and the timestamp */
|
||||
private byte[] difficulty;
|
||||
|
||||
private long timestamp;
|
||||
|
@ -40,12 +60,12 @@ public class Block {
|
|||
this.parsed = false;
|
||||
}
|
||||
|
||||
public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] stateHash, byte[] txListHash, byte[] difficulty, long timestamp, byte[] extraData, byte[] nonce, List<Transaction> transactionsList, List<Block> uncleList) {
|
||||
public Block(byte[] parentHash, byte[] unclesHash, byte[] coinbase, byte[] stateHash, byte[] txTrieHash, byte[] difficulty, long timestamp, byte[] extraData, byte[] nonce, List<Transaction> transactionsList, List<Block> uncleList) {
|
||||
this.parentHash = parentHash;
|
||||
this.unclesHash = unclesHash;
|
||||
this.coinbase = coinbase;
|
||||
this.stateHash = stateHash;
|
||||
this.txListHash = txListHash;
|
||||
this.txTrieHash = txTrieHash;
|
||||
this.difficulty = difficulty;
|
||||
this.timestamp = timestamp;
|
||||
this.extraData = extraData;
|
||||
|
@ -66,7 +86,7 @@ public class Block {
|
|||
this.unclesHash = ((RLPItem) params.get(1)).getData();
|
||||
this.coinbase = ((RLPItem) params.get(2)).getData();
|
||||
this.stateHash = ((RLPItem) params.get(3)).getData();
|
||||
this.txListHash = ((RLPItem) params.get(4)).getData();
|
||||
this.txTrieHash = ((RLPItem) params.get(4)).getData();
|
||||
this.difficulty = ((RLPItem) params.get(5)).getData();
|
||||
|
||||
byte[] tsBytes = ((RLPItem) params.get(6)).getData();
|
||||
|
@ -95,6 +115,11 @@ public class Block {
|
|||
return hash;
|
||||
}
|
||||
|
||||
public Block getParent() {
|
||||
// TODO: Implement
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] getParentHash() {
|
||||
if (!parsed) parseRLP();
|
||||
return parentHash;
|
||||
|
@ -115,9 +140,9 @@ public class Block {
|
|||
return stateHash;
|
||||
}
|
||||
|
||||
public byte[] getTxListHash() {
|
||||
public byte[] getTxTrieHash() {
|
||||
if (!parsed) parseRLP();
|
||||
return txListHash;
|
||||
return txTrieHash;
|
||||
}
|
||||
|
||||
public byte[] getDifficulty() {
|
||||
|
@ -160,11 +185,37 @@ public class Block {
|
|||
", unclesHash=" + Utils.toHexString(unclesHash) +
|
||||
", coinbase=" + Utils.toHexString(coinbase) +
|
||||
", stateHash=" + Utils.toHexString(stateHash) +
|
||||
", txListHash=" + Utils.toHexString(txListHash) +
|
||||
", txTrieHash=" + Utils.toHexString(txTrieHash) +
|
||||
", difficulty=" + Utils.toHexString(difficulty) +
|
||||
", timestamp=" + timestamp +
|
||||
", extraData=" + Utils.toHexString(extraData) +
|
||||
", nonce=" + Utils.toHexString(nonce) +
|
||||
']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Because every transaction published into the blockchain imposes on the
|
||||
* network the cost of needing to download and verify it, there is a need
|
||||
* for some regulatory mechanism to prevent abuse.
|
||||
*
|
||||
* To solve this we simply institute a floating cap:
|
||||
*
|
||||
* No block can have more operations than BLK_LIMIT_FACTOR times
|
||||
* the long-term exponential moving average.
|
||||
*
|
||||
* Specifically:
|
||||
*
|
||||
* blk.oplimit = floor((blk.parent.oplimit * (EMAFACTOR - 1)
|
||||
* + floor(GAS_LIMIT * BLK_LIMIT_FACTOR)) / EMA_FACTOR)
|
||||
*
|
||||
* BLK_LIMIT_FACTOR and EMA_FACTOR are constants that will be set
|
||||
* to 65536 and 1.5 for the time being, but will likely be changed
|
||||
* after further analysis.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public double getOplimit() {
|
||||
return Math.floor((this.getParent().getOplimit() * (EMA_FACTOR - 1)
|
||||
+ Math.floor(GAS_LIMIT * LIMIT_FACTOR)) / EMA_FACTOR);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,35 +7,49 @@ import org.ethereum.net.rlp.RLPList;
|
|||
import org.ethereum.util.Utils;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* User: Roman Mandeleil
|
||||
* Created on: 21/04/14 09:19
|
||||
* 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 RLPList rawData;
|
||||
private boolean parsed = false;
|
||||
|
||||
// creation contract tx or simple send tx
|
||||
// [ nonce, value, receiveAddress, gasPrice, gasDeposit, data, signatureV, signatureR, signatureS ]
|
||||
// or
|
||||
// [ nonce, endowment, 0, gasPrice, gasDeposit (for init), body, init, signatureV, signatureR, signatureS ]
|
||||
/* creation contract tx or simple send tx
|
||||
* [ nonce, value, receiveAddress, gasPrice, gasDeposit, data, signatureV, signatureR, signatureS ]
|
||||
* or
|
||||
* [ nonce, endowment, 0, gasPrice, gasDeposit (for init), body, init, signatureV, signatureR, signatureS ]
|
||||
*/
|
||||
|
||||
/* SHA3 hash of the rlpEncoded transaction */
|
||||
private byte[] hash;
|
||||
/* a counter used to make sure each transaction can only be processed once */
|
||||
private byte[] nonce;
|
||||
/* the amount of ether to transfer (calculated as wei) */
|
||||
private byte[] value;
|
||||
|
||||
// In creation transaction the receive address is - 0
|
||||
/* the address of the destination account
|
||||
* In creation transaction the receive address is - 0 */
|
||||
private byte[] receiveAddress;
|
||||
/* the amount of ether to pay as a transaction fee
|
||||
* to the miner for each unit of gas */
|
||||
private byte[] gasPrice;
|
||||
private byte[] gas;
|
||||
|
||||
// Contract creation [data] will hold the contract
|
||||
// for other transaction [data] can hold data
|
||||
/* the amount of "gas" to allow for the computation.
|
||||
* Gas is the fuel of the computational engine;
|
||||
* every computational step taken and every byte added
|
||||
* to the state or transaction list consumes some gas. */
|
||||
private byte[] gasLimit;
|
||||
/* An unlimited size byte array specifying
|
||||
* either input [data] of the message call
|
||||
* or the [body] for a new contract */
|
||||
private byte[] data;
|
||||
/* Initialisation code for a new contract */
|
||||
private byte[] init;
|
||||
|
||||
// Signature
|
||||
/* the elliptic curve signature
|
||||
* (including public key recovery bits) */
|
||||
private ECDSASignature signature;
|
||||
|
||||
public Transaction(RLPList rawData) {
|
||||
|
@ -48,7 +62,7 @@ public class Transaction {
|
|||
this.value = value;
|
||||
this.receiveAddress = recieveAddress;
|
||||
this.gasPrice = gasPrice;
|
||||
this.gas = gas;
|
||||
this.gasLimit = gas;
|
||||
this.data = data;
|
||||
this.signature = ECDSASignature.fromComponents(r, s, v);
|
||||
parsed = true;
|
||||
|
@ -61,7 +75,7 @@ public class Transaction {
|
|||
this.value = ((RLPItem) rawData.getElement(1)).getData();
|
||||
this.receiveAddress = ((RLPItem) rawData.getElement(2)).getData();
|
||||
this.gasPrice = ((RLPItem) rawData.getElement(3)).getData();
|
||||
this.gas = ((RLPItem) rawData.getElement(4)).getData();
|
||||
this.gasLimit = ((RLPItem) rawData.getElement(4)).getData();
|
||||
this.data = ((RLPItem) rawData.getElement(5)).getData();
|
||||
|
||||
if (rawData.size() == 9){ // Simple transaction
|
||||
|
@ -113,9 +127,9 @@ public class Transaction {
|
|||
return gasPrice;
|
||||
}
|
||||
|
||||
public byte[] getGas() {
|
||||
public byte[] getGasLimit() {
|
||||
if (!parsed) rlpParse();
|
||||
return gas;
|
||||
return gasLimit;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
|
@ -141,7 +155,7 @@ public class Transaction {
|
|||
", value=" + Utils.toHexString(value) +
|
||||
", receiveAddress=" + Utils.toHexString(receiveAddress) +
|
||||
", gasPrice=" + Utils.toHexString(gasPrice) +
|
||||
", gas=" + Utils.toHexString(gas) +
|
||||
", gas=" + Utils.toHexString(gasLimit) +
|
||||
", data=" + Utils.toHexString(data) +
|
||||
", init=" + Utils.toHexString(init) +
|
||||
", signatureV=" + signature.v +
|
||||
|
|
|
@ -214,7 +214,7 @@ public class MessagesTest {
|
|||
Utils.toHexString( tx.getGasPrice() ).toUpperCase());
|
||||
|
||||
assertEquals("64",
|
||||
Utils.toHexString( tx.getGas() ).toUpperCase());
|
||||
Utils.toHexString( tx.getGasLimit() ).toUpperCase());
|
||||
|
||||
assertEquals("NULL",
|
||||
Utils.toHexString( tx.getData() ).toUpperCase());
|
||||
|
@ -265,7 +265,7 @@ public class MessagesTest {
|
|||
Utils.toHexString( tx.getGasPrice() ).toUpperCase());
|
||||
|
||||
assertEquals("2710",
|
||||
Utils.toHexString( tx.getGas() ).toUpperCase());
|
||||
Utils.toHexString( tx.getGasLimit() ).toUpperCase());
|
||||
|
||||
assertEquals("606956330C0D630000003359366000530A0D630000003359602060005301356000533557604060005301600054630000000C58",
|
||||
Utils.toHexString( tx.getData() ).toUpperCase());
|
||||
|
@ -300,7 +300,7 @@ public class MessagesTest {
|
|||
Utils.toHexString( tx.getGasPrice() ).toUpperCase());
|
||||
|
||||
assertEquals("2710",
|
||||
Utils.toHexString( tx.getGas() ).toUpperCase());
|
||||
Utils.toHexString( tx.getGasLimit() ).toUpperCase());
|
||||
|
||||
assertEquals("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000002D0ACEEE7E5AB874E22CCF8D1A649F59106D74E8",
|
||||
Utils.toHexString( tx.getData() ).toUpperCase());
|
||||
|
@ -354,7 +354,7 @@ public class MessagesTest {
|
|||
Utils.toHexString(block.getStateHash()).toUpperCase());
|
||||
|
||||
assertEquals("1DCC4DE8DEC75D7AAB85B567B6CCD41AD312451B948A7413F0A142FD40D49347",
|
||||
Utils.toHexString(block.getTxListHash()).toUpperCase());
|
||||
Utils.toHexString(block.getTxTrieHash()).toUpperCase());
|
||||
|
||||
assertEquals("02471A26", Utils.toHexString(block.getDifficulty()).toUpperCase());
|
||||
assertEquals(1398260220, block.getTimestamp());
|
||||
|
@ -399,7 +399,7 @@ public class MessagesTest {
|
|||
Utils.toHexString(block.getStateHash()).toUpperCase());
|
||||
|
||||
assertEquals("9BFE4817D274EA3EB8672E9FE848C3885B53BBBD1D7C26E6039F90FB96B942B0",
|
||||
Utils.toHexString(block.getTxListHash()).toUpperCase());
|
||||
Utils.toHexString(block.getTxTrieHash()).toUpperCase());
|
||||
|
||||
assertEquals("3FF000", Utils.toHexString(block.getDifficulty()).toUpperCase());
|
||||
assertEquals(1396643511, block.getTimestamp());
|
||||
|
|
Loading…
Reference in New Issue