Initial commit poc6 protocol update
This commit is contained in:
parent
040129799c
commit
a256c12a62
|
@ -40,11 +40,11 @@ public class Block {
|
|||
private BlockHeader header;
|
||||
|
||||
/* Transactions */
|
||||
private List<TransactionReceipt> txReceiptList = new CopyOnWriteArrayList<TransactionReceipt>() ;
|
||||
private List<Transaction> transactionsList = new CopyOnWriteArrayList<Transaction>();
|
||||
private List<TransactionReceipt> txReceiptList = new CopyOnWriteArrayList<>() ;
|
||||
private List<Transaction> transactionsList = new CopyOnWriteArrayList<>();
|
||||
|
||||
/* Uncles */
|
||||
private List<BlockHeader> uncleList = new CopyOnWriteArrayList<BlockHeader>();
|
||||
private List<BlockHeader> uncleList = new CopyOnWriteArrayList<>();
|
||||
|
||||
/* Private */
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.ethereum.net;
|
||||
package org.ethereum.core;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -26,9 +25,7 @@ public class BlockQueue {
|
|||
private Timer timer = new Timer("BlockQueueTimer");
|
||||
|
||||
public BlockQueue() {
|
||||
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
public void run() {
|
||||
nudgeQueue();
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import org.ethereum.facade.Blockchain;
|
|||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.listener.EthereumListener;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.net.BlockQueue;
|
||||
import org.ethereum.util.AdvancedDeviceUtils;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.vm.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -59,6 +59,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
|
||||
private Repository repository;
|
||||
private Block lastBlock;
|
||||
private BigInteger totalDifficulty;
|
||||
|
||||
// keep the index of the chain for
|
||||
// convenient usage, <block_number, block_hash>
|
||||
|
@ -70,11 +71,13 @@ public class BlockchainImpl implements Blockchain {
|
|||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getGasPrice() {
|
||||
// In case of the genesis block we don't want to rely on the min gas price
|
||||
return lastBlock.isGenesis() ? lastBlock.getMinGasPrice() : INITIAL_MIN_GAS_PRICE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getLatestBlockHash() {
|
||||
if (blockCache.isEmpty())
|
||||
return Genesis.getInstance().getHash();
|
||||
|
@ -82,14 +85,17 @@ public class BlockchainImpl implements Blockchain {
|
|||
return getLastBlock().getHash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return blockCache.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getBlockByNumber(long blockNr) {
|
||||
return repository.getBlock(blockNr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Block block) {
|
||||
|
||||
if (block == null)
|
||||
|
@ -127,7 +133,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
ethereumListener.onBlock(block);
|
||||
}
|
||||
|
||||
public void processBlock(Block block) {
|
||||
private void processBlock(Block block) {
|
||||
if(block.isValid()) {
|
||||
if (!block.isGenesis()) {
|
||||
if (!CONFIG.blockChainOnly()) {
|
||||
|
@ -142,7 +148,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
}
|
||||
}
|
||||
|
||||
public void applyBlock(Block block) {
|
||||
private void applyBlock(Block block) {
|
||||
|
||||
int i = 0;
|
||||
long totalGasUsed = 0;
|
||||
|
@ -160,11 +166,19 @@ public class BlockchainImpl implements Blockchain {
|
|||
}
|
||||
|
||||
this.addReward(block);
|
||||
this.increaseTotalDifficulty(block);
|
||||
|
||||
if(block.getNumber() >= CONFIG.traceStartBlock())
|
||||
repository.dumpState(block, totalGasUsed, 0, null);
|
||||
}
|
||||
|
||||
private void increaseTotalDifficulty(Block block) {
|
||||
totalDifficulty.add(new BigInteger(block.getDifficulty()));
|
||||
for (BlockHeader uncleHeader : block.getUncleList()) {
|
||||
totalDifficulty.add(new BigInteger(uncleHeader.getDifficulty()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add reward to block- and every uncle coinbase
|
||||
* assuming the entire block is valid.
|
||||
|
@ -190,6 +204,7 @@ public class BlockchainImpl implements Blockchain {
|
|||
repository.addBalance(block.getCoinbase(), totalBlockReward);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void storeBlock(Block block) {
|
||||
|
||||
/* Debug check to see if the state is still as expected */
|
||||
|
@ -433,23 +448,33 @@ public class BlockchainImpl implements Blockchain {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockQueue getBlockQueue() {
|
||||
return blockQueue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Long, byte[]> getBlockCache() {
|
||||
return this.blockCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getLastBlock() {
|
||||
return lastBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastBlock(Block block) {
|
||||
this.lastBlock = block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close(){
|
||||
blockQueue.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getTotalDifficulty() {
|
||||
return ByteUtil.bigIntegerToBytes(totalDifficulty);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public class DatabaseImpl implements Database {
|
|||
|
||||
public List<ByteArrayWrapper> dumpKeys() {
|
||||
DBIterator iterator = getDb().iterator();
|
||||
ArrayList<ByteArrayWrapper> keys = new ArrayList<ByteArrayWrapper>();
|
||||
ArrayList<ByteArrayWrapper> keys = new ArrayList<>();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
ByteArrayWrapper key = new ByteArrayWrapper(iterator.next().getKey());
|
||||
|
|
|
@ -3,9 +3,9 @@ package org.ethereum.db;
|
|||
import org.codehaus.plexus.util.FileUtils;
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.BlockchainImpl;
|
||||
import org.ethereum.core.Genesis;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.facade.Blockchain;
|
||||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.json.EtherObjectMapper;
|
||||
import org.ethereum.json.JSONHelper;
|
||||
|
@ -128,8 +128,8 @@ public class RepositoryImpl implements Repository {
|
|||
this.worldState.sync();
|
||||
}
|
||||
|
||||
public BlockchainImpl loadBlockchain() {
|
||||
BlockchainImpl blockchain = WorldManager.getInstance().getBlockchain();
|
||||
public Blockchain loadBlockchain() {
|
||||
Blockchain blockchain = WorldManager.getInstance().getBlockchain();
|
||||
DBIterator iterator = chainDB.iterator();
|
||||
try {
|
||||
if (!iterator.hasNext()) {
|
||||
|
@ -161,8 +161,7 @@ public class RepositoryImpl implements Repository {
|
|||
}
|
||||
logger.debug("Block #{} -> {}", block.getNumber(), block.toFlatString());
|
||||
}
|
||||
logger.info(
|
||||
"*** Loaded up to block [ {} ] with stateRoot [ {} ]",
|
||||
logger.info("*** Loaded up to block [{}] with stateRoot [{}]",
|
||||
blockchain.getLastBlock().getNumber(),
|
||||
Hex.toHexString(blockchain.getLastBlock().getStateRoot()));
|
||||
}
|
||||
|
|
|
@ -1,11 +1,22 @@
|
|||
package org.ethereum.facade;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.BlockQueue;
|
||||
|
||||
public interface Blockchain {
|
||||
|
||||
public int getSize();
|
||||
public void add(Block block);
|
||||
public void storeBlock(Block block);
|
||||
public Map<Long, byte[]> getBlockCache();
|
||||
public Block getBlockByNumber(long blockNr);
|
||||
public long getGasPrice();
|
||||
public void setLastBlock(Block block);
|
||||
public Block getLastBlock();
|
||||
public BlockQueue getBlockQueue();
|
||||
public void close();
|
||||
public byte[] getTotalDifficulty();
|
||||
public byte[] getLatestBlockHash();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import org.ethereum.core.Wallet;
|
|||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.listener.EthereumListener;
|
||||
import org.ethereum.net.client.ClientPeer;
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Set;
|
||||
|
@ -25,7 +25,7 @@ public interface Ethereum {
|
|||
* @param excludePeer - peer to exclude
|
||||
* @return online peer if available otherwise null
|
||||
*/
|
||||
public PeerData findOnlinePeer(PeerData excludePeer) ;
|
||||
public Peer findOnlinePeer(Peer excludePeer) ;
|
||||
|
||||
/**
|
||||
* Find an online peer but not from excluded list
|
||||
|
@ -33,12 +33,12 @@ public interface Ethereum {
|
|||
* @param excludePeerSet - peers to exclude
|
||||
* @return online peer if available otherwise null
|
||||
*/
|
||||
public PeerData findOnlinePeer(Set<PeerData> excludePeerSet) ;
|
||||
public Peer findOnlinePeer(Set<Peer> excludePeerSet) ;
|
||||
|
||||
/**
|
||||
* @return online peer if available
|
||||
*/
|
||||
public PeerData findOnlinePeer();
|
||||
public Peer findOnlinePeer();
|
||||
|
||||
|
||||
/**
|
||||
|
@ -46,7 +46,7 @@ public interface Ethereum {
|
|||
*
|
||||
* @return online peer.
|
||||
*/
|
||||
public PeerData waitForOnlinePeer();
|
||||
public Peer waitForOnlinePeer();
|
||||
|
||||
/*
|
||||
*
|
||||
|
@ -59,7 +59,7 @@ public interface Ethereum {
|
|||
* }
|
||||
*
|
||||
*/
|
||||
public Set<PeerData> getPeers();
|
||||
public Set<Peer> getPeers();
|
||||
|
||||
public void startPeerDiscovery();
|
||||
public void stopPeerDiscovery();
|
||||
|
|
|
@ -10,7 +10,7 @@ import org.ethereum.core.Wallet;
|
|||
import org.ethereum.listener.EthereumListener;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.net.client.ClientPeer;
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.ethereum.net.submit.TransactionExecutor;
|
||||
import org.ethereum.net.submit.TransactionTask;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -37,24 +37,24 @@ public class EthereumImpl implements Ethereum {
|
|||
* @return online peer
|
||||
*/
|
||||
@Override
|
||||
public PeerData findOnlinePeer(PeerData peerData) {
|
||||
public Peer findOnlinePeer(Peer peerData) {
|
||||
|
||||
Set<PeerData> excludePeers = new HashSet<>();
|
||||
Set<Peer> excludePeers = new HashSet<>();
|
||||
excludePeers.add(peerData);
|
||||
|
||||
return findOnlinePeer(excludePeers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PeerData findOnlinePeer() {
|
||||
public Peer findOnlinePeer() {
|
||||
|
||||
Set<PeerData> excludePeers = new HashSet<>();
|
||||
Set<Peer> excludePeers = new HashSet<>();
|
||||
return findOnlinePeer(excludePeers);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public PeerData findOnlinePeer(Set<PeerData> excludePeers) {
|
||||
public Peer findOnlinePeer(Set<Peer> excludePeers) {
|
||||
logger.info("Looking for online peers...");
|
||||
|
||||
final EthereumListener listener = WorldManager.getInstance().getListener();
|
||||
|
@ -64,10 +64,10 @@ public class EthereumImpl implements Ethereum {
|
|||
|
||||
WorldManager.getInstance().startPeerDiscovery();
|
||||
|
||||
final Set<PeerData> peers = WorldManager.getInstance().getPeers();
|
||||
final Set<Peer> peers = WorldManager.getInstance().getPeers();
|
||||
synchronized (peers) {
|
||||
|
||||
for (PeerData peer : peers) { // it blocks until a peer is available.
|
||||
for (Peer peer : peers) { // it blocks until a peer is available.
|
||||
|
||||
if (peer.isOnline() && !excludePeers.contains(peer)) {
|
||||
|
||||
|
@ -85,9 +85,9 @@ public class EthereumImpl implements Ethereum {
|
|||
|
||||
|
||||
@Override
|
||||
public PeerData waitForOnlinePeer(){
|
||||
public Peer waitForOnlinePeer(){
|
||||
|
||||
PeerData peer = null;
|
||||
Peer peer = null;
|
||||
while(peer == null){
|
||||
|
||||
try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}
|
||||
|
@ -99,7 +99,7 @@ public class EthereumImpl implements Ethereum {
|
|||
|
||||
|
||||
@Override
|
||||
public Set<PeerData> getPeers() {
|
||||
public Set<Peer> getPeers() {
|
||||
return WorldManager.getInstance().getPeers();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import java.math.BigInteger;
|
|||
|
||||
import org.ethereum.core.AccountState;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.BlockchainImpl;
|
||||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.trie.Trie;
|
||||
import org.ethereum.vm.DataWord;
|
||||
|
@ -151,7 +150,7 @@ public interface Repository {
|
|||
*
|
||||
* @return the <code>Blockchain</code> object
|
||||
*/
|
||||
public BlockchainImpl loadBlockchain();
|
||||
public Blockchain loadBlockchain();
|
||||
|
||||
/**
|
||||
* Dump the full state of the current repository into a file with JSON format
|
||||
|
|
|
@ -57,7 +57,6 @@ public class AccountState {
|
|||
if (hexVal) {
|
||||
key = new ByteArrayWrapper(Hex.decode(keyS.substring(2)));
|
||||
} else {
|
||||
|
||||
byte[] data = ByteUtil.bigIntegerToBytes(new BigInteger(keyS));
|
||||
key = new ByteArrayWrapper(data);
|
||||
}
|
||||
|
@ -67,14 +66,11 @@ public class AccountState {
|
|||
if (hexVal) {
|
||||
value = new ByteArrayWrapper(Hex.decode(valS.substring(2)));
|
||||
} else {
|
||||
|
||||
byte[] data = ByteUtil.bigIntegerToBytes(new BigInteger(valS));
|
||||
value = new ByteArrayWrapper(data);
|
||||
}
|
||||
|
||||
storage.put(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public byte[] getAddress() {
|
||||
|
|
|
@ -206,8 +206,7 @@ public class TestRunner {
|
|||
resultCallCreate = resultCallCreates.get(i);
|
||||
}
|
||||
|
||||
CallCreate expectedCallCreate =
|
||||
testCase.getCallCreateList().get(i);
|
||||
CallCreate expectedCallCreate = testCase.getCallCreateList().get(i);
|
||||
|
||||
if (resultCallCreate == null && expectedCallCreate != null) {
|
||||
|
||||
|
@ -223,7 +222,8 @@ public class TestRunner {
|
|||
continue;
|
||||
}
|
||||
|
||||
boolean assertDestination = Arrays.equals(expectedCallCreate.getDestination(),
|
||||
boolean assertDestination = Arrays.equals(
|
||||
expectedCallCreate.getDestination(),
|
||||
resultCallCreate.getDestination());
|
||||
if (!assertDestination) {
|
||||
|
||||
|
@ -235,7 +235,8 @@ public class TestRunner {
|
|||
results.add(output);
|
||||
}
|
||||
|
||||
boolean assertData = Arrays.equals(expectedCallCreate.getData(),
|
||||
boolean assertData = Arrays.equals(
|
||||
expectedCallCreate.getData(),
|
||||
resultCallCreate.getData());
|
||||
if (!assertData) {
|
||||
|
||||
|
@ -247,10 +248,10 @@ public class TestRunner {
|
|||
results.add(output);
|
||||
}
|
||||
|
||||
boolean assertGasLimit = Arrays.equals(expectedCallCreate.getGasLimit(),
|
||||
boolean assertGasLimit = Arrays.equals(
|
||||
expectedCallCreate.getGasLimit(),
|
||||
resultCallCreate.getGasLimit());
|
||||
if (!assertGasLimit) {
|
||||
|
||||
String output =
|
||||
String.format("Call/Create gasLimit is different expected: [ %s ], result: [ %s ]",
|
||||
Hex.toHexString(expectedCallCreate.getGasLimit()),
|
||||
|
@ -259,10 +260,10 @@ public class TestRunner {
|
|||
results.add(output);
|
||||
}
|
||||
|
||||
boolean assertValue = Arrays.equals(expectedCallCreate.getValue(),
|
||||
boolean assertValue = Arrays.equals(
|
||||
expectedCallCreate.getValue(),
|
||||
resultCallCreate.getValue());
|
||||
if (!assertValue) {
|
||||
|
||||
String output =
|
||||
String.format("Call/Create value is different expected: [ %s ], result: [ %s ]",
|
||||
Hex.toHexString(expectedCallCreate.getValue()),
|
||||
|
|
|
@ -10,10 +10,11 @@ import org.ethereum.core.BlockchainImpl;
|
|||
import org.ethereum.core.Wallet;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.db.RepositoryImpl;
|
||||
import org.ethereum.facade.Blockchain;
|
||||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.listener.EthereumListener;
|
||||
import org.ethereum.net.client.ClientPeer;
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.ethereum.net.peerdiscovery.PeerDiscovery;
|
||||
|
||||
/**
|
||||
|
@ -26,13 +27,13 @@ import org.ethereum.net.peerdiscovery.PeerDiscovery;
|
|||
*/
|
||||
public class WorldManager {
|
||||
|
||||
private BlockchainImpl blockchain;
|
||||
private Blockchain blockchain;
|
||||
private Repository repository;
|
||||
private Wallet wallet;
|
||||
|
||||
private PeerDiscovery peerDiscovery;
|
||||
|
||||
private final Set<PeerData> peers = Collections.synchronizedSet(new HashSet<PeerData>());
|
||||
private final Set<Peer> peers = Collections.synchronizedSet(new HashSet<Peer>());
|
||||
|
||||
private ClientPeer activePeer;
|
||||
|
||||
|
@ -50,11 +51,10 @@ public class WorldManager {
|
|||
this.blockchain = new BlockchainImpl(repository);
|
||||
|
||||
// Initialize PeerData
|
||||
List<PeerData> peerDataList = parsePeerDiscoveryIpList(CONFIG.peerDiscoveryIPList());
|
||||
List<Peer> peerDataList = parsePeerDiscoveryIpList(CONFIG.peerDiscoveryIPList());
|
||||
peers.addAll(peerDataList);
|
||||
|
||||
peerDiscovery = new PeerDiscovery(peers);
|
||||
|
||||
}
|
||||
|
||||
// used for testing
|
||||
|
@ -85,10 +85,10 @@ public class WorldManager {
|
|||
this.listener = listener;
|
||||
}
|
||||
|
||||
public void addPeers(final Set<PeerData> newPeers) {
|
||||
public void addPeers(final Set<Peer> newPeers) {
|
||||
|
||||
synchronized (peers) {
|
||||
for (final PeerData peer : newPeers) {
|
||||
for (final Peer peer : newPeers) {
|
||||
if (peerDiscovery.isStarted() && !peers.contains(peer)) {
|
||||
peerDiscovery.addNewPeerData(peer);
|
||||
}
|
||||
|
@ -116,10 +116,10 @@ public class WorldManager {
|
|||
return listener;
|
||||
}
|
||||
|
||||
public List<PeerData> parsePeerDiscoveryIpList(final String peerDiscoveryIpList){
|
||||
public List<Peer> parsePeerDiscoveryIpList(final String peerDiscoveryIpList) {
|
||||
|
||||
final List<String> ipList = Arrays.asList(peerDiscoveryIpList.split(","));
|
||||
final List<PeerData> peers = new ArrayList<>();
|
||||
final List<Peer> peers = new ArrayList<>();
|
||||
|
||||
for (String ip : ipList){
|
||||
String[] addr = ip.trim().split(":");
|
||||
|
@ -130,13 +130,12 @@ public class WorldManager {
|
|||
InetAddress iAddr = InetAddress.getByName(ip_trim);
|
||||
int port = Integer.parseInt(port_trim);
|
||||
|
||||
PeerData peerData = new PeerData(iAddr.getAddress(), port, new byte[]{00});
|
||||
Peer peerData = new Peer(iAddr.getAddress(), port, new byte[]{00});
|
||||
peers.add(peerData);
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return peers;
|
||||
}
|
||||
|
||||
|
@ -148,7 +147,7 @@ public class WorldManager {
|
|||
return repository;
|
||||
}
|
||||
|
||||
public BlockchainImpl getBlockchain() {
|
||||
public Blockchain getBlockchain() {
|
||||
return blockchain;
|
||||
}
|
||||
|
||||
|
@ -168,7 +167,7 @@ public class WorldManager {
|
|||
return activePeer;
|
||||
}
|
||||
|
||||
public Set<PeerData> getPeers() {
|
||||
public Set<Peer> getPeers() {
|
||||
return peers;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ public enum Command {
|
|||
|
||||
private int cmd;
|
||||
|
||||
private static final Map<Integer, Command> intToTypeMap = new HashMap<Integer, Command>();
|
||||
private static final Map<Integer, Command> intToTypeMap = new HashMap<>();
|
||||
static {
|
||||
for (Command type : Command.values()) {
|
||||
intToTypeMap.put(type.cmd, type);
|
||||
|
|
|
@ -9,16 +9,13 @@ import io.netty.channel.MessageSizeEstimator;
|
|||
* @author: Roman Mandeleil
|
||||
* Created on: 04/07/2014 13:16
|
||||
*/
|
||||
|
||||
public class EthereumMessageSizeEstimator implements MessageSizeEstimator {
|
||||
|
||||
private final Handle handle = new HandleImpl();
|
||||
|
||||
private static final class HandleImpl implements Handle {
|
||||
|
||||
|
||||
private HandleImpl() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,12 +23,13 @@ public class EthereumMessageSizeEstimator implements MessageSizeEstimator {
|
|||
|
||||
ByteBuf buffer = ((ByteBuf)msg);
|
||||
|
||||
if (buffer.readableBytes() < 8) throw new RuntimeException("Not Ethereum packet");
|
||||
if (buffer.readableBytes() < 8)
|
||||
throw new RuntimeException("Not an Ethereum packet");
|
||||
|
||||
int msgSize = ((buffer.getByte(4) & 0xFF) << 24) +
|
||||
((buffer.getByte(5) & 0xFF) << 16) +
|
||||
((buffer.getByte(6) & 0xFF) << 8) +
|
||||
((buffer.getByte(7) & 0xFF));
|
||||
|
||||
return msgSize;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,8 +56,11 @@ public class MessageQueue {
|
|||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Recv: [{}] - [{}]",
|
||||
msg.getMessageName(),
|
||||
Hex.toHexString(msg.getPayload()));
|
||||
msg.getCommand().name(),
|
||||
Hex.toHexString(msg.getEncoded()));
|
||||
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Recv: {}", msg.toString());
|
||||
|
||||
if (null != messageQueue.peek()) {
|
||||
|
||||
|
@ -69,7 +72,7 @@ public class MessageQueue {
|
|||
|
||||
if (msg.getClass() == waitingMessage.getAnswerMessage()){
|
||||
messageRoundtrip.answer();
|
||||
logger.debug("Message round trip covered: [ {} ] ", messageRoundtrip.getMsg().getMessageName());
|
||||
logger.debug("Message round trip covered: [{}] ", messageRoundtrip.getMsg().getCommand());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,17 +112,20 @@ public class MessageQueue {
|
|||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Send: [{}] - [{}]",
|
||||
msg.getMessageName(),
|
||||
Hex.toHexString(msg.getPayload()));
|
||||
msg.getCommand().name(),
|
||||
Hex.toHexString(msg.getEncoded()));
|
||||
|
||||
ByteBuf buffer = ctx.alloc().buffer(msg.getPayload().length + 8);
|
||||
if (logger.isInfoEnabled())
|
||||
logger.info("Send: {}", msg.toString());
|
||||
|
||||
int packetLength = StaticMessages.SYNC_TOKEN.length + msg.getEncoded().length;
|
||||
ByteBuf buffer = ctx.alloc().buffer(packetLength);
|
||||
buffer.writeBytes(StaticMessages.SYNC_TOKEN);
|
||||
buffer.writeBytes(ByteUtil.calcPacketLength(msg.getPayload()));
|
||||
buffer.writeBytes(msg.getPayload());
|
||||
buffer.writeBytes(ByteUtil.calcPacketLength(msg.getEncoded()));
|
||||
buffer.writeBytes(msg.getEncoded());
|
||||
ctx.writeAndFlush(buffer);
|
||||
}
|
||||
|
||||
|
||||
private boolean containsGetBlockHashes() {
|
||||
Iterator<MessageRoundtrip> iterator = messageQueue.iterator();
|
||||
while(iterator.hasNext()){
|
||||
|
|
|
@ -77,7 +77,6 @@ public class ClientPeer {
|
|||
// Wait until the connection is closed.
|
||||
f.channel().closeFuture().sync();
|
||||
|
||||
|
||||
} catch (InterruptedException ie) {
|
||||
logger.error("-- ClientPeer: catch (InterruptedException ie) --", ie);
|
||||
} finally {
|
||||
|
@ -85,10 +84,10 @@ public class ClientPeer {
|
|||
|
||||
handler.killTimers();
|
||||
|
||||
final Set<PeerData> peers = WorldManager.getInstance().getPeers();
|
||||
final Set<Peer> peers = WorldManager.getInstance().getPeers();
|
||||
|
||||
synchronized (peers) {
|
||||
for (PeerData peer : peers){
|
||||
for (Peer peer : peers) {
|
||||
if (host.equals(peer.getInetAddress().getHostAddress()) &&
|
||||
port == peer.getPort()){
|
||||
peer.setOnline(false);
|
||||
|
@ -97,10 +96,7 @@ public class ClientPeer {
|
|||
}
|
||||
|
||||
EthereumListener listener = WorldManager.getInstance().getListener();
|
||||
if (listener != null){
|
||||
listener.onPeerDisconnect(host, port);
|
||||
}
|
||||
|
||||
if (listener != null) listener.onPeerDisconnect(host, port);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,25 +104,20 @@ public class ClientPeer {
|
|||
this.peerListener = peerListener;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The wire gets data for signed transactions and
|
||||
* sends it to the net.
|
||||
*/
|
||||
public void sendTransaction(Transaction transaction) {
|
||||
|
||||
transaction.getEncoded();
|
||||
java.util.List<Transaction> txList = new ArrayList<Transaction>();
|
||||
List<Transaction> txList = new ArrayList<>();
|
||||
txList.add(transaction);
|
||||
TransactionsMessage transactionsMessage = new TransactionsMessage(txList);
|
||||
|
||||
|
||||
byte[] payload = transactionsMessage.getPayload();
|
||||
byte[] payload = transactionsMessage.getEncoded();
|
||||
|
||||
if (peerListener != null)
|
||||
peerListener.console("Send msg: [ " +
|
||||
Hex.toHexString(payload) +
|
||||
" ]");
|
||||
peerListener.console("Send msg: [" + Hex.toHexString(payload) + "]");
|
||||
|
||||
handler.sendMsg(transactionsMessage);
|
||||
}
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
package org.ethereum.net.client;
|
||||
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.FixedRecvByteBufAllocator;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.listener.EthereumListener;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.net.Command;
|
||||
import org.ethereum.net.MessageQueue;
|
||||
import org.ethereum.net.PeerListener;
|
||||
import org.ethereum.net.message.*;
|
||||
import org.ethereum.net.peerdiscovery.PeerProtocolHandler;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Timer;
|
||||
|
@ -31,59 +28,39 @@ import static org.ethereum.net.message.StaticMessages.*;
|
|||
* @author: Roman Mandeleil
|
||||
* Created on: 10/04/14 08:19
|
||||
*/
|
||||
public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
||||
public class EthereumProtocolHandler extends PeerProtocolHandler {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("wire");
|
||||
|
||||
private Timer blocksAskTimer = new Timer("ChainAskTimer");
|
||||
private final Timer timer = new Timer("MiscMessageTimer");
|
||||
|
||||
private int secToAskForBlocks = 1;
|
||||
private boolean tearDown = false;
|
||||
private PeerListener peerListener;
|
||||
private MessageQueue msgQueue = null;
|
||||
|
||||
public EthereumProtocolHandler() { }
|
||||
|
||||
public EthereumProtocolHandler(PeerListener peerListener) {
|
||||
this.peerListener = peerListener;
|
||||
super(peerListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(final ChannelHandlerContext ctx) {
|
||||
|
||||
msgQueue = new MessageQueue(ctx);
|
||||
|
||||
logger.info("Send: " + StaticMessages.HELLO_MESSAGE.toString());
|
||||
msgQueue.sendMessage(StaticMessages.HELLO_MESSAGE);
|
||||
sendPing();
|
||||
|
||||
// sample for pinging in background
|
||||
super.channelActive(ctx);
|
||||
sendGetBlockHashes();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
public void run() {
|
||||
|
||||
if (tearDown) this.cancel();
|
||||
sendPing();
|
||||
}
|
||||
}, 2000, 5000);
|
||||
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
public void run() {
|
||||
sendGetPeers();
|
||||
}
|
||||
}, 2000, 60000);
|
||||
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
public void run() {
|
||||
sendGetTransactions();
|
||||
}
|
||||
}, 2000, 10000);
|
||||
|
||||
blocksAskTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
sendGetBlockHashes();
|
||||
}
|
||||
}, 2000, 10000);
|
||||
|
||||
blocksAskTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
sendGetBlocks();
|
||||
}
|
||||
|
@ -92,89 +69,28 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws InterruptedException {
|
||||
super.channelRead(ctx, msg);
|
||||
byte[] payload = (byte[]) msg;
|
||||
|
||||
logger.info("[Recv msg: [{}] ]", Hex.toHexString(payload));
|
||||
|
||||
EthereumListener listener = WorldManager.getInstance().getListener();
|
||||
|
||||
byte commandCode = RLP.getCommandCode(payload);
|
||||
Command receivedCommand = Command.fromInt(commandCode);
|
||||
|
||||
logger.info("[Recv: {}]", receivedCommand.name());
|
||||
Command receivedCommand = Command.fromInt(RLP.getCommandCode(payload));
|
||||
if (peerListener != null) peerListener.console("[Recv: " + receivedCommand.name() + "]");
|
||||
|
||||
switch(receivedCommand) {
|
||||
|
||||
case HELLO:
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
HelloMessage helloMessage = new HelloMessage(rlpList);
|
||||
logger.info(helloMessage.toString());
|
||||
if (peerListener != null) peerListener.console(helloMessage.toString());
|
||||
|
||||
if (listener != null){
|
||||
listener.trace(String.format("Got handshake: [ %s ]", helloMessage.toString()));
|
||||
listener.onRecvMessage(helloMessage);
|
||||
}
|
||||
break;
|
||||
case DISCONNECT:
|
||||
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
|
||||
msgQueue.receivedMessage(disconnectMessage);
|
||||
|
||||
logger.info(disconnectMessage.toString());
|
||||
if (peerListener != null) peerListener.console(disconnectMessage.toString());
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(disconnectMessage);
|
||||
break;
|
||||
case PING:
|
||||
msgQueue.receivedMessage(PING_MESSAGE);
|
||||
sendPong();
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(PING_MESSAGE);
|
||||
break;
|
||||
case PONG:
|
||||
msgQueue.receivedMessage(PONG_MESSAGE);
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(PONG_MESSAGE);
|
||||
break;
|
||||
case GET_PEERS:
|
||||
msgQueue.receivedMessage(GET_PEERS_MESSAGE);
|
||||
|
||||
// TODO: send peer list
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(GET_PEERS_MESSAGE);
|
||||
break;
|
||||
case PEERS:
|
||||
PeersMessage peersMessage = new PeersMessage(payload);
|
||||
msgQueue.receivedMessage(peersMessage);
|
||||
|
||||
WorldManager.getInstance().addPeers(peersMessage.getPeers());
|
||||
|
||||
logger.info(peersMessage.toString());
|
||||
if (peerListener != null) peerListener.console(peersMessage.toString());
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(peersMessage);
|
||||
sendStatus();
|
||||
break;
|
||||
case TRANSACTIONS:
|
||||
TransactionsMessage transactionsMessage = new TransactionsMessage(payload);
|
||||
msgQueue.receivedMessage(transactionsMessage);
|
||||
if (peerListener != null) peerListener.console(transactionsMessage.toString());
|
||||
|
||||
List<Transaction> txList = transactionsMessage.getTransactions();
|
||||
for(Transaction tx : txList)
|
||||
// WorldManager.getInstance().getBlockchain()
|
||||
// .applyTransaction(null, tx);
|
||||
// WorldManager.getInstance().getBlockchain().applyTransaction(null, tx);
|
||||
WorldManager.getInstance().getWallet().addTransaction(tx);
|
||||
|
||||
logger.info(transactionsMessage.toString());
|
||||
if (peerListener != null) peerListener.console(transactionsMessage.toString());
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(transactionsMessage);
|
||||
break;
|
||||
|
@ -182,45 +98,22 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
BlocksMessage blocksMessage = new BlocksMessage(payload);
|
||||
List<Block> blockList = blocksMessage.getBlockDataList();
|
||||
msgQueue.receivedMessage(blocksMessage);
|
||||
if (peerListener != null) peerListener.console(blocksMessage.toString());
|
||||
|
||||
// If we get one block from a peer we ask less greedy
|
||||
if (blockList.size() <= 1 && secToAskForBlocks != 10) {
|
||||
|
||||
logger.info("Now we ask for blocks each 10 seconds");
|
||||
secToAskForBlocks = 10;
|
||||
|
||||
blocksAskTimer.cancel();
|
||||
blocksAskTimer.purge();
|
||||
blocksAskTimer = new Timer();
|
||||
blocksAskTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
public void run() {
|
||||
sendGetBlocks();
|
||||
}
|
||||
}, 3000, secToAskForBlocks * 1000);
|
||||
logger.info("Now we ask for blocks every 10 seconds");
|
||||
updateBlockAskTimer(10);
|
||||
}
|
||||
|
||||
// If we get more blocks from a peer we ask more greedy
|
||||
if (blockList.size() > 2 && secToAskForBlocks != 1) {
|
||||
|
||||
logger.info("Now we ask for a chain each 1 seconds");
|
||||
secToAskForBlocks = 1;
|
||||
|
||||
blocksAskTimer.cancel();
|
||||
blocksAskTimer.purge();
|
||||
blocksAskTimer = new Timer();
|
||||
blocksAskTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
|
||||
public void run() {
|
||||
sendGetBlocks();
|
||||
}
|
||||
}, 3000, secToAskForBlocks * 1000);
|
||||
logger.info("Now we ask for a chain every 1 seconds");
|
||||
updateBlockAskTimer(1);
|
||||
}
|
||||
|
||||
if (blockList.isEmpty()) return;
|
||||
WorldManager.getInstance().getBlockchain().getBlockQueue().addBlocks(blockList);
|
||||
if (peerListener != null) peerListener.console(blocksMessage.toString());
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(blocksMessage);
|
||||
break;
|
||||
|
@ -238,13 +131,32 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
listener.onRecvMessage(GET_TRANSACTIONS_MESSAGE);
|
||||
break;
|
||||
case GET_BLOCK_HASHES:
|
||||
// TODO Implement GET_BLOCK_HASHES command
|
||||
GetBlockHashesMessage getBlockHashesMessage = new GetBlockHashesMessage(payload);
|
||||
msgQueue.receivedMessage(getBlockHashesMessage);
|
||||
if (peerListener != null) peerListener.console(getBlockHashesMessage.toString());
|
||||
|
||||
sendBlockHashes();
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(getBlockHashesMessage);
|
||||
break;
|
||||
case BLOCK_HASHES:
|
||||
// TODO Implement BLOCK_HASHES command
|
||||
BlockHashesMessage blockHashesMessage = new BlockHashesMessage(payload);
|
||||
msgQueue.receivedMessage(blockHashesMessage);
|
||||
if (peerListener != null) peerListener.console(blockHashesMessage.toString());
|
||||
|
||||
// TODO Process Block Hashes
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(blockHashesMessage);
|
||||
break;
|
||||
case GET_BLOCKS:
|
||||
// TODO Implement GET_BLOCKS command
|
||||
GetBlocksMessage getBlocksMessage = new GetBlocksMessage(payload);
|
||||
msgQueue.receivedMessage(getBlocksMessage);
|
||||
|
||||
sendBlocks();
|
||||
|
||||
if (listener != null)
|
||||
listener.onRecvMessage(getBlocksMessage);
|
||||
break;
|
||||
default:
|
||||
// do nothing and ignore this command
|
||||
|
@ -252,6 +164,18 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateBlockAskTimer(int seconds) {
|
||||
secToAskForBlocks = seconds;
|
||||
blocksAskTimer.cancel();
|
||||
blocksAskTimer.purge();
|
||||
blocksAskTimer = new Timer();
|
||||
blocksAskTimer.scheduleAtFixedRate(new TimerTask() {
|
||||
public void run() {
|
||||
sendGetBlocks();
|
||||
}
|
||||
}, 3000, secToAskForBlocks * 1000);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||
// limit the size of recieving buffer to 1024
|
||||
|
@ -260,7 +184,7 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws InterruptedException {
|
||||
this.tearDown = true;
|
||||
logger.info("Lost connection to the server");
|
||||
logger.error(cause.getMessage(), cause);
|
||||
|
@ -268,30 +192,26 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
timer.cancel();
|
||||
}
|
||||
|
||||
public void sendMsg(Message msg) {
|
||||
msgQueue.sendMessage(msg);
|
||||
|
||||
EthereumListener listener = WorldManager.getInstance().getListener();
|
||||
if (listener != null)
|
||||
listener.onSendMessage(msg);
|
||||
}
|
||||
|
||||
private void sendPing() {
|
||||
sendMsg(PING_MESSAGE);
|
||||
}
|
||||
|
||||
private void sendPong() {
|
||||
sendMsg(PONG_MESSAGE);
|
||||
}
|
||||
|
||||
private void sendGetPeers() {
|
||||
sendMsg(GET_PEERS_MESSAGE);
|
||||
protected void sendStatus() {
|
||||
byte protocolVersion = 0, networkId = 0;
|
||||
byte[] totalDifficulty = WorldManager.getInstance().getBlockchain().getTotalDifficulty();
|
||||
byte[] bestHash = WorldManager.getInstance().getBlockchain().getLatestBlockHash();
|
||||
byte[] genesisHash = StaticMessages.GENESIS_HASH;
|
||||
StatusMessage peersMessage = new StatusMessage(protocolVersion, networkId,
|
||||
totalDifficulty, bestHash, genesisHash);
|
||||
sendMsg(peersMessage);
|
||||
}
|
||||
|
||||
private void sendGetTransactions() {
|
||||
sendMsg(GET_TRANSACTIONS_MESSAGE);
|
||||
}
|
||||
|
||||
private void sendGetBlockHashes() {
|
||||
byte[] lastHash = WorldManager.getInstance().getBlockchain().getLatestBlockHash();
|
||||
GetBlockHashesMessage getBlockHashesMessage = new GetBlockHashesMessage(lastHash, 128);
|
||||
sendMsg(getBlockHashesMessage);
|
||||
}
|
||||
|
||||
private void sendGetBlocks() {
|
||||
|
||||
if (WorldManager.getInstance().getBlockchain().getBlockQueue().size() >
|
||||
|
@ -306,6 +226,14 @@ public class EthereumProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
sendMsg(getBlocksMessage);
|
||||
}
|
||||
|
||||
private void sendBlocks() {
|
||||
// TODO: Send blocks
|
||||
}
|
||||
|
||||
private void sendBlockHashes() {
|
||||
// TODO: Send block hashes
|
||||
}
|
||||
|
||||
public void killTimers(){
|
||||
blocksAskTimer.cancel();
|
||||
blocksAskTimer.purge();
|
||||
|
|
|
@ -1,31 +1,35 @@
|
|||
package org.ethereum.net.client;
|
||||
|
||||
import org.ethereum.net.message.HelloMessage;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 13/04/14 17:36
|
||||
*/
|
||||
public class PeerData {
|
||||
public class Peer {
|
||||
|
||||
private byte[] ip;
|
||||
private int port;
|
||||
private short port;
|
||||
private byte[] peerId;
|
||||
private byte capabilities;
|
||||
private List<String> capabilities;
|
||||
private HelloMessage handshake;
|
||||
|
||||
private transient boolean isOnline = false;
|
||||
private transient long lastCheckTime = 0;
|
||||
|
||||
public PeerData(byte[] ip, int port, byte[] peerId) {
|
||||
public Peer(byte[] ip, int port, byte[] peerId) {
|
||||
this.ip = ip;
|
||||
this.port = port & 0xFFFF;
|
||||
this.port = (short) (port & 0xFFFF);
|
||||
this.peerId = peerId;
|
||||
this.capabilities = new ArrayList<>();
|
||||
}
|
||||
|
||||
public InetAddress getInetAddress() {
|
||||
|
@ -52,7 +56,7 @@ public class PeerData {
|
|||
}
|
||||
|
||||
public boolean isOnline() {
|
||||
if (getCapabilities() < 7) return false;
|
||||
if (getCapabilities().size() < 0) return false;
|
||||
return isOnline;
|
||||
}
|
||||
|
||||
|
@ -68,12 +72,12 @@ public class PeerData {
|
|||
this.lastCheckTime = lastCheckTime;
|
||||
}
|
||||
|
||||
public byte getCapabilities() {
|
||||
public List<String> getCapabilities() {
|
||||
|
||||
if (handshake != null)
|
||||
return handshake.getCapabilities();
|
||||
else
|
||||
return 0;
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
|
||||
public HelloMessage getHandshake() {
|
||||
|
@ -84,16 +88,30 @@ public class PeerData {
|
|||
this.handshake = handshake;
|
||||
}
|
||||
|
||||
public byte[] getEncoded() {
|
||||
byte[] ip = RLP.encodeElement(this.ip);
|
||||
byte[] port = RLP.encodeShort(this.port);
|
||||
byte[] peerId = RLP.encodeElement(this.peerId);
|
||||
byte[][] encodedCaps = new byte[this.capabilities.size()][];
|
||||
for (int i = 0; i < this.capabilities.size(); i++) {
|
||||
encodedCaps[i] = RLP.encodeString(this.capabilities.get(i));
|
||||
}
|
||||
byte[] capabilities = RLP.encodeList(encodedCaps);
|
||||
return RLP.encodeList(ip, port, peerId, capabilities);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Peer: [ip=" + getInetAddress().getHostAddress() + ", port=" + getPort() +
|
||||
", peerId=" + (getPeerId() == null ? "": Hex.toHexString(getPeerId())) + "]";
|
||||
return "[ip=" + getInetAddress().getHostAddress() +
|
||||
", port=" + getPort() +
|
||||
", peerId=" + (getPeerId() == null ? "" : Hex.toHexString(getPeerId()))
|
||||
+ "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) return false;
|
||||
PeerData peerData = (PeerData) obj;
|
||||
Peer peerData = (Peer) obj;
|
||||
return this.getInetAddress().equals(peerData.getInetAddress());
|
||||
}
|
||||
|
||||
|
|
|
@ -1,29 +1,47 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import static org.ethereum.net.Command.BLOCK_HASHES;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.ethereum.db.ByteArrayWrapper;
|
||||
import org.ethereum.net.Command;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
public class BlockHashesMessage extends Message {
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
// TODO Auto-generated method stub
|
||||
private List<ByteArrayWrapper> hashes;
|
||||
|
||||
public BlockHashesMessage(byte[] payload) {
|
||||
super(payload);
|
||||
}
|
||||
|
||||
private void parse() {
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
this.encoded = new byte[0]; // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
// TODO Auto-generated method stub
|
||||
public Command getCommand() {
|
||||
return BLOCK_HASHES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return encoded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
public String toString() {
|
||||
if (!parsed) parse();
|
||||
return "[command=" + this.getCommand().name() + " hashes=" + Joiner.on("\n").join(hashes) + " ]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getAnswerMessage() {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,25 +18,18 @@ import org.ethereum.util.RLPList;
|
|||
*/
|
||||
public class BlocksMessage extends Message {
|
||||
|
||||
private List<Block> blockDataList = new ArrayList<Block>();
|
||||
private List<Block> blockDataList = new ArrayList<>();
|
||||
|
||||
public BlocksMessage(RLPList rawData) {
|
||||
super(rawData);
|
||||
public BlocksMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public BlocksMessage(byte[] payload) {
|
||||
super(RLP.decode2(payload));
|
||||
this.payload = payload;
|
||||
}
|
||||
public void parse() {
|
||||
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
public void parseRLP() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem) (paramsList).get(0)).getRLPData()[0]) != BLOCKS) {
|
||||
throw new Error("BlocksMessage: parsing for mal data");
|
||||
}
|
||||
if ( (((RLPItem)(paramsList).get(0)).getRLPData()[0] & 0xFF) != BLOCKS.asByte())
|
||||
throw new RuntimeException("Not a BlocksMessage command");
|
||||
|
||||
for (int i = 1; i < paramsList.size(); ++i) {
|
||||
RLPList rlpData = ((RLPList) paramsList.get(i));
|
||||
|
@ -47,33 +40,32 @@ public class BlocksMessage extends Message {
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
public Command getCommand() {
|
||||
return BLOCKS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return encoded;
|
||||
}
|
||||
|
||||
public List<Block> getBlockDataList() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
return blockDataList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "Block";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getAnswerMessage() {
|
||||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (Block blockData : this.getBlockDataList()) {
|
||||
sb.append(" ").append(blockData.toFlatString()).append("\n");
|
||||
|
||||
}
|
||||
return "Blocks Message [\n" + sb.toString() + " ]";
|
||||
return "[command=" + getCommand().name() + "\n" + sb.toString() + " ]";
|
||||
}
|
||||
}
|
|
@ -17,57 +17,45 @@ public class DisconnectMessage extends Message {
|
|||
|
||||
private ReasonCode reason;
|
||||
|
||||
public DisconnectMessage(byte[] payload) {
|
||||
super(RLP.decode2(payload));
|
||||
this.payload = payload;
|
||||
public DisconnectMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public DisconnectMessage(RLPList rawData) {
|
||||
super(rawData);
|
||||
}
|
||||
private void parse() {
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem)(paramsList).get(0)).getRLPData()[0]) != DISCONNECT) {
|
||||
throw new Error("Disconnect: parsing for mal data");
|
||||
}
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
byte[] reasonB = ((RLPItem) paramsList.get(1)).getRLPData();
|
||||
if (reasonB == null) {
|
||||
if (reasonB == null)
|
||||
this.reason = REQUESTED;
|
||||
} else {
|
||||
else
|
||||
this.reason = ReasonCode.fromInt(reasonB[0]);
|
||||
}
|
||||
|
||||
this.parsed = true;
|
||||
// TODO: what to do when mal data ?
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
public Command getCommand() {
|
||||
return DISCONNECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return encoded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public ReasonCode getReason() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
return reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "Disconnect";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (!parsed) parseRLP();
|
||||
return "Disconnect Message [ reason=" + reason + " ]";
|
||||
if (!parsed) parse();
|
||||
return "[command=" + this.getCommand().name() + " reason=" + reason + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,57 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static org.ethereum.net.Command.GET_BLOCK_HASHES;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPItem;
|
||||
import org.ethereum.util.RLPList;
|
||||
|
||||
public class GetBlockHashesMessage extends Message {
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
/** The hash from the block of which parent hash to start sending */
|
||||
private byte[] hash;
|
||||
/** The maximum number of blocks to return. Note: the peer could return fewer. */
|
||||
private int maxBlocks;
|
||||
|
||||
public GetBlockHashesMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public GetBlockHashesMessage(byte[] hash, int maxBlocks) {
|
||||
this.hash = hash;
|
||||
this.maxBlocks = maxBlocks;
|
||||
this.parsed = true;
|
||||
this.encode();
|
||||
}
|
||||
|
||||
private void encode() {
|
||||
byte[] command = RLP.encodeByte(this.getCommand().asByte());
|
||||
byte[] hash = RLP.encodeElement(this.hash);
|
||||
byte[] maxBlocks = RLP.encodeInt(this.maxBlocks);
|
||||
this.encoded = RLP.encodeList(command, hash, maxBlocks);
|
||||
}
|
||||
|
||||
public void parse() {
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
this.hash = ((RLPItem) paramsList.get(1)).getRLPData();
|
||||
byte[] maxBlocksBytes = ((RLPItem) paramsList.get(2)).getRLPData();
|
||||
this.maxBlocks = new BigInteger(1, maxBlocksBytes).intValue();
|
||||
|
||||
this.parsed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
return null;
|
||||
public byte[] getEncoded() {
|
||||
return encoded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "GetBlockHashes";
|
||||
public Command getCommand() {
|
||||
return GET_BLOCK_HASHES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -21,4 +59,19 @@ public class GetBlockHashesMessage extends Message {
|
|||
return BlockHashesMessage.class;
|
||||
}
|
||||
|
||||
public byte[] getHash() {
|
||||
if (!parsed) parse();
|
||||
return hash;
|
||||
}
|
||||
|
||||
public int getMaxBlocks() {
|
||||
if (!parsed) parse();
|
||||
return maxBlocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[command=" + this.getCommand().name() + "]"; //TODO
|
||||
}
|
||||
|
||||
}
|
|
@ -14,19 +14,19 @@ import org.spongycastle.util.encoders.Hex;
|
|||
|
||||
public class GetBlocksMessage extends Message {
|
||||
|
||||
private List<byte[]> blockHashList = new ArrayList<byte[]>();
|
||||
private List<byte[]> blockHashList = new ArrayList<>();
|
||||
private BigInteger blockNum;
|
||||
|
||||
public GetBlocksMessage(RLPList rawData) {
|
||||
super(rawData);
|
||||
public GetBlocksMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
// TODO: it get's byte for now change it to int
|
||||
// TODO: it get's byte for now. change it to int
|
||||
public GetBlocksMessage(byte number , byte[]... blockHashList) {
|
||||
|
||||
byte[][] encodedElements = new byte[blockHashList.length + 2][];
|
||||
|
||||
encodedElements[0] = new byte[]{0x14};
|
||||
encodedElements[0] = new byte[]{GET_BLOCKS.asByte()};
|
||||
int i = 1;
|
||||
for (byte[] hash : blockHashList) {
|
||||
this.blockHashList.add(hash);
|
||||
|
@ -36,16 +36,15 @@ public class GetBlocksMessage extends Message {
|
|||
}
|
||||
encodedElements[i] = RLP.encodeByte(number);
|
||||
|
||||
this.payload = RLP.encodeList(encodedElements);
|
||||
this.encoded = RLP.encodeList(encodedElements);
|
||||
this.parsed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
public void parse() {
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem) (paramsList).get(0)).getRLPData()[0]) != GET_BLOCKS)
|
||||
throw new Error("GetBlocks: parsing for mal data");
|
||||
if ( (((RLPItem)(paramsList).get(0)).getRLPData()[0] & 0xFF) != GET_BLOCKS.asByte())
|
||||
throw new RuntimeException("Not a GetBlockssMessage command");
|
||||
|
||||
int size = paramsList.size();
|
||||
for (int i = 1; i < size - 1; ++i) {
|
||||
|
@ -57,17 +56,16 @@ public class GetBlocksMessage extends Message {
|
|||
this.blockNum = new BigInteger(blockNumB);
|
||||
|
||||
this.parsed = true;
|
||||
// TODO: what to do when mal data ?
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
public byte[] getEncoded() {
|
||||
return encoded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "GetBlocks";
|
||||
public Command getCommand() {
|
||||
return GET_BLOCKS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,12 +74,13 @@ public class GetBlocksMessage extends Message {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (byte[] blockHash : blockHashList)
|
||||
sb.append("").append(Hex.toHexString(blockHash)).append(", ");
|
||||
for (byte[] blockHash : blockHashList) {
|
||||
sb.append("").append(Hex.toHexString(blockHash)).append("\n ");
|
||||
}
|
||||
sb.append(" blockNum=").append(blockNum);
|
||||
return "GetBlocks Message [" + sb.toString() + " ]";
|
||||
return "[command=" + this.getCommand().name() + " " + sb.toString() + " ]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import static org.ethereum.net.Command.GET_PEERS;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
|
@ -9,26 +12,27 @@ import org.spongycastle.util.encoders.Hex;
|
|||
*/
|
||||
public class GetPeersMessage extends Message {
|
||||
|
||||
public GetPeersMessage() {
|
||||
this.payload = Hex.decode("C110");
|
||||
/** GetPeers message is always a the same single command payload */
|
||||
private final static byte[] FIXED_PAYLOAD = Hex.decode("C104");
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return FIXED_PAYLOAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName(){
|
||||
return "GetPeers";
|
||||
public Command getCommand(){
|
||||
return GET_PEERS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<PeersMessage> getAnswerMessage() {
|
||||
return PeersMessage.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[command=" + this.getCommand().name() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import static org.ethereum.net.Command.GET_TRANSACTIONS;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
|
@ -9,26 +12,26 @@ import org.spongycastle.util.encoders.Hex;
|
|||
*/
|
||||
public class GetTransactionsMessage extends Message {
|
||||
|
||||
public GetTransactionsMessage() {
|
||||
this.payload = Hex.decode("C116");
|
||||
/** GetTransactions message is always a the same single command payload */
|
||||
private static byte[] FIXED_PAYLOAD = Hex.decode("C116");
|
||||
|
||||
public byte[] getEncoded() {
|
||||
return FIXED_PAYLOAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
public Command getCommand() {
|
||||
return GET_TRANSACTIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName(){
|
||||
return "GetTransactions";
|
||||
public Class<TransactionsMessage> getAnswerMessage() {
|
||||
return TransactionsMessage.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getAnswerMessage() {
|
||||
return null;
|
||||
public String toString() {
|
||||
return "[command=" + this.getCommand().name() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import static org.ethereum.net.Command.HELLO;
|
||||
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPItem;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wrapper around an Ethereum HelloMessage on the network
|
||||
|
@ -26,18 +30,18 @@ public class HelloMessage extends Message {
|
|||
private String clientId;
|
||||
/** A peer-network capability code, readable ASCII and 3 letters.
|
||||
* Currently only "eth" and "shh" are known. */
|
||||
private byte capabilities;
|
||||
private List<String> capabilities;
|
||||
/** The port on which the peer is listening for an incoming connection */
|
||||
private short listenPort;
|
||||
/** The identity and public key of the peer */
|
||||
private byte[] peerId;
|
||||
|
||||
public HelloMessage(RLPList rawData) {
|
||||
super(rawData);
|
||||
public HelloMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public HelloMessage(byte p2pVersion, String clientId,
|
||||
byte capabilities, short listenPort, byte[] peerId) {
|
||||
List<String> capabilities, short listenPort, byte[] peerId) {
|
||||
this.p2pVersion = p2pVersion;
|
||||
this.clientId = clientId;
|
||||
this.capabilities = capabilities;
|
||||
|
@ -46,22 +50,27 @@ public class HelloMessage extends Message {
|
|||
this.parsed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
public void parse() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
// the message does no distinguish between the 0 and null so here I check command code for null
|
||||
// TODO: find out if it can be 00
|
||||
// TODO: find out if it can be 00. Do we need to check for this?
|
||||
// The message does not distinguish between 0 and null,
|
||||
// so we check command code for null.
|
||||
if (((RLPItem) paramsList.get(0)).getRLPData() != null)
|
||||
throw new Error("HelloMessage: parsing for mal data");
|
||||
|
||||
this.p2pVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0];
|
||||
byte[] p2pVersionBytes = ((RLPItem) paramsList.get(1)).getRLPData();
|
||||
this.p2pVersion = p2pVersionBytes != null ? p2pVersionBytes[0] : 0;
|
||||
|
||||
byte[] clientIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
|
||||
this.clientId = new String(clientIdBytes != null ? clientIdBytes : EMPTY_BYTE_ARRAY);
|
||||
|
||||
this.capabilities = ((RLPItem) paramsList.get(3)).getRLPData()[0];
|
||||
RLPList capabilityList = (RLPList) paramsList.get(3);
|
||||
this.capabilities = new ArrayList<>();
|
||||
for (int i = 0; i < capabilityList.size(); i++) {
|
||||
this.capabilities.add(new String(capabilityList.get(i).getRLPData()));
|
||||
}
|
||||
|
||||
byte[] peerPortBytes = ((RLPItem) paramsList.get(4)).getRLPData();
|
||||
this.listenPort = new BigInteger(peerPortBytes).shortValue();
|
||||
|
@ -69,57 +78,58 @@ public class HelloMessage extends Message {
|
|||
this.peerId = ((RLPItem) paramsList.get(5)).getRLPData();
|
||||
|
||||
this.parsed = true;
|
||||
// TODO: what to do when mal data ?
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
if (encoded == null) this.encode();
|
||||
return encoded;
|
||||
}
|
||||
|
||||
private void encode() {
|
||||
byte[] command = RLP.encodeByte(HELLO.asByte());
|
||||
byte[] protocolVersion = RLP.encodeByte(this.p2pVersion);
|
||||
byte[] p2pVersion = RLP.encodeByte(this.p2pVersion);
|
||||
byte[] clientId = RLP.encodeString(this.clientId);
|
||||
byte[] capabilities = RLP.encodeByte(this.capabilities);
|
||||
byte[][] capabilities = new byte[this.capabilities.size()][];
|
||||
for (int i = 0; i < this.capabilities.size(); i++) {
|
||||
capabilities[i] = RLP.encode(this.capabilities.get(i).getBytes());
|
||||
}
|
||||
byte[] capabilityList = RLP.encodeList(capabilities);
|
||||
byte[] peerPort = RLP.encodeShort(this.listenPort);
|
||||
byte[] peerId = RLP.encodeElement(this.peerId);
|
||||
|
||||
byte[] data = RLP.encodeList(command, protocolVersion,
|
||||
clientId, capabilities, peerPort, peerId);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
public byte getCommandCode() {
|
||||
if (!parsed) parseRLP();
|
||||
return HELLO.asByte();
|
||||
this.encoded = RLP.encodeList(command, p2pVersion,
|
||||
clientId, capabilityList, peerPort, peerId);
|
||||
}
|
||||
|
||||
public byte getP2PVersion() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
return p2pVersion;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public byte getCapabilities() {
|
||||
if (!parsed) parseRLP();
|
||||
public List<String> getCapabilities() {
|
||||
if (!parsed) parse();
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
public short getListenPort() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
return listenPort;
|
||||
}
|
||||
|
||||
public byte[] getPeerId() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
return peerId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "HelloMessage";
|
||||
public Command getCommand() {
|
||||
return HELLO;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -128,14 +138,13 @@ public class HelloMessage extends Message {
|
|||
}
|
||||
|
||||
public String toString() {
|
||||
if (!parsed) parseRLP();
|
||||
return "Hello Message [ command=" + HELLO.asByte() + " " +
|
||||
" p2pVersion=" + this.p2pVersion + " " +
|
||||
" clientId=" + this.clientId + " " +
|
||||
" capabilities=" + this.capabilities + " " +
|
||||
if (!parsed) parse();
|
||||
return "[command=" + this.getCommand().name() +
|
||||
" p2pVersion=" + this.p2pVersion +
|
||||
" clientId=" + this.clientId +
|
||||
" capabilities=[" + Joiner.on(" ").join(this.capabilities) + "]" +
|
||||
" peerPort=" + this.listenPort + " " +
|
||||
" peerId=" + Hex.toHexString(this.peerId) + " " +
|
||||
"]";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,30 +1,41 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.ethereum.net.Command;
|
||||
|
||||
/**
|
||||
* Abstract message class for all messages on the Ethereum network
|
||||
*
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 06/04/14 14:58
|
||||
*/
|
||||
public abstract class Message {
|
||||
|
||||
RLPList rawData;
|
||||
boolean parsed = false;
|
||||
byte[] payload;
|
||||
protected boolean parsed;
|
||||
protected byte[] encoded;
|
||||
|
||||
public Message() {}
|
||||
|
||||
public Message(RLPList rawData) {
|
||||
this.rawData = rawData;
|
||||
public Message(byte[] encoded) {
|
||||
this.encoded = encoded;
|
||||
parsed = false;
|
||||
}
|
||||
|
||||
public abstract void parseRLP();
|
||||
public abstract Command getCommand();
|
||||
|
||||
public abstract byte[] getPayload();
|
||||
|
||||
public abstract String getMessageName();
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ package org.ethereum.net.message;
|
|||
import static org.ethereum.net.Command.PEERS;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPItem;
|
||||
import org.ethereum.util.RLPList;
|
||||
|
@ -21,26 +23,23 @@ public class PeersMessage extends Message {
|
|||
|
||||
private boolean parsed = false;
|
||||
|
||||
private final Set<PeerData> peers = new LinkedHashSet<PeerData>();
|
||||
private Set<Peer> peers = new LinkedHashSet<>();
|
||||
|
||||
public PeersMessage(byte[] payload) {
|
||||
super(RLP.decode2(payload));
|
||||
this.payload = payload;
|
||||
super(payload);
|
||||
}
|
||||
|
||||
public PeersMessage(RLPList rawData) {
|
||||
this.rawData = rawData;
|
||||
parsed = false;
|
||||
public PeersMessage(Set<Peer> peers) {
|
||||
this.peers = peers;
|
||||
this.parsed = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
public void parse() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
if (Command.fromInt(((RLPItem)(paramsList).get(0)).getRLPData()[0] & 0xFF) != PEERS) {
|
||||
throw new Error("PeersMessage: parsing for mal data");
|
||||
}
|
||||
if ( (((RLPItem)(paramsList).get(0)).getRLPData()[0] & 0xFF) != PEERS.asByte())
|
||||
throw new RuntimeException("Not a PeersMessage command");
|
||||
|
||||
for (int i = 1; i < paramsList.size(); ++i) {
|
||||
|
||||
|
@ -55,42 +54,51 @@ public class PeersMessage extends Message {
|
|||
peerPort = bb.getShort();
|
||||
}
|
||||
byte[] peerId = ((RLPItem) peerParams.get(2)).getRLPData();
|
||||
PeerData peer = new PeerData(ip, peerPort, peerId);
|
||||
Peer peer = new Peer(ip, peerPort, peerId);
|
||||
peers.add(peer);
|
||||
}
|
||||
this.parsed = true;
|
||||
// TODO: what to do when mal data ?
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
public Command getCommand() {
|
||||
return PEERS;
|
||||
}
|
||||
|
||||
public Set<PeerData> getPeers() {
|
||||
if (!parsed)
|
||||
parseRLP();
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
if (encoded == null) this.encode();
|
||||
return encoded;
|
||||
}
|
||||
|
||||
private void encode() {
|
||||
byte[][] encodedByteArrays = new byte[this.peers.size()+1][];
|
||||
encodedByteArrays[0] = RLP.encodeByte(this.getCommand().asByte());
|
||||
List<Peer> peerList = new ArrayList<>();
|
||||
peerList.addAll(this.peers);
|
||||
for (int i = 0; i < peerList.size(); i++) {
|
||||
encodedByteArrays[i+1] = peerList.get(i).getEncoded();
|
||||
}
|
||||
this.encoded = RLP.encodeList(encodedByteArrays);
|
||||
}
|
||||
|
||||
public Set<Peer> getPeers() {
|
||||
if (!parsed) this.parse();
|
||||
return peers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "Peers";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getAnswerMessage() {
|
||||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (!parsed)
|
||||
parseRLP();
|
||||
if (!parsed) this.parse();
|
||||
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (PeerData peerData : peers) {
|
||||
sb.append("[").append(peerData).append("] \n ");
|
||||
for (Peer peerData : peers) {
|
||||
sb.append("\n [").append(peerData).append("]");
|
||||
}
|
||||
return "Peers Message [\n " + sb.toString() + "]";
|
||||
return "[command=" + this.getCommand().name() + sb.toString() + "]";
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import static org.ethereum.net.Command.PING;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
|
@ -9,26 +12,25 @@ import org.spongycastle.util.encoders.Hex;
|
|||
*/
|
||||
public class PingMessage extends Message {
|
||||
|
||||
public PingMessage() {
|
||||
this.payload = Hex.decode("C102");
|
||||
/** Ping message is always a the same single command payload */
|
||||
private static byte[] FIXED_PAYLOAD = Hex.decode("C102");
|
||||
|
||||
public byte[] getEncoded() {
|
||||
return FIXED_PAYLOAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName(){
|
||||
return "Ping";
|
||||
public Command getCommand() {
|
||||
return PING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<PongMessage> getAnswerMessage() {
|
||||
return PongMessage.class;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[command=" + getCommand().name() + "]";
|
||||
}
|
||||
}
|
|
@ -1,5 +1,8 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import static org.ethereum.net.Command.PONG;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
|
@ -9,25 +12,26 @@ import org.spongycastle.util.encoders.Hex;
|
|||
*/
|
||||
public class PongMessage extends Message {
|
||||
|
||||
public PongMessage() {
|
||||
this.payload = Hex.decode("C103");
|
||||
/** Pong message is always a the same single command payload */
|
||||
private static byte[] FIXED_PAYLOAD = Hex.decode("C103");
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
return FIXED_PAYLOAD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
}
|
||||
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public String getMessageName(){
|
||||
return "Pong";
|
||||
public Command getCommand() {
|
||||
return PONG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getAnswerMessage() {
|
||||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[command=PONG]";
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ public enum ReasonCode {
|
|||
|
||||
private int reason;
|
||||
|
||||
private static final Map<Integer, ReasonCode> intToTypeMap = new HashMap<Integer, ReasonCode>();
|
||||
private static final Map<Integer, ReasonCode> intToTypeMap = new HashMap<>();
|
||||
static {
|
||||
for (ReasonCode type : ReasonCode.values()) {
|
||||
intToTypeMap.put(type.reason, type);
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package org.ethereum.net.message;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.core.Genesis;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
|
@ -18,31 +22,31 @@ public class StaticMessages {
|
|||
public final static GetPeersMessage GET_PEERS_MESSAGE = new GetPeersMessage();
|
||||
public final static GetTransactionsMessage GET_TRANSACTIONS_MESSAGE = new GetTransactionsMessage();
|
||||
|
||||
public static final byte[] PING_PACKET = Hex.decode("2240089100000002C102");
|
||||
public static final byte[] PONG_PACKET = Hex.decode("2240089100000002C103");
|
||||
public static final byte[] GET_PEERS_PACKET = Hex.decode("2240089100000002C110");
|
||||
public static final byte[] GET_TRANSACTIONS = Hex.decode("2240089100000002C116");
|
||||
|
||||
public static final byte[] DISCONNECT_08 = Hex.decode("2240089100000003C20108");
|
||||
public static final byte[] DISCONNECT_PEER_QUITTING = Hex.decode("2240089100000003C20108");
|
||||
|
||||
public static final byte[] SYNC_TOKEN = Hex.decode("22400891");
|
||||
public static final byte[] GENESIS_HASH = Genesis.getInstance().getHash();
|
||||
|
||||
private static HelloMessage generateHelloMessage() {
|
||||
String helloAnnouncement = buildHelloAnnouncement();
|
||||
byte p2pVersion = 0x00;
|
||||
List<String> capabilities = new ArrayList<>(Arrays.asList("eth"));
|
||||
short listenPort = (short) 30303;
|
||||
byte[] peerIdBytes = HashUtil.randomPeerId();
|
||||
|
||||
return new HelloMessage(p2pVersion, helloAnnouncement,
|
||||
capabilities, listenPort, peerIdBytes);
|
||||
}
|
||||
|
||||
private static String buildHelloAnnouncement() {
|
||||
String version = SystemProperties.CONFIG.projectVersion();
|
||||
String system = System.getProperty("os.name");
|
||||
if (system.contains(" "))
|
||||
system = system.substring(0, system.indexOf(" "));
|
||||
if (System.getProperty("java.vm.vendor").contains("Android"))
|
||||
system = "Android";
|
||||
|
||||
String phrase = SystemProperties.CONFIG.helloPhrase();
|
||||
|
||||
String helloAnnouncement = String.format("Ethereum(J)/v%s/%s/%s/Java", version, phrase, system);
|
||||
|
||||
return new HelloMessage((byte) 0x21, helloAnnouncement,
|
||||
Byte.parseByte("00000111", 2), (short) 30303, peerIdBytes);
|
||||
return String.format("Ethereum(J)/v%s/%s/%s/Java", version, phrase, system);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,12 @@ package org.ethereum.net.message;
|
|||
|
||||
import static org.ethereum.net.Command.STATUS;
|
||||
|
||||
import org.ethereum.net.Command;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPItem;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
* Wrapper around an Ethereum StatusMessage on the network
|
||||
|
@ -23,8 +26,8 @@ public class StatusMessage extends Message {
|
|||
/** The hash of the Genesis block */
|
||||
private byte[] genesisHash;
|
||||
|
||||
public StatusMessage(RLPList rawData) {
|
||||
super(rawData);
|
||||
public StatusMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public StatusMessage(byte protocolVersion, byte networkId,
|
||||
|
@ -35,18 +38,18 @@ public class StatusMessage extends Message {
|
|||
this.bestHash = bestHash;
|
||||
this.genesisHash = genesisHash;
|
||||
this.parsed = true;
|
||||
this.encode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
public void parse() {
|
||||
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
/* the message does not distinguish between the 0 and null
|
||||
* so check command code for null */
|
||||
// TODO: find out if it can be 00
|
||||
if (((RLPItem) paramsList.get(0)).getRLPData() != null)
|
||||
throw new Error("StaticMessage: parsing for mal data");
|
||||
if ( (((RLPItem)(paramsList).get(0)).getRLPData()[0] & 0xFF) != STATUS.asByte())
|
||||
throw new RuntimeException("Not a StatusMessage command");
|
||||
|
||||
this.protocolVersion = ((RLPItem) paramsList.get(1)).getRLPData()[0];
|
||||
byte[] networkIdBytes = ((RLPItem) paramsList.get(2)).getRLPData();
|
||||
|
@ -59,7 +62,12 @@ public class StatusMessage extends Message {
|
|||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
public byte[] getEncoded() {
|
||||
if (encoded == null) this.encode();
|
||||
return encoded;
|
||||
}
|
||||
|
||||
private void encode() {
|
||||
byte[] command = RLP.encodeByte(STATUS.asByte());
|
||||
byte[] protocolVersion = RLP.encodeByte(this.protocolVersion);
|
||||
byte[] networkId = RLP.encodeByte(this.networkId);
|
||||
|
@ -67,19 +75,54 @@ public class StatusMessage extends Message {
|
|||
byte[] bestHash = RLP.encodeElement(this.bestHash);
|
||||
byte[] genesisHash = RLP.encodeElement(this.genesisHash);
|
||||
|
||||
byte[] data = RLP.encodeList(command, protocolVersion, networkId,
|
||||
this.encoded = RLP.encodeList(command, protocolVersion, networkId,
|
||||
totalDifficulty, bestHash, genesisHash);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "StatusMessage";
|
||||
public Command getCommand() {
|
||||
return STATUS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte getProtocolVersion() {
|
||||
if (!parsed) this.parse();
|
||||
return protocolVersion;
|
||||
}
|
||||
|
||||
public byte getNetworkId() {
|
||||
if (!parsed) this.parse();
|
||||
return networkId;
|
||||
}
|
||||
|
||||
public byte[] getTotalDifficulty() {
|
||||
if (!parsed) this.parse();
|
||||
return totalDifficulty;
|
||||
}
|
||||
|
||||
public byte[] getBestHash() {
|
||||
if (!parsed) this.parse();
|
||||
return bestHash;
|
||||
}
|
||||
|
||||
public byte[] getGenesisHash() {
|
||||
if (!parsed) this.parse();
|
||||
return genesisHash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (!parsed) parse();
|
||||
return "[command=" + this.getCommand().name() +
|
||||
" protocolVersion=" + this.protocolVersion +
|
||||
" networkId=" + this.networkId +
|
||||
" totalDifficulty=" + ByteUtil.toHexString(this.totalDifficulty) +
|
||||
" bestHash=" + Hex.toHexString(this.bestHash) + " " +
|
||||
" genesisHash=" + Hex.toHexString(this.genesisHash) + " " +
|
||||
"]";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,7 @@ import org.ethereum.net.Command;
|
|||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPItem;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -22,52 +18,39 @@ import java.util.List;
|
|||
*/
|
||||
public class TransactionsMessage extends Message {
|
||||
|
||||
private Logger logger = LoggerFactory.getLogger("wire");
|
||||
private List<Transaction> transactions = new ArrayList<Transaction>();
|
||||
private List<Transaction> transactions = new ArrayList<>();
|
||||
|
||||
public TransactionsMessage() {
|
||||
public TransactionsMessage(byte[] encoded) {
|
||||
super(encoded);
|
||||
}
|
||||
|
||||
public TransactionsMessage(List<Transaction> transactionList) {
|
||||
|
||||
this.transactions = transactionList;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
for (Transaction tx : transactionList) {
|
||||
|
||||
byte[] txPayload = tx.getEncoded();
|
||||
try {
|
||||
baos.write(txPayload);
|
||||
} catch (IOException e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
byte[][] elements = new byte[transactionList.size() + 1][];
|
||||
elements[0] = new byte[]{Command.TRANSACTIONS.asByte()};
|
||||
for (int i = 0; i < transactionList.size(); ++i)
|
||||
elements[i + 1] = transactionList.get(i).getEncoded();
|
||||
payload = RLP.encodeList(elements);
|
||||
}
|
||||
|
||||
public TransactionsMessage(byte[] payload) {
|
||||
super(RLP.decode2(payload));
|
||||
this.payload = payload;
|
||||
}
|
||||
|
||||
public TransactionsMessage(RLPList rawData) {
|
||||
this.rawData = rawData;
|
||||
parsed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parseRLP() {
|
||||
RLPList paramsList = (RLPList) rawData.get(0);
|
||||
public byte[] getEncoded() {
|
||||
if (encoded == null) this.encode();
|
||||
return encoded;
|
||||
}
|
||||
|
||||
if (Command.fromInt(((RLPItem) (paramsList).get(0)).getRLPData()[0] & 0xFF) != TRANSACTIONS)
|
||||
throw new Error("TransactionMessage: parsing for mal data");
|
||||
private void encode() {
|
||||
byte[][] encodedTransactions = new byte[transactions.size()][];
|
||||
byte[] command = new byte[]{Command.TRANSACTIONS.asByte()};
|
||||
for (int i = 0; i < transactions.size(); ++i)
|
||||
encodedTransactions[i + 1] = transactions.get(i).getEncoded();
|
||||
byte[] encodedTxsList = RLP.encodeList(encodedTransactions);
|
||||
this.encoded = RLP.encodeList(command, encodedTxsList);
|
||||
}
|
||||
|
||||
transactions = new ArrayList<Transaction>();
|
||||
private void parse() {
|
||||
RLPList paramsList = (RLPList) RLP.decode2(encoded).get(0);
|
||||
|
||||
int commandByte = ((RLPItem) (paramsList).get(0)).getRLPData()[0] & 0xFF;
|
||||
if (Command.fromInt(commandByte) != TRANSACTIONS)
|
||||
throw new RuntimeException("Not a TransactionMessage: " + Integer.toHexString(commandByte));
|
||||
|
||||
transactions = new ArrayList<>();
|
||||
int size = paramsList.size();
|
||||
for (int i = 1; i < size; ++i) {
|
||||
RLPList rlpTxData = (RLPList) paramsList.get(i);
|
||||
|
@ -78,27 +61,22 @@ public class TransactionsMessage extends Message {
|
|||
}
|
||||
|
||||
public List<Transaction> getTransactions() {
|
||||
if (!parsed) parseRLP();
|
||||
if (!parsed) parse();
|
||||
return transactions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageName() {
|
||||
return "Transactions";
|
||||
public Command getCommand() {
|
||||
return TRANSACTIONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class getAnswerMessage() {
|
||||
public Class<?> getAnswerMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getPayload() {
|
||||
return payload;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if(!parsed) parseRLP();
|
||||
if(!parsed) parse();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
for (Transaction transaction : transactions)
|
||||
sb.append(" ").append(transaction).append("\n");
|
||||
|
|
|
@ -1,178 +0,0 @@
|
|||
package org.ethereum.net.peerdiscovery;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.FixedRecvByteBufAllocator;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.net.Command;
|
||||
import org.ethereum.net.PeerListener;
|
||||
import org.ethereum.net.message.DisconnectMessage;
|
||||
import org.ethereum.net.message.HelloMessage;
|
||||
import org.ethereum.net.message.PeersMessage;
|
||||
import org.ethereum.net.message.StaticMessages;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import static org.ethereum.net.Command.*;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
* Created on: 10/04/14 08:19
|
||||
*/
|
||||
public class EthereumPeerTasterHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger("peerdiscovery");
|
||||
|
||||
private final static byte[] MAGIC_PREFIX = {(byte)0x22, (byte)0x40, (byte)0x08, (byte)0x91};
|
||||
|
||||
private long lastPongTime = 0;
|
||||
private boolean tearDown = false;
|
||||
|
||||
private PeerListener peerListener;
|
||||
|
||||
private HelloMessage handshake = null;
|
||||
|
||||
public EthereumPeerTasterHandler() { }
|
||||
|
||||
public EthereumPeerTasterHandler(PeerListener peerListener) {
|
||||
this.peerListener = peerListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(final ChannelHandlerContext ctx) {
|
||||
|
||||
// Here we send the hello message with random id each time
|
||||
// to not interrupt active peer
|
||||
|
||||
HelloMessage helloMessage = StaticMessages.HELLO_MESSAGE;
|
||||
|
||||
byte[] helloLength =ByteUtil.calcPacketLength(helloMessage.getPayload());
|
||||
|
||||
final ByteBuf buffer = ctx.alloc().buffer(helloMessage.getPayload().length + 8);
|
||||
|
||||
buffer.writeBytes(MAGIC_PREFIX);
|
||||
buffer.writeBytes(helloLength);
|
||||
buffer.writeBytes(helloMessage.getPayload());
|
||||
logger.info("Send: " + helloMessage.toString());
|
||||
ctx.writeAndFlush(buffer);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
byte[] payload = (byte[]) msg;
|
||||
|
||||
logger.info("[Send msg: [{}] ]", Hex.toHexString(payload));
|
||||
|
||||
byte command = RLP.getCommandCode(payload);
|
||||
|
||||
// got HELLO
|
||||
if (Command.fromInt(command) == HELLO) {
|
||||
logger.info("[Recv: HELLO]" );
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
HelloMessage helloMessage = new HelloMessage(rlpList);
|
||||
handshake = helloMessage;
|
||||
logger.info(helloMessage.toString());
|
||||
|
||||
sendGetPeers(ctx);
|
||||
}
|
||||
// got DISCONNECT
|
||||
if (Command.fromInt(command) == DISCONNECT) {
|
||||
logger.info("[Recv: DISCONNECT]");
|
||||
if (peerListener != null) peerListener.console("[Recv: DISCONNECT]");
|
||||
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
DisconnectMessage disconnectMessage = new DisconnectMessage(rlpList);
|
||||
|
||||
logger.info(disconnectMessage.toString());
|
||||
}
|
||||
|
||||
// got PING send pong
|
||||
if (Command.fromInt(command) == PING) {
|
||||
logger.info("[Recv: PING]");
|
||||
if (peerListener != null) peerListener.console("[Recv: PING]");
|
||||
sendPong(ctx);
|
||||
}
|
||||
|
||||
// got PONG mark it
|
||||
if (Command.fromInt(command) == PONG) {
|
||||
logger.info("[Recv: PONG]" );
|
||||
if (peerListener != null) peerListener.console("[Recv: PONG]");
|
||||
this.lastPongTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
// got PEERS
|
||||
if (Command.fromInt(command) == PEERS) {
|
||||
logger.info("[Recv: PEERS]");
|
||||
if (peerListener != null) peerListener.console("[Recv: PEERS]");
|
||||
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
PeersMessage peersMessage = new PeersMessage(rlpList);
|
||||
|
||||
WorldManager.getInstance().addPeers(peersMessage.getPeers());
|
||||
logger.info(peersMessage.toString());
|
||||
|
||||
sendDisconnectNice(ctx);
|
||||
|
||||
ctx.close().sync();
|
||||
ctx.disconnect().sync();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
|
||||
// limit the size of recieving buffer to 1024
|
||||
ctx.channel().config().setRecvByteBufAllocator(new FixedRecvByteBufAllocator(32368));
|
||||
ctx.channel().config().setOption(ChannelOption.SO_RCVBUF, 32368);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
this.tearDown = true;
|
||||
logger.info("Lost connection to the server");
|
||||
logger.error(cause.getMessage(), cause);
|
||||
|
||||
ctx.close().sync();
|
||||
ctx.disconnect().sync();
|
||||
}
|
||||
|
||||
private void sendPing(ChannelHandlerContext ctx) {
|
||||
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.PING_PACKET.length);
|
||||
buffer.writeBytes(StaticMessages.PING_PACKET);
|
||||
ctx.writeAndFlush(buffer);
|
||||
}
|
||||
|
||||
private void sendPong(ChannelHandlerContext ctx) {
|
||||
logger.info("[Send: PONG]");
|
||||
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.PONG_PACKET.length);
|
||||
buffer.writeBytes(StaticMessages.PONG_PACKET);
|
||||
ctx.writeAndFlush(buffer);
|
||||
}
|
||||
|
||||
private void sendDisconnectNice(ChannelHandlerContext ctx) {
|
||||
logger.info("[Send: DISCONNECT]");
|
||||
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.DISCONNECT_08.length);
|
||||
buffer.writeBytes(StaticMessages.DISCONNECT_08);
|
||||
ctx.writeAndFlush(buffer);
|
||||
}
|
||||
|
||||
private void sendGetPeers(ChannelHandlerContext ctx) {
|
||||
ByteBuf buffer = ctx.alloc().buffer(StaticMessages.GET_PEERS_PACKET.length);
|
||||
buffer.writeBytes(StaticMessages.GET_PEERS_PACKET);
|
||||
ctx.writeAndFlush(buffer);
|
||||
}
|
||||
|
||||
public HelloMessage getHandshake(){
|
||||
return this.handshake;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package org.ethereum.net.peerdiscovery;
|
||||
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -24,11 +24,11 @@ public class PeerDiscovery {
|
|||
private ThreadPoolExecutor executorPool;
|
||||
private PeerDiscoveryMonitorThread monitor;
|
||||
|
||||
private final Set<PeerData> peers;
|
||||
private final Set<Peer> peers;
|
||||
|
||||
private final AtomicBoolean started = new AtomicBoolean(false);
|
||||
|
||||
public PeerDiscovery(Set<PeerData> peers) {
|
||||
public PeerDiscovery(Set<Peer> peers) {
|
||||
this.peers = peers;
|
||||
}
|
||||
|
||||
|
@ -49,14 +49,14 @@ public class PeerDiscovery {
|
|||
Thread monitorThread = new Thread(monitor);
|
||||
monitorThread.start();
|
||||
|
||||
for (PeerData peerData : this.peers) {
|
||||
for (Peer peerData : this.peers) {
|
||||
executorPool.execute(new WorkerThread(peerData, executorPool));
|
||||
}
|
||||
|
||||
started.set(true);
|
||||
}
|
||||
|
||||
public void addNewPeerData(PeerData peerData) {
|
||||
public void addNewPeerData(Peer peerData) {
|
||||
logger.debug("add new peer for discovery: {}", peerData);
|
||||
executorPool.execute(new WorkerThread(peerData, executorPool));
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ import org.ethereum.manager.WorldManager;
|
|||
import org.ethereum.net.Command;
|
||||
import org.ethereum.net.MessageQueue;
|
||||
import org.ethereum.net.PeerListener;
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.ethereum.net.message.DisconnectMessage;
|
||||
import org.ethereum.net.message.HelloMessage;
|
||||
import org.ethereum.net.message.Message;
|
||||
|
@ -194,7 +194,7 @@ public class PeerProtocolHandler extends ChannelInboundHandlerAdapter {
|
|||
}
|
||||
|
||||
protected void sendPeers() {
|
||||
Set<PeerData> peers = WorldManager.getInstance().getPeers();
|
||||
Set<Peer> peers = WorldManager.getInstance().getPeers();
|
||||
PeersMessage peersMessage = new PeersMessage(peers);
|
||||
sendMsg(peersMessage);
|
||||
}
|
||||
|
|
|
@ -20,10 +20,7 @@ import static org.ethereum.config.SystemProperties.CONFIG;
|
|||
public class PeerTaster {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger("peerdiscovery");
|
||||
final EthereumPeerTasterHandler handler = new EthereumPeerTasterHandler();
|
||||
|
||||
public PeerTaster() {
|
||||
}
|
||||
private final PeerProtocolHandler handler = new PeerProtocolHandler();
|
||||
|
||||
public void connect(String host, int port) {
|
||||
|
||||
|
@ -34,7 +31,6 @@ public class PeerTaster {
|
|||
Bootstrap b = new Bootstrap();
|
||||
b.group(workerGroup);
|
||||
b.channel(NioSocketChannel.class);
|
||||
|
||||
b.handler(new ChannelInitializer<NioSocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(NioSocketChannel ch) throws Exception {
|
||||
|
@ -43,14 +39,14 @@ public class PeerTaster {
|
|||
ch.pipeline().addLast(handler);
|
||||
}
|
||||
});
|
||||
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONFIG.peerDiscoveryTimeout());
|
||||
|
||||
// Start the client.
|
||||
b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, CONFIG.peerDiscoveryTimeout());
|
||||
ChannelFuture f = b.connect(host, port).sync(); // (5)
|
||||
|
||||
// Wait until the connection is closed.
|
||||
f.channel().closeFuture().sync();
|
||||
logger.debug("connection is closed");
|
||||
logger.debug("Connection is closed");
|
||||
|
||||
} catch (InterruptedException ie) {
|
||||
logger.info("-- ClientPeer: catch (InterruptedException ie) --");
|
||||
|
@ -66,5 +62,4 @@ public class PeerTaster {
|
|||
public HelloMessage getHandshake() {
|
||||
return handler.getHandshake();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package org.ethereum.net.peerdiscovery;
|
||||
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -16,28 +16,26 @@ public class WorkerThread implements Runnable {
|
|||
private final static Logger logger = LoggerFactory.getLogger("peerdiscovery");
|
||||
|
||||
ThreadPoolExecutor poolExecutor;
|
||||
private PeerData peerData;
|
||||
private Peer peerData;
|
||||
private PeerTaster peerTaster;
|
||||
|
||||
public WorkerThread(PeerData peerData, ThreadPoolExecutor poolExecutor) {
|
||||
public WorkerThread(Peer peerData, ThreadPoolExecutor poolExecutor) {
|
||||
this.poolExecutor = poolExecutor;
|
||||
this.peerData = peerData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.info(Thread.currentThread().getName()+" Start. Command = "+ peerData.toString());
|
||||
logger.info("{} start", Thread.currentThread().getName());
|
||||
processCommand();
|
||||
logger.info(Thread.currentThread().getName()+" End.");
|
||||
logger.info("{} end", Thread.currentThread().getName());
|
||||
|
||||
try {Thread.sleep(10000); } catch (InterruptedException e) {logger.error("sleep interrupted");}
|
||||
poolExecutor.execute(this);
|
||||
}
|
||||
|
||||
private void processCommand() {
|
||||
|
||||
try {
|
||||
|
||||
peerTaster = new PeerTaster();
|
||||
peerTaster.connect(peerData.getInetAddress().getHostAddress(), peerData.getPort());
|
||||
|
||||
|
@ -47,9 +45,8 @@ public class WorkerThread implements Runnable {
|
|||
}
|
||||
catch (Throwable e) {
|
||||
if (peerData.isOnline() == true)
|
||||
logger.info("Peer: [ {} ] got offline, due: [ {} ]",
|
||||
peerData.getInetAddress().getHostAddress(),
|
||||
e);
|
||||
logger.info("Peer: [{}] went offline, due to: [{}]",
|
||||
peerData.getInetAddress().getHostAddress(), e);
|
||||
logger.info("Peer: " + peerData.toString() + " isOnline: false");
|
||||
peerData.setOnline(false);
|
||||
} finally {
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -77,7 +78,7 @@ public class SerpentCompiler {
|
|||
|
||||
String[] lexaArr = code.split("\\s+");
|
||||
|
||||
List<String> lexaList = new ArrayList<String>();
|
||||
List<String> lexaList = new ArrayList<>();
|
||||
Collections.addAll(lexaList, lexaArr);
|
||||
|
||||
// Encode push_n numbers
|
||||
|
@ -134,7 +135,7 @@ public class SerpentCompiler {
|
|||
}
|
||||
|
||||
// calc label pos & remove labels
|
||||
HashMap<String, Integer> labels = new HashMap<String, Integer>();
|
||||
Map<String, Integer> labels = new HashMap<>();
|
||||
|
||||
for (int i = 0; i < lexaList.size(); ++i) {
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.math.BigInteger;
|
|||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -19,10 +20,10 @@ import java.util.regex.Pattern;
|
|||
public class SerpentToAssemblyCompiler extends SerpentBaseVisitor<String> {
|
||||
|
||||
private int labelIndex = 0;
|
||||
private ArrayList<String> vars = new ArrayList<String>();
|
||||
private List<String> vars = new ArrayList<>();
|
||||
|
||||
private HashMap<String, Integer> arraysSize = new HashMap<String, Integer>();
|
||||
private List<String> arraysIndex = new ArrayList<String>();
|
||||
private Map<String, Integer> arraysSize = new HashMap<>();
|
||||
private List<String> arraysIndex = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public String visitParse(@NotNull SerpentParser.ParseContext ctx) {
|
||||
|
|
|
@ -133,9 +133,8 @@ public class TrieImpl implements Trie {
|
|||
* @return value
|
||||
*/
|
||||
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));
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ public class ByteUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* 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
|
||||
* @param numBytes the desired size of the resulting byte array
|
||||
|
@ -41,10 +41,10 @@ public class ByteUtil {
|
|||
}
|
||||
|
||||
/**
|
||||
* emitting sign indication byte
|
||||
* Omitting sign indication byte
|
||||
*
|
||||
* @param b - any big integer number
|
||||
* @return
|
||||
* @return a byte array representation of this number without a sign byte
|
||||
*/
|
||||
public static byte[] bigIntegerToBytes(BigInteger b) {
|
||||
if (b == null)
|
||||
|
@ -84,7 +84,7 @@ public class ByteUtil {
|
|||
}
|
||||
|
||||
public static String toHexString(byte[] data) {
|
||||
if (data == null) return "null";
|
||||
if (data == null) return "";
|
||||
else return Hex.toHexString(data);
|
||||
}
|
||||
|
||||
|
@ -129,12 +129,18 @@ public class ByteUtil {
|
|||
public static String nibblesToPrettyString(byte[] nibbles){
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
for (byte nibble : nibbles) {
|
||||
String nibleString = Utils.oneByteToHexString(nibble);
|
||||
String nibleString = oneByteToHexString(nibble);
|
||||
buffer.append("\\x" + nibleString);
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
public static String oneByteToHexString(byte value) {
|
||||
String retVal = Integer.toString(value & 0xFF, 16);
|
||||
if (retVal.length() == 1) retVal = "0" + retVal;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the number of bytes need
|
||||
* to encode the number
|
||||
|
@ -155,6 +161,22 @@ public class ByteUtil {
|
|||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an array of byte arrays to a single string
|
||||
* <br/>
|
||||
* Example: "eth" or "eth shh bzz"
|
||||
*
|
||||
* @return byte arrays as String
|
||||
*/
|
||||
public static String toString(byte[][] arrays) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte[] array : arrays) {
|
||||
sb.append(new String(array)).append(" ");
|
||||
}
|
||||
if(sb.length() > 0) sb.deleteCharAt(sb.length()-1);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param arg - not more that 32 bits
|
||||
* @return - bytes of the value pad with complete to 32 zeroes
|
||||
|
|
|
@ -627,7 +627,7 @@ public class RLP {
|
|||
// It's an item less than 55 bytes long,
|
||||
// data[0] - 0x80 == length of the item
|
||||
if ((msgData[pos] & 0xFF) > OFFSET_SHORT_ITEM
|
||||
&& (msgData[pos] & 0xFF) < OFFSET_LONG_ITEM) {
|
||||
&& (msgData[pos] & 0xFF) <= OFFSET_LONG_ITEM) {
|
||||
|
||||
byte length = (byte) ((msgData[pos] & 0xFF) - OFFSET_SHORT_ITEM);
|
||||
|
||||
|
@ -706,7 +706,7 @@ public class RLP {
|
|||
}
|
||||
|
||||
private static DecodeResult decodeList(byte[] data, int pos, int prevPos, int len) {
|
||||
List<Object> slice = new ArrayList<Object>();
|
||||
List<Object> slice = new ArrayList<>();
|
||||
for (int i = 0; i < len;) {
|
||||
// Get the next item in the data list and append it
|
||||
DecodeResult result = decode(data, pos);
|
||||
|
@ -828,9 +828,7 @@ public class RLP {
|
|||
(srcData.length == 1 && srcData[0] == 0)) {
|
||||
return new byte[]{(byte) 0x80};
|
||||
} if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) {
|
||||
|
||||
return srcData;
|
||||
|
||||
} else if (srcData.length < SIZE_THRESHOLD) {
|
||||
// length = 8X
|
||||
byte length = (byte) (OFFSET_SHORT_ITEM + srcData.length);
|
||||
|
|
|
@ -119,13 +119,6 @@ public class Utils {
|
|||
return Double.parseDouble (version.substring (0, pos - 1));
|
||||
}
|
||||
|
||||
public static String oneByteToHexString(byte value) {
|
||||
String retVal = Integer.toString(value & 0xFF, 16);
|
||||
if (retVal.length() == 1) retVal = "0" + retVal;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
public static String getFromUrl(String urlToRead) {
|
||||
URL url;
|
||||
HttpURLConnection conn;
|
||||
|
|
|
@ -263,7 +263,7 @@ public class Value {
|
|||
output.append("'");
|
||||
for (byte oneByte : asBytes()) {
|
||||
if (oneByte < 16) {
|
||||
output.append("\\x").append(Utils.oneByteToHexString(oneByte));
|
||||
output.append("\\x").append(ByteUtil.oneByteToHexString(oneByte));
|
||||
} else {
|
||||
output.append(Character.valueOf((char)oneByte));
|
||||
}
|
||||
|
@ -278,14 +278,13 @@ public class Value {
|
|||
return "Unexpected type";
|
||||
}
|
||||
|
||||
public int countYourBranchNodes(){
|
||||
public int countBranchNodes() {
|
||||
|
||||
if (this.isList()) {
|
||||
|
||||
List<Object> objList = this.asList();
|
||||
int i = 0;
|
||||
for (Object obj : objList) {
|
||||
i += (new Value(obj)).countYourBranchNodes();
|
||||
i += (new Value(obj)).countBranchNodes();
|
||||
}
|
||||
return i;
|
||||
} else if (this.isBytes()) {
|
||||
|
|
|
@ -312,8 +312,8 @@ public enum OpCode {
|
|||
|
||||
private byte opcode;
|
||||
|
||||
private static final Map<Byte, OpCode> intToTypeMap = new HashMap<Byte, OpCode>();
|
||||
private static final Map<String, Byte> stringToByteMap = new HashMap<String, Byte>();
|
||||
private static final Map<Byte, OpCode> intToTypeMap = new HashMap<>();
|
||||
private static final Map<String, Byte> stringToByteMap = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (OpCode type : OpCode.values()) {
|
||||
|
|
|
@ -4,7 +4,6 @@ import org.ethereum.crypto.HashUtil;
|
|||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.Utils;
|
||||
import org.ethereum.vm.MessageCall.MsgType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -606,7 +605,7 @@ public class Program {
|
|||
// Check if value is ASCII
|
||||
String character = ((byte) 0x20 <= value && value <= (byte) 0x7e) ? new String(new byte[] { value }) : "?";
|
||||
firstLine.append(character).append("");
|
||||
secondLine.append(Utils.oneByteToHexString(value)).append(" ");
|
||||
secondLine.append(ByteUtil.oneByteToHexString(value)).append(" ");
|
||||
|
||||
if ((i + 1) % 8 == 0) {
|
||||
String tmp = String.format("%4s", Integer.toString(i - 7, 16)).replace(" ", "0");
|
||||
|
@ -650,7 +649,7 @@ public class Program {
|
|||
for (int i = 0; memory != null && i < memory.limit(); ++i) {
|
||||
|
||||
byte value = memory.get(i);
|
||||
oneLine.append(Utils.oneByteToHexString(value)).append(" ");
|
||||
oneLine.append(ByteUtil.oneByteToHexString(value)).append(" ");
|
||||
|
||||
if ((i + 1) % 16 == 0) {
|
||||
String tmp = String.format("[%4s]-[%4s]", Integer.toString(i - 15, 16),
|
||||
|
|
|
@ -16,7 +16,7 @@ import org.iq80.leveldb.WriteOptions;
|
|||
|
||||
public class MockDB implements DB {
|
||||
|
||||
Map<ByteArrayWrapper, byte[]> storage = new HashMap<ByteArrayWrapper, byte[]>();
|
||||
Map<ByteArrayWrapper, byte[]> storage = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -4,8 +4,6 @@ import static org.junit.Assert.assertEquals;
|
|||
|
||||
import org.ethereum.net.message.DisconnectMessage;
|
||||
import org.ethereum.net.message.ReasonCode;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -13,27 +11,25 @@ public class DisconnectMessageTest {
|
|||
|
||||
/* DISCONNECT_MESSAGE */
|
||||
|
||||
@Test /* DisconnectMessage 1 */
|
||||
public void test_3() {
|
||||
@Test /* DisconnectMessage 1 - Requested */
|
||||
public void test_1() {
|
||||
|
||||
String disconnectMessageRaw = "C20100";
|
||||
byte[] payload = Hex.decode(disconnectMessageRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
DisconnectMessage disconnectMessage = new DisconnectMessage(rlpList);
|
||||
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
|
||||
System.out.println(disconnectMessage);
|
||||
|
||||
assertEquals(disconnectMessage.getReason(), ReasonCode.REQUESTED);
|
||||
}
|
||||
|
||||
@Test /* DisconnectMessage 2 */
|
||||
public void test_4() {
|
||||
@Test /* DisconnectMessage 2 - TCP Error */
|
||||
public void test_2() {
|
||||
|
||||
String disconnectMessageRaw = "C20101";
|
||||
byte[] payload = Hex.decode(disconnectMessageRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
DisconnectMessage disconnectMessage = new DisconnectMessage(rlpList);
|
||||
DisconnectMessage disconnectMessage = new DisconnectMessage(payload);
|
||||
System.out.println(disconnectMessage);
|
||||
|
||||
assertEquals(disconnectMessage.getReason(), ReasonCode.TCP_ERROR);
|
||||
|
|
|
@ -2,9 +2,11 @@ package org.ethereum.net;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.ethereum.net.message.HelloMessage;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -12,51 +14,76 @@ public class HelloMessageTest {
|
|||
|
||||
/* HELLO_MESSAGE */
|
||||
|
||||
@Test /* HelloMessage 1 */
|
||||
public void test_1() {
|
||||
@Test /* HelloMessage 1 from PeerServer */
|
||||
public void testPeer() {
|
||||
String helloMessageRaw = "F8 80 80 80 B7 45 74 68 " +
|
||||
"65 72 65 75 6D 28 2B 2B 29 2F 50 65 65 72 20 53 " +
|
||||
"65 72 76 65 72 20 5A 65 72 6F 2F 76 30 2E 36 2E " +
|
||||
"38 64 2F 52 65 6C 65 61 73 65 2F 4C 69 6E 75 78 " +
|
||||
"2F 67 2B 2B C0 82 76 5F B8 40 20 17 B9 5D 55 86 " +
|
||||
"AD D0 53 E7 C5 DC C8 11 2D B1 D5 57 ED 83 58 9C " +
|
||||
"4E 0B D2 54 42 F3 9E 41 11 65 5A 48 72 57 AA 7E " +
|
||||
"4E D3 09 E8 B4 D5 5B E5 FA 8D 8D 6E 97 B7 2C 67 " +
|
||||
"D7 6A A0 3E B6 9A D9 81 ED 60";
|
||||
|
||||
String helloMessageRaw = "F8 77 80 0C 80 AD 45 74 " +
|
||||
"68 65 72 65 75 6D 28 2B 2B 29 2F 5A 65 72 6F 47 " +
|
||||
"6F 78 2F 76 30 2E 35 2E 31 2F 6E 63 75 72 73 65 " +
|
||||
"73 2F 4C 69 6E 75 78 2F 67 2B 2B 07 82 76 5F B8 " +
|
||||
"40 D8 83 3B 83 56 0E 0B 12 17 0E 91 69 DC 43 78 " +
|
||||
"42 23 A5 98 42 DE 23 59 E6 D0 3D B3 4C 30 A9 66 " +
|
||||
"C2 DE 3B 4B 25 52 FB 0D 75 95 A1 85 D5 58 F2 E6 " +
|
||||
"69 B5 95 67 4F 52 17 C9 96 EE 14 88 84 82 8B E0 FD";
|
||||
byte[] payload = Hex.decode(helloMessageRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
HelloMessage helloMessage = new HelloMessage(rlpList);
|
||||
helloMessage.parseRLP();
|
||||
HelloMessage helloMessage = new HelloMessage(payload);
|
||||
System.out.println(helloMessage);
|
||||
|
||||
assertEquals(12, helloMessage.getP2PVersion());
|
||||
assertEquals("Ethereum(++)/ZeroGox/v0.5.1/ncurses/Linux/g++", helloMessage.getClientId());
|
||||
assertEquals(7, helloMessage.getCapabilities());
|
||||
assertEquals(0, helloMessage.getP2PVersion());
|
||||
assertEquals("Ethereum(++)/Peer Server Zero/v0.6.8d/Release/Linux/g++", helloMessage.getClientId());
|
||||
assertEquals(0, helloMessage.getCapabilities().size());
|
||||
assertEquals(30303, helloMessage.getListenPort());
|
||||
assertEquals(
|
||||
"D8833B83560E0B12170E9169DC43784223A59842DE2359E6D03DB34C30A966C2DE3B4B2552FB0D7595A185D558F2E669B595674F5217C996EE148884828BE0FD",
|
||||
"2017B95D5586ADD053E7C5DCC8112DB1D557ED83589C4E0BD25442F39E4111655A487257AA7E4ED309E8B4D55BE5FA8D8D6E97B72C67D76AA03EB69AD981ED60",
|
||||
Hex.toHexString(helloMessage.getPeerId()).toUpperCase());
|
||||
}
|
||||
|
||||
@Test /* HelloMessage 2 */
|
||||
public void test_2() {
|
||||
@Test /* HelloMessage 2 from Node */
|
||||
public void testNode() {
|
||||
String helloMessageRaw = "F8 7B 80 80 AE 4E 45 74 68 65 72 65 "
|
||||
+ "75 6D 28 2B 2B 29 2F 5A 65 72 6F 47 6F 78 2F 76 30 "
|
||||
+ "2E 36 2E 39 2F 6E 63 75 72 73 65 73 2F 4C 69 6E 75 "
|
||||
+ "78 2F 67 2B 2B C4 83 65 74 68 82 76 5F B8 40 CA DF "
|
||||
+ "B9 3D 2B B5 FB E2 94 35 84 D9 3E D9 0E 37 46 67 C9 "
|
||||
+ "E8 B2 50 2E 97 46 93 CC C6 B3 D3 70 BD 4C DE 77 38 "
|
||||
+ "D0 B6 26 E3 D2 F3 CA EC C5 9E 13 02 D1 71 1B F5 95 "
|
||||
+ "71 10 60 D7 B4 92 1E 18 B9 76 56";
|
||||
|
||||
String helloMessageRaw = "F87F800B80B5457468657265756D282B2B292F76302E342E332F4554485F4255494C445F545950452F4554485F4255494C445F504C4154464F524D0782765FB840E02B18FBA6B887FB9258469C3AF8E445CC9AE2B5386CAC5F60C4170F822086224E3876555C745A7EC8AC181C7F9701776D94A779604EA12651DE5F4A748D29E1";
|
||||
byte[] payload = Hex.decode(helloMessageRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
HelloMessage helloMessage = new HelloMessage(rlpList);
|
||||
helloMessage.parseRLP();
|
||||
HelloMessage helloMessage = new HelloMessage(payload);
|
||||
helloMessage.parse();
|
||||
System.out.println(helloMessage);
|
||||
|
||||
assertEquals(11, helloMessage.getP2PVersion());
|
||||
assertEquals("Ethereum(++)/v0.4.3/ETH_BUILD_TYPE/ETH_BUILD_PLATFORM", helloMessage.getClientId());
|
||||
assertEquals(7, helloMessage.getCapabilities());
|
||||
assertEquals(0, helloMessage.getP2PVersion());
|
||||
assertEquals("NEthereum(++)/ZeroGox/v0.6.9/ncurses/Linux/g++", helloMessage.getClientId());
|
||||
assertEquals(1, helloMessage.getCapabilities().size());
|
||||
assertEquals("eth", helloMessage.getCapabilities().get(0));
|
||||
assertEquals(30303, helloMessage.getListenPort());
|
||||
assertEquals(
|
||||
"E02B18FBA6B887FB9258469C3AF8E445CC9AE2B5386CAC5F60C4170F822086224E3876555C745A7EC8AC181C7F9701776D94A779604EA12651DE5F4A748D29E1",
|
||||
Hex.toHexString(helloMessage.getPeerId()).toUpperCase() );
|
||||
assertEquals("cadfb93d2bb5fbe2943584d93ed90e374667c9e8b2502e974693ccc6b3d370bd4cde7738d0b626e3d2f3caecc59e1302d1711bf595711060d7b4921e18b97656",
|
||||
Hex.toHexString(helloMessage.getPeerId()));
|
||||
}
|
||||
|
||||
@Test /* HelloMessage 3 from new */
|
||||
public void testFromNew() {
|
||||
String helloAnnouncement = "Ethereum(J)/0.6.0/dev/Windows/Java";
|
||||
byte p2pVersion = 0x00;
|
||||
List<String> capabilities = new ArrayList<>(Arrays.asList("eth", "shh"));
|
||||
short listenPort = (short) 30303;
|
||||
byte[] peerIdBytes = Hex.decode("CAB0D93EEE1F44EF1286367101F1553450E3DDCE"
|
||||
+ "EA45ABCAB0AC21E1EFB48A6610EBE88CE7317EB09229558311BA8B7250911D"
|
||||
+ "7E49562C3988CA3143329DA3EA");
|
||||
|
||||
HelloMessage helloMessage = new HelloMessage(p2pVersion, helloAnnouncement,
|
||||
capabilities, listenPort, peerIdBytes);
|
||||
System.out.println(helloMessage);
|
||||
// rlp encoded hello message
|
||||
String expected = "F8738080A2457468657265756D284A292F302E362E302F6465762F5"
|
||||
+ "7696E646F77732F4A617661C8836574688373686882765FB840CAB0D93EEE1F"
|
||||
+ "44EF1286367101F1553450E3DDCEEA45ABCAB0AC21E1EFB48A6610EBE88CE73"
|
||||
+ "17EB09229558311BA8B7250911D7E49562C3988CA3143329DA3EA";
|
||||
|
||||
assertEquals(expected, Hex.toHexString(helloMessage.getEncoded()).toUpperCase());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,34 +2,55 @@ package org.ethereum.net;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.ethereum.net.message.GetPeersMessage;
|
||||
import org.ethereum.net.message.PeersMessage;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
public class PeersMessageTest {
|
||||
|
||||
/* GET_PEERS */
|
||||
|
||||
@Test /* GetPeersMessage */
|
||||
public void testGetPeers() {
|
||||
|
||||
GetPeersMessage getPeersMessage = new GetPeersMessage();
|
||||
System.out.println(getPeersMessage);
|
||||
|
||||
assertEquals(PeersMessage.class, getPeersMessage.getAnswerMessage());
|
||||
}
|
||||
|
||||
/* PEERS */
|
||||
|
||||
@Test /* PeersMessage 1*/
|
||||
public void test_5() {
|
||||
@Test /* PeersMessage 1 from RLP */
|
||||
public void testPeers_1() {
|
||||
|
||||
String peersMessageRaw = "F89911F84A84364845B482765FB840430BB21ECF73A54AEF511404948C016532406B371EDABD20A478C3ECD22052A0065A7399A6D19594E24B153930E63A3B12B3BA4F30A3CDA1977D60D4060FFF25F84A845163E11282765FB8405F1DBE5E50E92A6B67377E079D986155C0D82D964E65332F524810ED7831A52837F1C0FB042EA2A25548E3B444C337F54C7547B2D877734E2899F40BFA23ED51";
|
||||
String peersMessageRaw = "F8 99 05 F8 4A 84 36 48 45 B4 82 76 "
|
||||
+ "5F B8 40 43 0B B2 1E CF 73 A5 4A EF 51 14 04 94 8C "
|
||||
+ "01 65 32 40 6B 37 1E DA BD 20 A4 78 C3 EC D2 20 52 "
|
||||
+ "A0 06 5A 73 99 A6 D1 95 94 E2 4B 15 39 30 E6 3A 3B "
|
||||
+ "12 B3 BA 4F 30 A3 CD A1 97 7D 60 D4 06 0F FF 25 F8 "
|
||||
+ "4A 84 51 63 E1 12 82 76 5F B8 40 5F 1D BE 5E 50 E9 "
|
||||
+ "2A 6B 67 37 7E 07 9D 98 61 55 C0 D8 2D 96 4E 65 33 "
|
||||
+ "2F 52 48 10 ED 78 31 A5 28 37 F1 C0 FB 04 2E A2 A2 "
|
||||
+ "55 48 E3 B4 44 C3 37 F5 4C 75 47 B2 D8 77 73 4E 28 "
|
||||
+ "99 F4 0B FA 23 ED 51";
|
||||
byte[] payload = Hex.decode(peersMessageRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
PeersMessage peersMessage= new PeersMessage(rlpList);
|
||||
PeersMessage peersMessage= new PeersMessage(payload);
|
||||
System.out.println(peersMessage);
|
||||
|
||||
assertEquals(2, peersMessage.getPeers().size());
|
||||
|
||||
Iterator<PeerData> it = peersMessage.getPeers().iterator(); it.next();
|
||||
PeerData peerData = it.next();
|
||||
Iterator<Peer> it = peersMessage.getPeers().iterator(); it.next();
|
||||
Peer peerData = it.next();
|
||||
|
||||
assertEquals("/81.99.225.18", peerData.getInetAddress().toString());
|
||||
assertEquals(30303, peerData.getPort());
|
||||
|
@ -37,24 +58,42 @@ public class PeersMessageTest {
|
|||
Hex.toHexString(peerData.getPeerId()).toUpperCase());
|
||||
}
|
||||
|
||||
@Test /* PeersMessage 2 from constructor */
|
||||
public void testPeers_2() throws UnknownHostException {
|
||||
Set<Peer> peers = new HashSet<>();
|
||||
peers.add(new Peer(InetAddress.getByName("82.217.72.169").getAddress(), 30303, Hex.decode("585764a3c49a3838c69ad0855abfeb5672f71b072af62082b5679961781100814b8de88a8fbc1da7c73791f88159d73b5d2a13a5579535d603e045c3db5cbb75")));
|
||||
peers.add(new Peer(InetAddress.getByName("192.168.1.193").getAddress(), 30303, new byte[0]));
|
||||
PeersMessage peersMessage = new PeersMessage(peers);
|
||||
System.out.println(peersMessage.toString());
|
||||
|
||||
String expected = "f85905f84b8452d948a982765fb840585764a3c49a3838c69ad0855abfeb5672f71b072af62082b5679961781100814b8de88a8fbc1da7c73791f88159d73b5d2a13a5579535d603e045c3db5cbb75c0ca84c0a801c182765f80c0";
|
||||
assertEquals(expected, Hex.toHexString(peersMessage.getEncoded()));
|
||||
}
|
||||
|
||||
@Test /* Peers msg parsing performance */
|
||||
public void test_7() throws UnknownHostException {
|
||||
public void testPeersPerformance() throws UnknownHostException {
|
||||
|
||||
long time1 = System.currentTimeMillis();
|
||||
for (int i = 0; i < 20000; ++i) {
|
||||
|
||||
String peersPacketRaw = "F89911F84A84364845B482765FB840430BB21ECF73A54AEF511404948C016532406B371EDABD20A478C3ECD22052A0065A7399A6D19594E24B153930E63A3B12B3BA4F30A3CDA1977D60D4060FFF25F84A845163E11282765FB8405F1DBE5E50E92A6B67377E079D986155C0D82D964E65332F524810ED7831A52837F1C0FB042EA2A25548E3B444C337F54C7547B2D877734E2899F40BFA23ED51";
|
||||
String peersPacketRaw = "F8 99 05 F8 4A 84 36 48 45 B4 82 76 "
|
||||
+ "5F B8 40 43 0B B2 1E CF 73 A5 4A EF 51 14 04 94 "
|
||||
+ "8C 01 65 32 40 6B 37 1E DA BD 20 A4 78 C3 EC D2 "
|
||||
+ "20 52 A0 06 5A 73 99 A6 D1 95 94 E2 4B 15 39 30 "
|
||||
+ "E6 3A 3B 12 B3 BA 4F 30 A3 CD A1 97 7D 60 D4 06 "
|
||||
+ "0F FF 25 F8 4A 84 51 63 E1 12 82 76 5F B8 40 5F "
|
||||
+ "1D BE 5E 50 E9 2A 6B 67 37 7E 07 9D 98 61 55 C0 "
|
||||
+ "D8 2D 96 4E 65 33 2F 52 48 10 ED 78 31 A5 28 37 "
|
||||
+ "F1 C0 FB 04 2E A2 A2 55 48 E3 B4 44 C3 37 F5 4C "
|
||||
+ "75 47 B2 D8 77 73 4E 28 99 F4 0B FA 23 ED 51";
|
||||
|
||||
byte[] payload = Hex.decode(peersPacketRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
PeersMessage peersMessage = new PeersMessage(rlpList);
|
||||
peersMessage.parseRLP();
|
||||
PeersMessage peersMessage = new PeersMessage(payload);
|
||||
peersMessage.parse();
|
||||
}
|
||||
long time2 = System.currentTimeMillis();
|
||||
|
||||
System.out.println("20,000 PEERS packets parsing: " + (time2 - time1) + "(msec)");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.ethereum.net;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.ethereum.net.message.HelloMessage;
|
||||
import org.ethereum.net.message.StatusMessage;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
@ -11,46 +10,40 @@ public class StatusMessageTest {
|
|||
|
||||
/* STATUS_MESSAGE */
|
||||
|
||||
@Test /* StatusMessage 1 from PeerServer */
|
||||
public void testPeer() {
|
||||
@Test /* StatusMessage 1 from network */
|
||||
public void test_1() {
|
||||
String statusMessageRaw = "";
|
||||
|
||||
byte[] payload = Hex.decode(statusMessageRaw);
|
||||
|
||||
StatusMessage statusMessage = new StatusMessage(payload);
|
||||
System.out.println(statusMessage);
|
||||
|
||||
assertEquals(0, statusMessage.getGenesisHash());
|
||||
assertEquals(0, statusMessage.getNetworkId());
|
||||
assertEquals(0, statusMessage.getProtocolVersion());
|
||||
assertEquals(0, statusMessage.getTotalDifficulty());
|
||||
assertEquals(0, statusMessage.getBestHash());
|
||||
assertEquals(0, statusMessage.getNetworkId());
|
||||
assertEquals("", Hex.toHexString(statusMessage.getTotalDifficulty()));
|
||||
assertEquals("", Hex.toHexString(statusMessage.getBestHash()));
|
||||
assertEquals("", Hex.toHexString(statusMessage.getGenesisHash()));
|
||||
}
|
||||
|
||||
@Test /* HelloMessage 2 from Node */
|
||||
public void testNode() {
|
||||
String helloMessageRaw = "F8 80 80 80 B7 45 74 68 " +
|
||||
"65 72 65 75 6D 28 2B 2B 29 2F 50 65 65 72 20 53 " +
|
||||
"65 72 76 65 72 20 5A 65 72 6F 2F 76 30 2E 36 2E " +
|
||||
"38 64 2F 52 65 6C 65 61 73 65 2F 4C 69 6E 75 78 " +
|
||||
"2F 67 2B 2B C0 82 76 5F B8 40 20 17 B9 5D 55 86 " +
|
||||
"AD D0 53 E7 C5 DC C8 11 2D B1 D5 57 ED 83 58 9C " +
|
||||
"4E 0B D2 54 42 F3 9E 41 11 65 5A 48 72 57 AA 7E " +
|
||||
"4E D3 09 E8 B4 D5 5B E5 FA 8D 8D 6E 97 B7 2C 67 " +
|
||||
"D7 6A A0 3E B6 9A D9 81 ED 60";
|
||||
@Test /* StatusMessage 1 from new */
|
||||
public void test_2() {
|
||||
byte protocolVersion = 0, networkId = 0;
|
||||
byte[] totalDifficulty = Hex.decode("ff");
|
||||
byte[] bestHash = Hex.decode("ff");
|
||||
byte[] genesisHash = Hex.decode("ff");
|
||||
|
||||
byte[] payload = Hex.decode(helloMessageRaw);
|
||||
HelloMessage helloMessage = new HelloMessage(payload);
|
||||
helloMessage.parse();
|
||||
System.out.println(helloMessage);
|
||||
StatusMessage statusMessage = new StatusMessage(protocolVersion,
|
||||
networkId, totalDifficulty, bestHash, genesisHash);
|
||||
System.out.println(statusMessage);
|
||||
|
||||
assertEquals(0, helloMessage.getP2PVersion());
|
||||
assertEquals("Ethereum(++)/Nick/v0.6.8d/Release/Linux/g++", helloMessage.getClientId());
|
||||
assertEquals(3, helloMessage.getCapabilities().size());
|
||||
assertEquals(30303, helloMessage.getListenPort());
|
||||
assertEquals(
|
||||
"2017B95D5586ADD053E7C5DCC8112DB1D557ED83589C4E0BD25442F39E4111655A487257AA7E4ED309E8B4D55BE5FA8D8D6E97B72C67D76AA03EB69AD981ED60",
|
||||
Hex.toHexString(helloMessage.getPeerId()).toUpperCase() );
|
||||
String expected = "ff";
|
||||
assertEquals(expected, statusMessage.getEncoded());
|
||||
|
||||
assertEquals(0, statusMessage.getProtocolVersion());
|
||||
assertEquals(0, statusMessage.getNetworkId());
|
||||
assertEquals("", Hex.toHexString(statusMessage.getTotalDifficulty()));
|
||||
assertEquals("", Hex.toHexString(statusMessage.getBestHash()));
|
||||
assertEquals("", Hex.toHexString(statusMessage.getGenesisHash()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ import org.ethereum.crypto.ECKey;
|
|||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.net.message.TransactionsMessage;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.ethereum.util.RLPList;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -22,7 +20,7 @@ public class TransactionsMessageTest {
|
|||
/* TRANSACTIONS */
|
||||
|
||||
@Test /* Transactions message 1 */
|
||||
public void test_8() {
|
||||
public void test_1() {
|
||||
|
||||
String txsPacketRaw = "f86e12f86b04648609184e72a00094cd2a3d9f938e13cd947ec05abc7fe734df8dd826"
|
||||
+ "881bc16d674ec80000801ba05c89ebf2b77eeab88251e553f6f9d53badc1d800"
|
||||
|
@ -30,9 +28,8 @@ public class TransactionsMessageTest {
|
|||
+ "daa3653a8d9f424c6a3265f06c";
|
||||
|
||||
byte[] payload = Hex.decode(txsPacketRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
TransactionsMessage transactionsMessage = new TransactionsMessage(rlpList);
|
||||
TransactionsMessage transactionsMessage = new TransactionsMessage(payload);
|
||||
System.out.println(transactionsMessage);
|
||||
|
||||
assertEquals(1, transactionsMessage.getTransactions().size());
|
||||
|
@ -45,7 +42,7 @@ public class TransactionsMessageTest {
|
|||
assertEquals("cd2a3d9f938e13cd947ec05abc7fe734df8dd826", Hex.toHexString(tx.getReceiveAddress()));
|
||||
assertEquals("64", Hex.toHexString(tx.getGasPrice()));
|
||||
assertEquals("09184e72a000", Hex.toHexString(tx.getGasLimit()));
|
||||
assertEquals("null", ByteUtil.toHexString(tx.getData()));
|
||||
assertEquals("", ByteUtil.toHexString(tx.getData()));
|
||||
|
||||
assertEquals("1b", Hex.toHexString(new byte[] { tx.getSignature().v }));
|
||||
assertEquals("5c89ebf2b77eeab88251e553f6f9d53badc1d800bbac02d830801c2aa94a4c9f", Hex.toHexString(tx.getSignature().r.toByteArray()));
|
||||
|
@ -53,7 +50,7 @@ public class TransactionsMessageTest {
|
|||
}
|
||||
|
||||
@Test /* Transactions message 2 */
|
||||
public void test_9() {
|
||||
public void test_2() {
|
||||
|
||||
String txsPacketRaw = "f9025012f89d8080940000000000000000000000000000000000000000860918"
|
||||
+ "4e72a000822710b3606956330c0d630000003359366000530a0d630000003359"
|
||||
|
@ -76,15 +73,13 @@ public class TransactionsMessageTest {
|
|||
+ "d7393152a7fbe41530e5bb8ac8f35433e5931b";
|
||||
|
||||
byte[] payload = Hex.decode(txsPacketRaw);
|
||||
RLPList rlpList = RLP.decode2(payload);
|
||||
|
||||
TransactionsMessage transactionsMessage = new TransactionsMessage(rlpList);
|
||||
TransactionsMessage transactionsMessage = new TransactionsMessage(payload);
|
||||
System.out.println(transactionsMessage);
|
||||
|
||||
assertEquals(3, transactionsMessage.getTransactions().size());
|
||||
|
||||
Transaction tx =
|
||||
transactionsMessage.getTransactions().get(0);
|
||||
Transaction tx = transactionsMessage.getTransactions().get(0);
|
||||
|
||||
assertEquals("1b9d9456293cbcbc2f28a0fdc67028128ea571b033fb0e21d0ee00bcd6167e5d",
|
||||
Hex.toHexString(tx.getHash()));
|
||||
|
@ -148,7 +143,7 @@ public class TransactionsMessageTest {
|
|||
}
|
||||
|
||||
@Test /* Transactions msg encode */
|
||||
public void test15() throws Exception {
|
||||
public void test_3() throws Exception {
|
||||
|
||||
String expected = "f87312f870808b00d3c21bcecceda10000009479b08ad8787060333663d19704909ee7b1903e588609184e72a000824255801ca00f410a70e42b2c9854a8421d32c87c370a2b9fff0a27f9f031bb4443681d73b5a018a7dc4c4f9dee9f3dc35cb96ca15859aa27e219a8e4a8547be6bd3206979858";
|
||||
|
||||
|
@ -166,11 +161,11 @@ public class TransactionsMessageTest {
|
|||
tx.sign(privKey);
|
||||
tx.getEncoded();
|
||||
|
||||
List<Transaction> txList = new ArrayList<Transaction>();
|
||||
List<Transaction> txList = new ArrayList<>();
|
||||
txList.add(tx);
|
||||
TransactionsMessage transactionsMessage = new TransactionsMessage(txList);
|
||||
|
||||
assertEquals(expected, Hex.toHexString( transactionsMessage.getPayload()) );
|
||||
assertEquals(expected, Hex.toHexString(transactionsMessage.getEncoded()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -642,7 +642,7 @@ public class TrieTest {
|
|||
|
||||
if(massiveUpdateFromDBEnabled) {
|
||||
List<String> randomWords = Arrays.asList(randomDictionary.split(","));
|
||||
HashMap<String, String> testerMap = new HashMap<>();
|
||||
Map<String, String> testerMap = new HashMap<>();
|
||||
|
||||
TrieImpl trie = new TrieImpl(mockDb);
|
||||
Random generator = new Random();
|
||||
|
|
|
@ -23,9 +23,33 @@ public class ByteUtilTest {
|
|||
// fail("Not yet implemented");
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testToStringDoubleByteArray_1() {
|
||||
String expected = "eth";
|
||||
byte[][] input = new byte[][]{"eth".getBytes()};
|
||||
String result = ByteUtil.toString(input);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringDoubleByteArray_2() {
|
||||
String expected = "eth shh";
|
||||
byte[][] input = new byte[][]{"eth".getBytes(), "shh".getBytes()};
|
||||
String result = ByteUtil.toString(input);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToStringDoubleByteArray_3() {
|
||||
String expected = "";
|
||||
byte[][] input = new byte[0][];
|
||||
String result = ByteUtil.toString(input);
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToHexString() {
|
||||
assertEquals("null", ByteUtil.toHexString(null));
|
||||
assertEquals("", ByteUtil.toHexString(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -305,7 +305,7 @@ public class RLPTest {
|
|||
String tx = "F86E12F86B80881BC16D674EC8000094CD2A3D9F938E13CD947EC05ABC7FE734DF8DD8268609184E72A00064801BA0C52C114D4F5A3BA904A9B3036E5E118FE0DBB987FE3955DA20F2CD8F6C21AB9CA06BA4C2874299A55AD947DBC98A25EE895AABF6B625C26C435E84BFD70EDF2F69";
|
||||
byte[] payload = Hex.decode(tx);
|
||||
|
||||
Queue<Integer> index = new LinkedList<Integer>();
|
||||
Queue<Integer> index = new LinkedList<>();
|
||||
RLP.fullTraverse(payload, 0, 0, payload.length, 1, index);
|
||||
|
||||
// TODO: assert lenght overflow while parsing list in RLP
|
||||
|
|
|
@ -50,8 +50,7 @@ public class ValueTest {
|
|||
|
||||
String testRlp = "f7808080d387206f72726563748a626574656c676575736580d387207870726573738a70726564696361626c658080808080808080808080";
|
||||
|
||||
Value val =
|
||||
Value.fromRlpEncoded(Hex.decode(testRlp));
|
||||
Value val = Value.fromRlpEncoded(Hex.decode(testRlp));
|
||||
|
||||
assertEquals(testRlp, Hex.toHexString(val.encode()));
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ import org.ethereum.core.Wallet;
|
|||
import org.ethereum.db.ContractDetails;
|
||||
import org.ethereum.util.ByteUtil;
|
||||
import org.ethereum.util.Utils;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.spongycastle.util.BigIntegers;
|
||||
|
@ -26,8 +25,6 @@ import java.math.BigInteger;
|
|||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* www.ethereumJ.com
|
||||
* @author: Roman Mandeleil
|
||||
|
|
|
@ -10,7 +10,7 @@ import javax.swing.table.AbstractTableModel;
|
|||
|
||||
|
||||
import org.ethereum.geo.IpGeoDB;
|
||||
import org.ethereum.net.client.PeerData;
|
||||
import org.ethereum.net.client.Peer;
|
||||
import org.ethereum.net.message.HelloMessage;
|
||||
import org.ethereum.util.Utils;
|
||||
|
||||
|
@ -23,7 +23,7 @@ import com.maxmind.geoip.Location;
|
|||
*/
|
||||
public class PeersTableModel extends AbstractTableModel {
|
||||
|
||||
private List<PeerInfo> peerInfoList = new ArrayList<PeerInfo>();
|
||||
private List<PeerInfo> peerInfoList = new ArrayList<>();
|
||||
Timer updater = new Timer();
|
||||
|
||||
public PeersTableModel() {
|
||||
|
@ -111,11 +111,11 @@ public class PeersTableModel extends AbstractTableModel {
|
|||
synchronized (peerInfoList) {
|
||||
peerInfoList.clear();
|
||||
|
||||
final Set<PeerData> peers = UIEthereumManager.ethereum.getPeers();
|
||||
final Set<Peer> peers = UIEthereumManager.ethereum.getPeers();
|
||||
|
||||
synchronized (peers){
|
||||
|
||||
for (PeerData peer : peers) {
|
||||
for (Peer peer : peers) {
|
||||
InetAddress addr = peer.getInetAddress();
|
||||
Location cr = IpGeoDB.getLocationForIp(addr);
|
||||
peerInfoList.add(new PeerInfo(cr, addr, peer.isOnline(), peer.getHandshake(), peer.getLastCheckTime()));
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.ethereum.gui;
|
|||
|
||||
import org.ethereum.core.Block;
|
||||
import org.ethereum.core.Transaction;
|
||||
import org.ethereum.facade.Repository;
|
||||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.vm.*;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
|
|
@ -38,7 +38,6 @@ import org.ethereum.manager.WorldManager;
|
|||
import org.ethereum.util.Utils;
|
||||
import org.ethereum.vm.DataWord;
|
||||
import org.ethereum.vm.Program;
|
||||
import org.spongycastle.util.encoders.DecoderException;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
import java.awt.Component;
|
||||
|
|
Loading…
Reference in New Issue