package org.ethereum.db; import org.apache.commons.lang3.tuple.Pair; import org.ethereum.datasource.DataSourceArray; import org.ethereum.datasource.ObjectDataSource; import org.ethereum.datasource.Serializer; import org.ethereum.datasource.Source; import org.ethereum.datasource.leveldb.LevelDbDataSource; import org.ethereum.net.rlpx.Node; import org.ethereum.util.RLP; import org.ethereum.util.RLPList; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.math.BigInteger; /** * Source for {@link org.ethereum.net.rlpx.Node} also known as Peers */ public class PeerSource { private static final Logger logger = LoggerFactory.getLogger("db"); // for debug purposes public static PeerSource INST; private Source<byte[], byte[]> src; DataSourceArray<Pair<Node, Integer>> nodes; public static final Serializer<Pair<Node, Integer>, byte[]> NODE_SERIALIZER = new Serializer<Pair<Node, Integer>, byte[]>(){ @Override public byte[] serialize(Pair<Node, Integer> value) { byte[] nodeRlp = value.getLeft().getRLP(); byte[] nodeIsDiscovery = RLP.encodeByte(value.getLeft().isDiscoveryNode() ? (byte) 1 : 0); byte[] savedReputation = RLP.encodeBigInteger(BigInteger.valueOf(value.getRight())); return RLP.encodeList(nodeRlp, nodeIsDiscovery, savedReputation); } @Override public Pair<Node, Integer> deserialize(byte[] bytes) { if (bytes == null) return null; RLPList nodeElement = (RLPList) RLP.decode2(bytes).get(0); byte[] nodeRlp = nodeElement.get(0).getRLPData(); byte[] nodeIsDiscovery = nodeElement.get(1).getRLPData(); byte[] savedReputation = nodeElement.get(2).getRLPData(); Node node = new Node(nodeRlp); node.setDiscoveryNode(nodeIsDiscovery != null); return Pair.of(node, savedReputation == null ? 0 : (new BigInteger(1, savedReputation)).intValue()); } }; public PeerSource(Source<byte[], byte[]> src) { this.src = src; INST = this; this.nodes = new DataSourceArray<>( new ObjectDataSource<>(src, NODE_SERIALIZER, 512)); } public DataSourceArray<Pair<Node, Integer>> getNodes() { return nodes; } public void clear() { if (src instanceof LevelDbDataSource) { ((LevelDbDataSource) src).reset(); this.nodes = new DataSourceArray<>( new ObjectDataSource<>(src, NODE_SERIALIZER, 512)); } else { throw new RuntimeException("Not supported"); } } }