saving TransactionReceipt, bumping eth:48
This commit is contained in:
parent
254c51704a
commit
d804cbb722
|
@ -114,6 +114,12 @@ public class BlockchainImpl implements Blockchain {
|
||||||
return blockStore.getBlockByNumber(blockNr);
|
return blockStore.getBlockByNumber(blockNr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TransactionReceipt getTransactionReceiptByHash(byte[] hash){
|
||||||
|
|
||||||
|
return blockStore.getTransactionReceiptByHash(hash);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Block getBlockByHash(byte[] hash){
|
public Block getBlockByHash(byte[] hash){
|
||||||
return blockStore.getBlockByHash(hash);
|
return blockStore.getBlockByHash(hash);
|
||||||
|
@ -210,13 +216,14 @@ public class BlockchainImpl implements Blockchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.processBlock(block);
|
this.processBlock(block);
|
||||||
track.commit();
|
|
||||||
repository.flush(); // saving to the disc
|
|
||||||
|
|
||||||
stateLogger.info("applied reward for block: [{}] \n state: [{}]",
|
stateLogger.info("applied reward for block: [{}] \n state: [{}]",
|
||||||
block.getNumber(),
|
block.getNumber(),
|
||||||
Hex.toHexString(repository.getRoot()));
|
Hex.toHexString(repository.getRoot()));
|
||||||
|
|
||||||
|
track.commit();
|
||||||
|
repository.flush(); // saving to the disc
|
||||||
|
|
||||||
|
|
||||||
// Remove all wallet transactions as they already approved by the net
|
// Remove all wallet transactions as they already approved by the net
|
||||||
worldManager.getWallet().removeTransactions(block.getTransactionsList());
|
worldManager.getWallet().removeTransactions(block.getTransactionsList());
|
||||||
|
|
||||||
|
@ -304,45 +311,52 @@ public class BlockchainImpl implements Blockchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processBlock(Block block) {
|
private void processBlock(Block block) {
|
||||||
|
|
||||||
|
List<TransactionReceipt> receipts = new ArrayList<>();
|
||||||
if(isValid(block)) {
|
if(isValid(block)) {
|
||||||
if (!block.isGenesis()) {
|
if (!block.isGenesis()) {
|
||||||
if (!CONFIG.blockChainOnly()) {
|
if (!CONFIG.blockChainOnly()) {
|
||||||
Wallet wallet = worldManager.getWallet();
|
Wallet wallet = worldManager.getWallet();
|
||||||
wallet.addTransactions(block.getTransactionsList());
|
wallet.addTransactions(block.getTransactionsList());
|
||||||
this.applyBlock(block);
|
receipts = this.applyBlock(block);
|
||||||
wallet.processBlock(block);
|
wallet.processBlock(block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.storeBlock(block);
|
this.storeBlock(block, receipts);
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Invalid block with nr: {}", block.getNumber());
|
logger.warn("Invalid block with nr: {}", block.getNumber());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyBlock(Block block) {
|
private List<TransactionReceipt> applyBlock(Block block) {
|
||||||
|
|
||||||
int i = 0;
|
int i = 1;
|
||||||
long totalGasUsed = 0;
|
long totalGasUsed = 0;
|
||||||
|
List<TransactionReceipt> reciepts = new ArrayList<>();
|
||||||
|
|
||||||
for (Transaction tx : block.getTransactionsList()) {
|
for (Transaction tx : block.getTransactionsList()) {
|
||||||
stateLogger.info("apply block: [{}] tx: [{}] ", block.getNumber(), i);
|
stateLogger.info("apply block: [{}] tx: [{}] ", block.getNumber(), i);
|
||||||
|
|
||||||
TransactionReceipt receipt = applyTransaction(block, tx);
|
TransactionReceipt receipt = applyTransaction(block, tx);
|
||||||
totalGasUsed += receipt.getCumulativeGasLong();
|
totalGasUsed += receipt.getCumulativeGasLong();
|
||||||
receipt.setCumulativeGas(totalGasUsed);
|
|
||||||
|
|
||||||
track.commit();
|
track.commit();
|
||||||
|
receipt.setCumulativeGas(totalGasUsed);
|
||||||
receipt.setPostTxState(repository.getRoot());
|
receipt.setPostTxState(repository.getRoot());
|
||||||
|
receipt.setTransaction(tx);
|
||||||
|
|
||||||
stateLogger.info("block: [{}] executed tx: [{}] \n state: [{}]", block.getNumber(), i,
|
stateLogger.info("block: [{}] executed tx: [{}] \n state: [{}]", block.getNumber(), i,
|
||||||
Hex.toHexString(repository.getRoot()));
|
Hex.toHexString(repository.getRoot()));
|
||||||
|
|
||||||
|
stateLogger.info("[{}] ", receipt.toString());
|
||||||
|
|
||||||
|
if (stateLogger.isInfoEnabled())
|
||||||
|
stateLogger.info("tx[{}].receipt: [{}] ",i, Hex.toHexString(receipt.getEncoded()));
|
||||||
|
|
||||||
if(block.getNumber() >= CONFIG.traceStartBlock())
|
if(block.getNumber() >= CONFIG.traceStartBlock())
|
||||||
repository.dumpState(block, totalGasUsed, i++, tx.getHash());
|
repository.dumpState(block, totalGasUsed, i++, tx.getHash());
|
||||||
|
|
||||||
// todo: (!!!). save the receipt
|
reciepts.add(receipt);
|
||||||
// todo: cache all the receipts and
|
|
||||||
// todo: save them to the disc together
|
|
||||||
// todo: with the block afterwards
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addReward(block);
|
this.addReward(block);
|
||||||
|
@ -352,6 +366,8 @@ public class BlockchainImpl implements Blockchain {
|
||||||
|
|
||||||
if(block.getNumber() >= CONFIG.traceStartBlock())
|
if(block.getNumber() >= CONFIG.traceStartBlock())
|
||||||
repository.dumpState(block, totalGasUsed, 0, null);
|
repository.dumpState(block, totalGasUsed, 0, null);
|
||||||
|
|
||||||
|
return reciepts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -377,7 +393,7 @@ public class BlockchainImpl implements Blockchain {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void storeBlock(Block block) {
|
public void storeBlock(Block block, List<TransactionReceipt> receipts) {
|
||||||
|
|
||||||
/* Debug check to see if the state is still as expected */
|
/* Debug check to see if the state is still as expected */
|
||||||
if(logger.isWarnEnabled()) {
|
if(logger.isWarnEnabled()) {
|
||||||
|
@ -394,7 +410,7 @@ public class BlockchainImpl implements Blockchain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
blockStore.saveBlock(block);
|
blockStore.saveBlock(block, receipts);
|
||||||
this.setBestBlock(block);
|
this.setBestBlock(block);
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
|
@ -538,18 +554,18 @@ public class BlockchainImpl implements Blockchain {
|
||||||
if (CONFIG.playVM())
|
if (CONFIG.playVM())
|
||||||
vm.play(program);
|
vm.play(program);
|
||||||
|
|
||||||
// todo: recepit save logs
|
|
||||||
// todo: receipt calc and save blooms
|
|
||||||
|
|
||||||
program.saveProgramTraceToFile(Hex.toHexString(tx.getHash()));
|
program.saveProgramTraceToFile(Hex.toHexString(tx.getHash()));
|
||||||
ProgramResult result = program.getResult();
|
ProgramResult result = program.getResult();
|
||||||
applyProgramResult(result, gasDebit, gasPrice, trackTx,
|
applyProgramResult(result, gasDebit, gasPrice, trackTx,
|
||||||
senderAddress, receiverAddress, coinbase, isContractCreation);
|
senderAddress, receiverAddress, coinbase, isContractCreation);
|
||||||
gasUsed = result.getGasUsed();
|
gasUsed = result.getGasUsed();
|
||||||
|
|
||||||
|
List<LogInfo> logs = result.getLogInfoList();
|
||||||
|
receipt.setLogInfoList(logs);
|
||||||
|
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
trackTx.rollback();
|
trackTx.rollback();
|
||||||
|
|
||||||
receipt.setCumulativeGas(tx.getGasLimit());
|
receipt.setCumulativeGas(tx.getGasLimit());
|
||||||
return receipt;
|
return receipt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ public class Bloom {
|
||||||
|
|
||||||
byte[] data = new byte[64];
|
byte[] data = new byte[64];
|
||||||
|
|
||||||
|
public Bloom() {
|
||||||
|
}
|
||||||
|
|
||||||
public Bloom(byte[] data){
|
public Bloom(byte[] data){
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
package org.ethereum.core;
|
package org.ethereum.core;
|
||||||
|
|
||||||
import org.ethereum.util.RLP;
|
import org.ethereum.util.*;
|
||||||
import org.ethereum.vm.LogInfo;
|
import org.ethereum.vm.LogInfo;
|
||||||
import org.spongycastle.util.BigIntegers;
|
import org.spongycastle.util.BigIntegers;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The transaction receipt is a tuple of three items
|
* The transaction receipt is a tuple of three items
|
||||||
* comprising the transaction, together with the post-transaction state,
|
* comprising the transaction, together with the post-transaction state,
|
||||||
|
@ -19,10 +22,12 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class TransactionReceipt {
|
public class TransactionReceipt {
|
||||||
|
|
||||||
private byte[] postTxState;
|
private Transaction transaction;
|
||||||
private byte[] cumulativeGas;
|
|
||||||
private Bloom bloomFilter;
|
private byte[] postTxState = EMPTY_BYTE_ARRAY;
|
||||||
private List<LogInfo> logInfoList;
|
private byte[] cumulativeGas = EMPTY_BYTE_ARRAY;
|
||||||
|
private Bloom bloomFilter = new Bloom();
|
||||||
|
private List<LogInfo> logInfoList = new ArrayList<LogInfo>();
|
||||||
|
|
||||||
/* Tx Receipt in encoded form */
|
/* Tx Receipt in encoded form */
|
||||||
private byte[] rlpEncoded;
|
private byte[] rlpEncoded;
|
||||||
|
@ -30,6 +35,30 @@ public class TransactionReceipt {
|
||||||
public TransactionReceipt() {
|
public TransactionReceipt() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TransactionReceipt(byte[] rlp) {
|
||||||
|
|
||||||
|
RLPList params = RLP.decode2(rlp);
|
||||||
|
RLPList receipt = (RLPList) params.get(0);
|
||||||
|
|
||||||
|
RLPItem postTxStateRLP = (RLPItem) receipt.get(0);
|
||||||
|
RLPItem cumulativeGasRLP = (RLPItem) receipt.get(1);
|
||||||
|
RLPItem bloomRLP = (RLPItem) receipt.get(2);
|
||||||
|
RLPList logs = (RLPList) receipt.get(3);
|
||||||
|
|
||||||
|
postTxState = postTxStateRLP.getRLPData();
|
||||||
|
cumulativeGas = cumulativeGasRLP.getRLPData();
|
||||||
|
bloomFilter = new Bloom(bloomRLP.getRLPData());
|
||||||
|
|
||||||
|
for (int i = 0; i < logs.size(); i++) {
|
||||||
|
RLPElement logRLP = logs.get(i);
|
||||||
|
LogInfo logInfo = new LogInfo(logRLP.getRLPData());
|
||||||
|
logInfoList.add(logInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
rlpEncoded = rlp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public TransactionReceipt(byte[] postTxState, byte[] cumulativeGas,
|
public TransactionReceipt(byte[] postTxState, byte[] cumulativeGas,
|
||||||
Bloom bloomFilter, List<LogInfo> logInfoList) {
|
Bloom bloomFilter, List<LogInfo> logInfoList) {
|
||||||
this.postTxState = postTxState;
|
this.postTxState = postTxState;
|
||||||
|
@ -69,6 +98,8 @@ public class TransactionReceipt {
|
||||||
byte[] cumulativeGasRLP = RLP.encodeElement(this.cumulativeGas);
|
byte[] cumulativeGasRLP = RLP.encodeElement(this.cumulativeGas);
|
||||||
byte[] bloomRLP = RLP.encodeElement(this.bloomFilter.data);
|
byte[] bloomRLP = RLP.encodeElement(this.bloomFilter.data);
|
||||||
|
|
||||||
|
byte[] logInfoListRLP = null;
|
||||||
|
if (logInfoList != null) {
|
||||||
byte[][] logInfoListE = new byte[logInfoList.size()][];
|
byte[][] logInfoListE = new byte[logInfoList.size()][];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
@ -76,7 +107,10 @@ public class TransactionReceipt {
|
||||||
logInfoListE[i] = logInfo.getEncoded() ;
|
logInfoListE[i] = logInfo.getEncoded() ;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
byte[] logInfoListRLP = RLP.encodeList(logInfoListE);
|
logInfoListRLP = RLP.encodeList(logInfoListE);
|
||||||
|
} else{
|
||||||
|
logInfoListRLP = RLP.encodeList();
|
||||||
|
}
|
||||||
|
|
||||||
rlpEncoded = RLP.encodeList(postTxStateRLP, cumulativeGasRLP, bloomRLP, logInfoListRLP);
|
rlpEncoded = RLP.encodeList(postTxStateRLP, cumulativeGasRLP, bloomRLP, logInfoListRLP);
|
||||||
|
|
||||||
|
@ -95,12 +129,23 @@ public class TransactionReceipt {
|
||||||
this.cumulativeGas = cumulativeGas;
|
this.cumulativeGas = cumulativeGas;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBloomFilter(Bloom bloomFilter) {
|
|
||||||
this.bloomFilter = bloomFilter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLogInfoList(List<LogInfo> logInfoList) {
|
public void setLogInfoList(List<LogInfo> logInfoList) {
|
||||||
|
if (logInfoList == null) return;
|
||||||
|
this.rlpEncoded = null;
|
||||||
this.logInfoList = logInfoList;
|
this.logInfoList = logInfoList;
|
||||||
|
|
||||||
|
for (LogInfo loginfo : logInfoList){
|
||||||
|
bloomFilter.or(loginfo.getBloom());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransaction(Transaction transaction){
|
||||||
|
this.transaction = transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Transaction getTransaction(){
|
||||||
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.ethereum.db;
|
package org.ethereum.db;
|
||||||
|
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
|
import org.ethereum.core.TransactionReceipt;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
@ -79,11 +80,20 @@ public class BlockStore {
|
||||||
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void saveBlock(Block block) {
|
public void saveBlock(Block block, List<TransactionReceipt> receipts) {
|
||||||
|
|
||||||
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(),
|
BlockVO blockVO = new BlockVO(block.getNumber(), block.getHash(),
|
||||||
block.getEncoded(), block.getCumulativeDifficulty());
|
block.getEncoded(), block.getCumulativeDifficulty());
|
||||||
|
|
||||||
|
for (TransactionReceipt receipt : receipts){
|
||||||
|
|
||||||
|
byte[] hash = receipt.getTransaction().getHash();
|
||||||
|
byte[] rlp = receipt.getEncoded();
|
||||||
|
|
||||||
|
TransactionReceiptVO transactionReceiptVO = new TransactionReceiptVO(hash, rlp);
|
||||||
|
sessionFactory.getCurrentSession().persist(transactionReceiptVO);
|
||||||
|
}
|
||||||
|
|
||||||
sessionFactory.getCurrentSession().persist(blockVO);
|
sessionFactory.getCurrentSession().persist(blockVO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,4 +142,17 @@ public class BlockStore {
|
||||||
sessionFactory.getCurrentSession().
|
sessionFactory.getCurrentSession().
|
||||||
createQuery("delete from BlockVO").executeUpdate();
|
createQuery("delete from BlockVO").executeUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TransactionReceipt getTransactionReceiptByHash(byte[] hash) {
|
||||||
|
|
||||||
|
List result = sessionFactory.getCurrentSession().
|
||||||
|
createQuery("from TransactionReceiptVO where hash = :hash").
|
||||||
|
setParameter("hash", hash).list();
|
||||||
|
|
||||||
|
if (result.size() == 0) return null;
|
||||||
|
TransactionReceiptVO vo = (TransactionReceiptVO)result.get(0);
|
||||||
|
|
||||||
|
return new TransactionReceipt(vo.rlp);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.ethereum.db;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* www.etherj.com
|
||||||
|
*
|
||||||
|
* @author: Roman Mandeleil
|
||||||
|
* Created on: 14/11/2014 09:59
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Table(name = "transaction_receipt")
|
||||||
|
public class TransactionReceiptVO {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
byte[] hash;
|
||||||
|
|
||||||
|
@Lob
|
||||||
|
byte[] rlp;
|
||||||
|
|
||||||
|
public TransactionReceiptVO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransactionReceiptVO(byte[] hash, byte[] rlp) {
|
||||||
|
this.hash = hash;
|
||||||
|
this.rlp = rlp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getHash() {
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHash(byte[] hash) {
|
||||||
|
this.hash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getRlp() {
|
||||||
|
return rlp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRlp(byte[] rlp) {
|
||||||
|
this.rlp = rlp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.ethereum.core.Block;
|
import org.ethereum.core.Block;
|
||||||
import org.ethereum.core.Chain;
|
import org.ethereum.core.Chain;
|
||||||
|
import org.ethereum.core.TransactionReceipt;
|
||||||
import org.ethereum.db.ByteArrayWrapper;
|
import org.ethereum.db.ByteArrayWrapper;
|
||||||
import org.ethereum.net.BlockQueue;
|
import org.ethereum.net.BlockQueue;
|
||||||
import org.ethereum.core.Genesis;
|
import org.ethereum.core.Genesis;
|
||||||
|
@ -17,7 +18,7 @@ public interface Blockchain {
|
||||||
public long getSize();
|
public long getSize();
|
||||||
public void add(Block block);
|
public void add(Block block);
|
||||||
public void tryToConnect(Block block);
|
public void tryToConnect(Block block);
|
||||||
public void storeBlock(Block block);
|
public void storeBlock(Block block, List<TransactionReceipt> receipts);
|
||||||
public Block getBlockByNumber(long blockNr);
|
public Block getBlockByNumber(long blockNr);
|
||||||
public void setBestBlock(Block block);
|
public void setBestBlock(Block block);
|
||||||
public Block getBestBlock();
|
public Block getBestBlock();
|
||||||
|
@ -30,6 +31,9 @@ public interface Blockchain {
|
||||||
public void setTotalDifficulty(BigInteger totalDifficulty);
|
public void setTotalDifficulty(BigInteger totalDifficulty);
|
||||||
public byte[] getBestBlockHash();
|
public byte[] getBestBlockHash();
|
||||||
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty);
|
public List<byte[]> getListOfHashesStartFrom(byte[] hash, int qty);
|
||||||
|
|
||||||
|
TransactionReceipt getTransactionReceiptByHash(byte[] hash);
|
||||||
|
|
||||||
public Block getBlockByHash(byte[] hash);
|
public Block getBlockByHash(byte[] hash);
|
||||||
public List<Chain> getAltChains();
|
public List<Chain> getAltChains();
|
||||||
public List<Block> getGarbage();
|
public List<Block> getGarbage();
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package org.ethereum.facade;
|
package org.ethereum.facade;
|
||||||
|
|
||||||
import org.ethereum.config.SystemProperties;
|
import org.ethereum.config.SystemProperties;
|
||||||
|
import org.ethereum.net.eth.EthHandler;
|
||||||
|
import org.ethereum.net.shh.ShhHandler;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -99,6 +101,9 @@ public class EthereumFactory {
|
||||||
|
|
||||||
public static Ethereum createEthereum(){
|
public static Ethereum createEthereum(){
|
||||||
|
|
||||||
|
logger.info("capability eth version: [{}]", EthHandler.VERSION);
|
||||||
|
logger.info("capability shh version: [{}]", ShhHandler.VERSION);
|
||||||
|
|
||||||
if (context == null){
|
if (context == null){
|
||||||
context = new AnnotationConfigApplicationContext(EthereumFactory.class);
|
context = new AnnotationConfigApplicationContext(EthereumFactory.class);
|
||||||
factory = context.getBean(EthereumFactory.class);
|
factory = context.getBean(EthereumFactory.class);
|
||||||
|
|
|
@ -19,10 +19,7 @@ import org.springframework.stereotype.Component;
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.ethereum.config.SystemProperties.CONFIG;
|
import static org.ethereum.config.SystemProperties.CONFIG;
|
||||||
|
|
||||||
|
@ -158,7 +155,7 @@ public class WorldManager {
|
||||||
repository.addBalance(Hex.decode(address), Genesis.PREMINE_AMOUNT);
|
repository.addBalance(Hex.decode(address), Genesis.PREMINE_AMOUNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
blockStore.saveBlock(Genesis.getInstance());
|
blockStore.saveBlock(Genesis.getInstance(), new ArrayList<TransactionReceipt>());
|
||||||
|
|
||||||
blockchain.setBestBlock(Genesis.getInstance());
|
blockchain.setBestBlock(Genesis.getInstance());
|
||||||
blockchain.setTotalDifficulty(BigInteger.ZERO);
|
blockchain.setTotalDifficulty(BigInteger.ZERO);
|
||||||
|
|
|
@ -42,7 +42,7 @@ import static org.ethereum.net.message.StaticMessages.GET_TRANSACTIONS_MESSAGE;
|
||||||
@Scope("prototype")
|
@Scope("prototype")
|
||||||
public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
public class EthHandler extends SimpleChannelInboundHandler<EthMessage> {
|
||||||
|
|
||||||
public final static byte VERSION = 47;
|
public final static byte VERSION = 48;
|
||||||
public final static byte NETWORK_ID = 0x0;
|
public final static byte NETWORK_ID = 0x0;
|
||||||
|
|
||||||
private final static Logger logger = LoggerFactory.getLogger("net");
|
private final static Logger logger = LoggerFactory.getLogger("net");
|
||||||
|
|
|
@ -4,6 +4,9 @@ import org.ethereum.core.BlockHeader;
|
||||||
import org.ethereum.core.Bloom;
|
import org.ethereum.core.Bloom;
|
||||||
import org.ethereum.crypto.HashUtil;
|
import org.ethereum.crypto.HashUtil;
|
||||||
import org.ethereum.util.RLP;
|
import org.ethereum.util.RLP;
|
||||||
|
import org.ethereum.util.RLPElement;
|
||||||
|
import org.ethereum.util.RLPItem;
|
||||||
|
import org.ethereum.util.RLPList;
|
||||||
import org.spongycastle.util.encoders.Hex;
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
@ -20,17 +23,38 @@ import java.util.List;
|
||||||
|
|
||||||
public class LogInfo {
|
public class LogInfo {
|
||||||
|
|
||||||
byte[] address;
|
byte[] address = new byte[]{};
|
||||||
List<DataWord> topics = new ArrayList<DataWord>();
|
List<DataWord> topics = new ArrayList<DataWord>();
|
||||||
byte[] data;
|
byte[] data = new byte[]{};
|
||||||
|
|
||||||
/* Log info in encoded form */
|
/* Log info in encoded form */
|
||||||
private byte[] rlpEncoded;
|
private byte[] rlpEncoded;
|
||||||
|
|
||||||
|
public LogInfo(byte[] rlp){
|
||||||
|
|
||||||
|
RLPList params = RLP.decode2(rlp);
|
||||||
|
RLPList logInfo = (RLPList) params.get(0);
|
||||||
|
|
||||||
|
RLPItem address = (RLPItem)logInfo.get(0);
|
||||||
|
RLPList topics = (RLPList)logInfo.get(1);
|
||||||
|
RLPItem data = (RLPItem)logInfo.get(2);
|
||||||
|
|
||||||
|
this.address = address.getRLPData() != null ? address.getRLPData() : new byte[]{};
|
||||||
|
this.data = data.getRLPData() != null ? data.getRLPData() : new byte[]{};
|
||||||
|
|
||||||
|
for (int i = 0; i < topics.size(); ++i){
|
||||||
|
|
||||||
|
byte[] topic = topics.get(i).getRLPData();
|
||||||
|
this.topics.add(new DataWord(topic));
|
||||||
|
}
|
||||||
|
|
||||||
|
rlpEncoded = rlp;
|
||||||
|
}
|
||||||
|
|
||||||
public LogInfo(byte[] address, List<DataWord> topics, byte[] data) {
|
public LogInfo(byte[] address, List<DataWord> topics, byte[] data) {
|
||||||
this.address = address;
|
this.address = (address != null) ? address : new byte[]{} ;
|
||||||
this.topics = (topics == null) ? new ArrayList<DataWord>() : topics;
|
this.topics = (topics != null) ? topics : new ArrayList<DataWord>();
|
||||||
this.data = data;
|
this.data = (data != null) ? data : new byte[]{} ;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getAddress() {
|
public byte[] getAddress() {
|
||||||
|
@ -48,7 +72,6 @@ public class LogInfo {
|
||||||
/* [address, [topic, topic ...] data] */
|
/* [address, [topic, topic ...] data] */
|
||||||
public byte[] getEncoded() {
|
public byte[] getEncoded() {
|
||||||
|
|
||||||
|
|
||||||
byte[] addressEncoded = RLP.encodeElement(this.address);
|
byte[] addressEncoded = RLP.encodeElement(this.address);
|
||||||
|
|
||||||
byte[][] topicsEncoded = null;
|
byte[][] topicsEncoded = null;
|
||||||
|
@ -57,7 +80,7 @@ public class LogInfo {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for( DataWord topic : topics ){
|
for( DataWord topic : topics ){
|
||||||
byte[] topicData = topic.getData();
|
byte[] topicData = topic.getData();
|
||||||
topicsEncoded[i] = topicData;
|
topicsEncoded[i] = RLP.encodeElement(topicData);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +95,6 @@ public class LogInfo {
|
||||||
byte[] topicData = topic.getData();
|
byte[] topicData = topic.getData();
|
||||||
ret.or(Bloom.create(HashUtil.sha3(topicData)));
|
ret.or(Bloom.create(HashUtil.sha3(topicData)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package test.ethereum.core;
|
||||||
|
|
||||||
|
import org.ethereum.vm.LogInfo;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* www.etherj.com
|
||||||
|
*
|
||||||
|
* @author: Roman Mandeleil
|
||||||
|
* Created on: 05/12/2014 16:26
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class LogInfoTest {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger("test");
|
||||||
|
|
||||||
|
@Test // rlp decode
|
||||||
|
public void test_1(){
|
||||||
|
|
||||||
|
// LogInfo{address=d5ccd26ba09ce1d85148b5081fa3ed77949417be, topics=[000000000000000000000000459d3a7595df9eba241365f4676803586d7d199c 436f696e73000000000000000000000000000000000000000000000000000000 ], data=}
|
||||||
|
byte[] rlp = Hex.decode("f85a94d5ccd26ba09ce1d85148b5081fa3ed77949417bef842a0000000000000000000000000459d3a7595df9eba241365f4676803586d7d199ca0436f696e7300000000000000000000000000000000000000000000000000000080");
|
||||||
|
LogInfo logInfo = new LogInfo(rlp);
|
||||||
|
|
||||||
|
assertEquals("d5ccd26ba09ce1d85148b5081fa3ed77949417be",
|
||||||
|
Hex.toHexString(logInfo.getAddress()));
|
||||||
|
assertEquals("", Hex.toHexString(logInfo.getData()));
|
||||||
|
|
||||||
|
assertEquals("000000000000000000000000459d3a7595df9eba241365f4676803586d7d199c",
|
||||||
|
logInfo.getTopics().get(0).toString());
|
||||||
|
assertEquals("436f696e73000000000000000000000000000000000000000000000000000000",
|
||||||
|
logInfo.getTopics().get(1).toString());
|
||||||
|
|
||||||
|
logger.info("{}", logInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test // rlp decode
|
||||||
|
public void test_2(){
|
||||||
|
|
||||||
|
LogInfo log = new LogInfo(Hex.decode("d5ccd26ba09ce1d85148b5081fa3ed77949417be"), null, null);
|
||||||
|
assertEquals("d794d5ccd26ba09ce1d85148b5081fa3ed77949417bec080", Hex.toHexString(log.getEncoded()));
|
||||||
|
|
||||||
|
logger.info("{}", log);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package test.ethereum.core;
|
||||||
|
|
||||||
|
import org.ethereum.core.TransactionReceipt;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* www.etherj.com
|
||||||
|
*
|
||||||
|
* @author: Roman Mandeleil
|
||||||
|
* Created on: 05/12/2014 16:26
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TransactionReceiptTest {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger("test");
|
||||||
|
|
||||||
|
|
||||||
|
@Test // rlp decode
|
||||||
|
public void test_1(){
|
||||||
|
|
||||||
|
byte[] rlp = Hex.decode("f8c4a0966265cc49fa1f10f0445f035258d116563931022a3570a640af5d73a214a8da822b6fb84000000010000000010000000000008000000000000000000000000000000000000000000000000000000000020000000000000014000000000400000000000440f85cf85a94d5ccd26ba09ce1d85148b5081fa3ed77949417bef842a0000000000000000000000000459d3a7595df9eba241365f4676803586d7d199ca0436f696e7300000000000000000000000000000000000000000000000000000080");
|
||||||
|
TransactionReceipt txReceipt = new TransactionReceipt(rlp);
|
||||||
|
|
||||||
|
assertEquals(1, txReceipt.getLogInfoList().size());
|
||||||
|
|
||||||
|
assertEquals("966265cc49fa1f10f0445f035258d116563931022a3570a640af5d73a214a8da",
|
||||||
|
Hex.toHexString(txReceipt.getPostTxState()));
|
||||||
|
|
||||||
|
assertEquals("2b6f",
|
||||||
|
Hex.toHexString(txReceipt.getCumulativeGas()));
|
||||||
|
|
||||||
|
assertEquals("00000010000000010000000000008000000000000000000000000000000000000000000000000000000000020000000000000014000000000400000000000440",
|
||||||
|
Hex.toHexString(txReceipt.getBloomFilter().getData()));
|
||||||
|
|
||||||
|
logger.info("{}", txReceipt);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue