Skip to content

Commit

Permalink
Eth63 started. Response answers handling only. Receipts fully handled…
Browse files Browse the repository at this point in the history
…, NodeData only for stateRoots.
  • Loading branch information
zilm13 committed Oct 3, 2016
1 parent 74b9996 commit 059c341
Show file tree
Hide file tree
Showing 14 changed files with 671 additions and 16 deletions.
Expand Up @@ -78,6 +78,22 @@ public TransactionReceipt(byte[] postTxState, byte[] cumulativeGas,
this.logInfoList = logInfoList;
}

public TransactionReceipt(final RLPList rlpList) {
if (rlpList == null || rlpList.size() != 4)
throw new RuntimeException("Should provide RLPList with postTxState, cumulativeGas, bloomFilter, logInfoList");

this.postTxState = rlpList.get(0).getRLPData();
this.cumulativeGas = rlpList.get(1).getRLPData();
this.bloomFilter = new Bloom(rlpList.get(2).getRLPData());

List<LogInfo> logInfos = new ArrayList<>();
for (RLPElement logInfoEl: (RLPList) rlpList.get(3)) {
LogInfo logInfo = new LogInfo(logInfoEl.getRLPData());
logInfos.add(logInfo);
}
this.logInfoList = logInfos;
}

public byte[] getPostTxState() {
return postTxState;
}
Expand Down Expand Up @@ -138,7 +154,7 @@ public byte[] getEncoded() {
return rlpEncoded;
}

