use of org.aion.p2p.INode in project aion by aionnetwork.
the class NodeMgr method getRandomRealtime.
public INode getRandomRealtime(long bbn) {
List<Integer> keysArr = new ArrayList<>();
for (Node n : activeNodes.values()) {
if ((n.getBestBlockNumber() == 0) || (n.getBestBlockNumber() > bbn)) {
keysArr.add(n.getIdHash());
}
}
int nodesCount = keysArr.size();
if (nodesCount > 0) {
Random r = new Random(System.currentTimeMillis());
try {
int randomNodeKeyIndex = r.nextInt(keysArr.size());
int randomNodeKey = keysArr.get(randomNodeKeyIndex);
return this.getActiveNode(randomNodeKey);
} catch (IllegalArgumentException e) {
return null;
}
} else
return null;
}
use of org.aion.p2p.INode in project aion by aionnetwork.
the class NodeMgr method updateAllNodesInfo.
public void updateAllNodesInfo(INode _n) {
Node n = (Node) _n;
if (n.hasFullInfo()) {
int fullHash = n.getFullHash();
if (allNodes.containsKey(fullHash)) {
Node orig = allNodes.get(fullHash);
// pull out metric.
orig.copyNodeStatus(n);
}
}
}
use of org.aion.p2p.INode in project aion by aionnetwork.
the class BlockPropagationTest method testIgnoreSameBlock.
@Test
public void testIgnoreSameBlock() {
List<ECKey> accounts = generateDefaultAccounts();
StandaloneBlockchain.Bundle bundle = new StandaloneBlockchain.Builder().withValidatorConfiguration("simple").withDefaultAccounts(accounts).build();
MiningBlock block = bundle.bc.createNewMiningBlock(bundle.bc.getGenesis(), Collections.EMPTY_LIST, true);
assertThat(block.getNumber()).isEqualTo(1);
byte[] sender = HashUtil.h256("node1".getBytes());
byte[] receiver = HashUtil.h256("receiver".getBytes());
NodeMock senderMock = new NodeMock(sender, 1);
NodeMock receiverMock = new NodeMock(receiver, 0);
Map<Integer, INode> node = new HashMap<>();
node.put(1, senderMock);
node.put(2, receiverMock);
AtomicInteger times = new AtomicInteger();
P2pMock p2pMock = new P2pMock(node) {
@Override
public void send(int _nodeId, String s, Msg _msg) {
if (_nodeId != receiverMock.getIdHash()) {
throw new RuntimeException("should only send to receiver");
}
times.getAndIncrement();
}
};
StandaloneBlockchain.Bundle anotherBundle = new StandaloneBlockchain.Builder().withValidatorConfiguration("simple").withDefaultAccounts(accounts).withEventManger(this.loadEventMgr()).build();
assertThat(bundle.bc.genesis.getHash()).isEqualTo(anotherBundle.bc.genesis.getHash());
SyncStats syncStats = new SyncStats(bundle.bc.getBestBlock().getNumber(), true);
BlockPropagationHandler handler = new BlockPropagationHandler(1024, // NOTE: not the same blockchain that generated the block
anotherBundle.bc, syncStats, p2pMock, anotherBundle.bc.getBlockHeaderValidator(), false, (byte) 2, new AionPendingStateImpl(anotherBundle.bc, blockEnergyUpperBound, pendingTransactionTimeout, enablePoolBackup, enableSeedMode, enablePoolDump, new PendingTxCallback(new ArrayList<>()), new NetworkBestBlockCallback(AionImpl.inst()), new TransactionBroadcastCallback(AionImpl.inst()), true));
// block is processed
assertThat(handler.processIncomingBlock(senderMock.getIdHash(), "test", block)).isEqualTo(BlockPropagationHandler.PropStatus.PROP_CONNECTED);
assertThat(handler.processIncomingBlock(senderMock.getIdHash(), "test", block)).isEqualTo(BlockPropagationHandler.PropStatus.DROPPED);
assertThat(times.get()).isEqualTo(1);
}
use of org.aion.p2p.INode in project aion by aionnetwork.
the class SyncMgrTest method testRequestBodies_withFilteringOnBlockNumberAndRemainingHeaders.
@Test
public void testRequestBodies_withFilteringOnBlockNumberAndRemainingHeaders() {
BlockHeader header1 = mock(BlockHeader.class);
when(header1.getNumber()).thenReturn(bestBlockNumber);
byte[] hash1 = Hex.decode("6fd8dae3304a9864f460ec7aec21bc94e14e34876e5dddd0a74d9c68ac7bc9ed");
when(header1.getHash()).thenReturn(hash1);
when(header1.getTxTrieRootWrapper()).thenReturn(EMPTY_TRIE_HASH);
BlockHeader header2 = mock(BlockHeader.class);
when(header2.getNumber()).thenReturn(bestBlockNumber + 1);
when(header2.getTxTrieRootWrapper()).thenReturn(EMPTY_TRIE_HASH);
byte[] hash2 = Hex.decode("f2652dde61042e9306dce95ecdc41a1be2be7eb374f19427aef2a79101b471ea");
when(header2.getHash()).thenReturn(hash2);
List<BlockHeader> list = new ArrayList<>();
list.add(header1);
list.add(header2);
INode peer1 = mock(INode.class);
when(peer1.getIdHash()).thenReturn(1);
when(peer1.getIdShort()).thenReturn("peer1");
when(peer1.getBestBlockNumber()).thenReturn(2 * bestBlockNumber);
// ensure that peer1 exists in the syncHeaderRequestManager
syncMgr.syncHeaderRequestManager.assertUpdateActiveNodes(Map.of(1, peer1), null, null, Set.of(1), Set.of(1), 2 * bestBlockNumber);
syncMgr.syncHeaderRequestManager.storeHeaders(1, list);
syncMgr.syncHeaderRequestManager.runInMode(1, SyncMode.NORMAL);
syncMgr.requestBodies(1, "peer1");
// ensure that 1 request was sent
verify(p2pMgr, never()).send(anyInt(), anyString(), any(ReqBlocksBodies.class));
assertThat(syncMgr.syncHeaderRequestManager.matchAndDropHeaders(1, 1, EMPTY_TRIE_HASH)).contains(header2);
}
use of org.aion.p2p.INode in project aion by aionnetwork.
the class SyncHeaderRequestManager method updateActiveNodes.
/**
* Updates the internally tracked states according to the given active peer list.
*
* <ol>
* <li>Ensures the inactive peers are dropped from all internal tracking and new peers are
* added according to the provided list of active connections.
* <li>Updates the best known block number for all active peers and the known network height.
* <li>Booked peers are checked for a change in their status based on the availability defined
* in {@link RequestState#tryMakeAvailable()} which takes into account the number of
* header requests allowed per second.
* </ol>
*/
private void updateActiveNodes(Map<Integer, INode> current) {
// find entries in the knownActiveNodes set that are not in the current map
Set<Integer> dropped = knownActiveNodes.stream().filter(node -> !current.containsKey(node)).collect(Collectors.toSet());
// remove dropped connections
for (Integer id : dropped) {
storedHeaders.remove(id);
bookedPeerStates.remove(id);
availablePeerStates.remove(id);
}
// add new peers and update best block for known peers
for (INode node : current.values()) {
Integer id = node.getIdHash();
if (bookedPeerStates.containsKey(id)) {
// update best
bookedPeerStates.get(id).lastBestBlock = node.getBestBlockNumber();
} else if (availablePeerStates.containsKey(id)) {
// update best
availablePeerStates.get(id).lastBestBlock = node.getBestBlockNumber();
} else {
// add peer
availablePeerStates.put(id, new RequestState(id, node.getIdShort(), node.getBestBlockNumber()));
}
// update the known network height
networkHeight = Math.max(networkHeight, node.getBestBlockNumber());
}
// update known active nodes
knownActiveNodes.clear();
knownActiveNodes.addAll(current.keySet());
// reset booked states if now available
if (!bookedPeerStates.isEmpty()) {
// check if any of the booked states have become available
Iterator<RequestState> states = bookedPeerStates.values().iterator();
while (states.hasNext()) {
RequestState currentState = states.next();
if (currentState.tryMakeAvailable()) {
availablePeerStates.put(currentState.id, currentState);
states.remove();
}
}
}
}
Aggregations