private byte[] getEncoded(boolean receiptTrie) {
public byte[] getEncoded(boolean receiptTrie) {

byte[] postTxStateRLP = RLP.encodeElement(this.postTxState);
byte[] cumulativeGasRLP = RLP.encodeElement(this.cumulativeGas);
Expand Down
19 changes: 19 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/db/RepositoryImpl.java
Expand Up @@ -16,6 +16,8 @@
import org.ethereum.trie.JournalPruneDataSource;
import org.ethereum.trie.SecureTrie;
import org.ethereum.trie.Trie;
import org.ethereum.trie.TrieImpl;
import org.ethereum.util.Value;
import org.ethereum.vm.DataWord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -614,6 +616,23 @@ public synchronized void loadAccount(byte[] addr,
cacheDetails.put(wrappedAddress, details);
}

/**
* Returns stateRoot raw Value
* @param stateRoot State root (hash)
* @return Value of state root
*/
public synchronized Value getState(final byte[] stateRoot) {
rwLock.readLock().lock();
try {
Value result = null;
result = ((TrieImpl) worldState).getCache().get(stateRoot);

return result;
} finally {
rwLock.readLock().unlock();
}
}

@Override
public synchronized byte[] getRoot() {
return worldState.getRootHash();
Expand Down
Expand Up @@ -11,10 +11,11 @@
*/
public enum EthVersion {

V62((byte) 62);
V62((byte) 62),
V63((byte) 63);

public static final byte LOWER = V62.getCode();
public static final byte UPPER = V62.getCode();
public static final byte UPPER = V63.getCode();

private byte code;

Expand Down
Expand Up @@ -47,8 +47,8 @@ public class Eth62 extends EthHandler {

protected static final int MAX_HASHES_TO_SEND = 65536;

private final static Logger logger = LoggerFactory.getLogger("sync");
private final static Logger loggerNet = LoggerFactory.getLogger("net");
protected final static Logger logger = LoggerFactory.getLogger("sync");
protected final static Logger loggerNet = LoggerFactory.getLogger("net");

@Autowired
protected BlockStore blockstore;
Expand Down Expand Up @@ -87,14 +87,25 @@ public class Eth62 extends EthHandler {

private Map<Long, byte[]> blockHashCheck;

private static final EthVersion version = V62;

public Eth62() {
super(V62);
this(version);
}

Eth62(final EthVersion version) {
super(version);
}

@Autowired
public Eth62(final SystemProperties config, final Blockchain blockchain,
final CompositeEthereumListener ethereumListener) {
super(V62, config, blockchain, ethereumListener);
this(version, config, blockchain, ethereumListener);
}

Eth62(final EthVersion version, final SystemProperties config,
final Blockchain blockchain, final CompositeEthereumListener ethereumListener) {
super(version, config, blockchain, ethereumListener);
maxHashesAsk = config.maxHashesAsk();
}

Expand Down Expand Up @@ -139,7 +150,7 @@ public void channelRead0(final ChannelHandlerContext ctx, EthMessage msg) throws

@Override
public synchronized void sendStatus() {
byte protocolVersion = version.getCode();
byte protocolVersion = getVersion().getCode();
int networkId = config.networkId();

BigInteger totalDifficulty = blockchain.getTotalDifficulty();
Expand Down Expand Up @@ -245,7 +256,7 @@ protected synchronized void processStatus(StatusMessage msg, ChannelHandlerConte
try {

if (!Arrays.equals(msg.getGenesisHash(), config.getGenesis().getHash())
|| msg.getProtocolVersion() != version.getCode()) {
|| msg.getProtocolVersion() != getVersion().getCode()) {
if (!peerDiscoveryMode) {
loggerNet.info("Removing EthHandler for {} due to protocol incompatibility", ctx.channel().remoteAddress());
}
Expand Down Expand Up @@ -570,11 +581,6 @@ public SyncStatistics getStats() {
return syncStats;
}

@Override
public EthVersion getVersion() {
return version;
}

@Override
public void onSyncDone(boolean done) {
syncDone = done;
Expand Down Expand Up @@ -769,7 +775,7 @@ public String getSyncStats() {

return String.format(
"Peer %s: [ %s, %16s, ping %6s ms, difficulty %s, best block %s ]",
version,
getVersion(),
channel.getPeerIdShort(),
syncState,
(int)channel.getPeerStats().getAvgLatency(),
Expand Down
116 changes: 116 additions & 0 deletions ethereumj-core/src/main/java/org/ethereum/net/eth/handler/Eth63.java
@@ -0,0 +1,116 @@
package org.ethereum.net.eth.handler;

import io.netty.channel.ChannelHandlerContext;
import org.ethereum.config.SystemProperties;
import org.ethereum.core.Block;
import org.ethereum.core.Blockchain;
import org.ethereum.core.Transaction;
import org.ethereum.core.TransactionInfo;
import org.ethereum.core.TransactionReceipt;
import org.ethereum.db.RepositoryImpl;
import org.ethereum.listener.CompositeEthereumListener;
import org.ethereum.net.eth.EthVersion;
import org.ethereum.net.eth.message.EthMessage;
import org.ethereum.net.eth.message.GetNodeDataMessage;
import org.ethereum.net.eth.message.GetReceiptsMessage;
import org.ethereum.net.eth.message.NodeDataMessage;
import org.ethereum.net.eth.message.ReceiptsMessage;

import org.ethereum.util.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static org.ethereum.crypto.HashUtil.sha3;
import static org.ethereum.net.eth.EthVersion.V63;

/**
* Fast synchronization (PV63) Handler
*/
@Component
@Scope("prototype")
public class Eth63 extends Eth62 {

@Autowired
private RepositoryImpl repository;

private static final EthVersion version = V63;

public Eth63() {
super(version);
}

@Autowired
public Eth63(final SystemProperties config, final Blockchain blockchain,
final CompositeEthereumListener ethereumListener) {
super(version, config, blockchain, ethereumListener);
}

@Override
public void channelRead0(final ChannelHandlerContext ctx, EthMessage msg) throws InterruptedException {

super.channelRead0(ctx, msg);

// Only commands that were added in V63, V62 are handled in child
switch (msg.getCommand()) {
case GET_NODE_DATA:
processGetNodeData((GetNodeDataMessage) msg);
break;
case NODE_DATA:
// TODO: Implement
break;
case GET_RECEIPTS:
processGetReceipts((GetReceiptsMessage) msg);
break;
case RECEIPTS:
// TODO: Implement
break;
default:
break;
}
}

protected synchronized void processGetNodeData(GetNodeDataMessage msg) {

if (logger.isTraceEnabled()) logger.trace(
"Peer {}: processing GetNodeData, size [{}]",
channel.getPeerIdShort(),
msg.getStateRoots().size()
);

List<Value> states = new ArrayList<>();
for (byte[] stateRoot : msg.getStateRoots()) {
Value value = repository.getState(stateRoot);
if (value != null) states.add(value);
}

sendMessage(new NodeDataMessage(states));
}

protected synchronized void processGetReceipts(GetReceiptsMessage msg) {

if (logger.isTraceEnabled()) logger.trace(
"Peer {}: processing GetReceipts, size [{}]",
channel.getPeerIdShort(),
msg.getBlockHashes().size()
);

List<List<TransactionReceipt>> receipts = new ArrayList<>();
for (byte[] blockHash : msg.getBlockHashes()) {
Block block = blockchain.getBlockByHash(blockHash);
if (block == null) continue;

List<TransactionReceipt> blockReceipts = new ArrayList<>();
for (Transaction transaction : block.getTransactionsList()) {
TransactionInfo transactionInfo = blockchain.getTransactionInfo(transaction.getHash());
blockReceipts.add(transactionInfo.getReceipt());
}
receipts.add(blockReceipts);
};

sendMessage(new ReceiptsMessage(receipts));
}
}
Expand Up @@ -128,4 +128,9 @@ public void setPeerDiscoveryMode(boolean peerDiscoveryMode) {
public void setChannel(Channel channel) {
this.channel = channel;
}

@Override
public EthVersion getVersion() {
return version;
}
}
Expand Up @@ -21,6 +21,7 @@ public class EthHandlerFactoryImpl implements EthHandlerFactory {
public EthHandler create(EthVersion version) {
switch (version) {
case V62: return ctx.getBean(Eth62.class);
case V63: return ctx.getBean(Eth63.class);
default: throw new IllegalArgumentException("Eth " + version + " is not supported");
}
}
Expand Down
@@ -0,0 +1,46 @@
package org.ethereum.net.eth.message;

import org.ethereum.net.message.Message;
import org.ethereum.net.message.MessageFactory;

import static org.ethereum.net.eth.EthVersion.V63;

/**
* Fast synchronization (PV63) message factory
*/
public class Eth63MessageFactory implements MessageFactory {

@Override
public Message create(byte code, byte[] encoded) {

EthMessageCodes receivedCommand = EthMessageCodes.fromByte(code, V63);
switch (receivedCommand) {
case STATUS:
return new StatusMessage(encoded);
case NEW_BLOCK_HASHES:
return new NewBlockHashesMessage(encoded);
case TRANSACTIONS:
return new TransactionsMessage(encoded);
case GET_BLOCK_HEADERS:
return new GetBlockHeadersMessage(encoded);
case BLOCK_HEADERS:
return new BlockHeadersMessage(encoded);
case GET_BLOCK_BODIES:
return new GetBlockBodiesMessage(encoded);
case BLOCK_BODIES:
return new BlockBodiesMessage(encoded);
case NEW_BLOCK:
return new NewBlockMessage(encoded);
case GET_NODE_DATA:
return new GetNodeDataMessage(encoded);
case NODE_DATA:
return new NodeDataMessage(encoded);
case GET_RECEIPTS:
return new GetReceiptsMessage(encoded);
case RECEIPTS:
return new ReceiptsMessage(encoded);
default:
throw new IllegalArgumentException("No such message");
}
}
}

0 comments on commit 059c341

Please sign in to comment.