Skip to content

Commit 334bf9c

Browse files
committed
[FEAT] Add some features and fix few bugs:
- Now multiple loggers can be used for a single scenario run - Some refactoring for names - Added new compact block for bitcoin according to BIP158 - Newer bitcoin nodes support compact blocks - Lowered the number of default nodes in Bitcoin network to a number close to 8000 (reported by https://www.dsn.kastel.kit.edu/bitcoin/) which is seems to be closer to reality than 16000 reported by https://bitnodes.io/ - Added new logging event: BlockchainReorgEvent - Added new logger for block propagation delay
1 parent b8d2269 commit 334bf9c

30 files changed

+440
-95
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ Currently, the following consensus algorithms are implemented in JABS:
105105
## Roadmap ##
106106

107107
- [x] Add new block mining process that can support adjustable difficulty.
108-
- [ ] Add multiple loggers and scenarios in main class.
108+
- [x] Add multiple loggers and scenarios in main class.
109109
- [ ] Add detailed comparison with other simulators in README.md.
110110
- [ ] Add new network latency stats that has countries instead of continents.
111111
- [ ] Add events for network churn.

src/main/java/jabs/Main.java

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
package jabs;
22

3-
import jabs.log.AbstractLogger;
4-
import jabs.log.BlockConfirmationLogger;
5-
import jabs.log.BlockGenerationLogger;
3+
import jabs.log.*;
4+
import jabs.network.stats.sixglobalregions.GlobalNetworkStats6Region;
5+
import jabs.network.stats.sixglobalregions.SixRegions;
66
import jabs.scenario.AbstractScenario;
77
import jabs.scenario.BitcoinGlobalNetworkScenario;
88
import jabs.scenario.NormalEthereumNetworkScenario;
99
import jabs.scenario.PBFTLANScenario;
10+
import jabs.simulator.randengine.RandomnessEngine;
1011

1112
import java.io.IOException;
1213
import java.nio.file.Paths;
@@ -21,28 +22,33 @@ public class Main {
2122
*/
2223
public static void main(String[] args) throws IOException {
2324
AbstractScenario scenario;
24-
AbstractLogger logger;
2525

2626
// Simulate one day in the life of Bitcoin network
2727
// Nakamoto protocol with block every 600 seconds
28-
// Around 16000 nodes with 30 miners
29-
logger = new BlockConfirmationLogger(Paths.get("_output/bitcoin-simulation-log.csv"));
30-
scenario = new BitcoinGlobalNetworkScenario("One day in the life of Bitcoin", 1, logger,
28+
// Around 8000 nodes with 30 miners
29+
scenario = new BitcoinGlobalNetworkScenario("One day in the life of Bitcoin", 1,
3130
86400, 600, 6);
31+
scenario.AddNewLogger(new BlockchainReorgLogger(Paths.get("_output/bitcoin-reorgs-log.csv")));
32+
scenario.AddNewLogger(new BlockConfirmationLogger(Paths.get("_output/bitcoin-confirmations-log.csv")));
33+
scenario.AddNewLogger(new BlockDeliveryLogger(Paths.get("_output/bitcoin-block-delivery-log.csv")));
34+
scenario.AddNewLogger(new BlockPropagationDelayLogger(
35+
Paths.get("_output/bitcoin-50-propagation-delay-log.csv"),0.5));
36+
scenario.AddNewLogger(new BlockPropagationDelayLogger(
37+
Paths.get("_output/bitcoin-90-propagation-delay-log.csv"),0.9));
3238
scenario.run();
3339

3440
// Simulate 1 hour in the life of Ethereum network
3541
// Ghost protocol with blocks every 14 seconds on average
3642
// Around 6000 nodes with 37 miners
37-
logger = new BlockGenerationLogger(Paths.get("_output/ethereum-simulation-log.csv"));
38-
scenario = new NormalEthereumNetworkScenario("One day in the life of Ethereum", 1, logger,
43+
scenario = new NormalEthereumNetworkScenario("One hour in the life of Ethereum", 1,
3944
3600, 14);
45+
scenario.AddNewLogger(new BlockGenerationLogger(Paths.get("_output/ethereum-simulation-log.csv")));
4046
scenario.run();
4147

4248
// Simulate PBFT Lan network of 40 nodes for 1 hour
43-
logger = new BlockGenerationLogger(Paths.get("_output/pbft-simulation-log.csv"));
44-
scenario = new PBFTLANScenario("24 hours of a PBFT lan Network", 1, logger,
49+
scenario = new PBFTLANScenario("One hour of a PBFT lan Network", 1,
4550
40, 3600);
51+
scenario.AddNewLogger(new BlockGenerationLogger(Paths.get("_output/pbft-simulation-log.csv")));
4652
scenario.run();
4753
}
4854
}

src/main/java/jabs/consensus/algorithm/NakamotoConsensus.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,34 @@
66
import jabs.consensus.blockchain.LocalBlockTree;
77
import jabs.simulator.Simulator;
88
import jabs.simulator.event.BlockConfirmationEvent;
9+
import jabs.simulator.event.BlockchainReorgEvent;
910

1011
public class NakamotoConsensus<B extends SingleParentBlock<B>, T extends Tx<T>>
1112
extends AbstractChainBasedConsensus<B, T> {
12-
private int longestChainLen = -1;
13+
private int longestChainLen = 0;
1314
private final double averageBlockMiningInterval;
1415
private final int confirmationDepth;
1516

1617
public NakamotoConsensus(LocalBlockTree<B> localBlockTree, NakamotoConsensusConfig nakamotoConsensusConfig) {
1718
super(localBlockTree);
1819
this.averageBlockMiningInterval = nakamotoConsensusConfig.averageBlockMiningInterval();
1920
this.confirmationDepth = nakamotoConsensusConfig.getConfirmationDepth();
20-
this.newIncomingBlock(localBlockTree.getGenesisBlock());
21+
this.currentMainChainHead = localBlockTree.getGenesisBlock();
2122
}
2223

2324
@Override
2425
public void newIncomingBlock(B block) {
2526
if (block.getHeight() > longestChainLen) {
27+
if (!(localBlockTree.getAncestorOfHeight(block, this.longestChainLen)
28+
.equals(this.currentMainChainHead))) {
29+
Simulator simulator = this.peerDLTNode.getSimulator();
30+
double currentTime = simulator.getCurrentTime();
31+
simulator.putEvent(
32+
new BlockchainReorgEvent(currentTime, this.peerDLTNode, block,
33+
block.getHeight() - this.longestChainLen),
34+
0
35+
);
36+
}
2637
this.longestChainLen = block.getHeight();
2738
this.currentMainChainHead = block;
2839
this.updateChain();
@@ -39,7 +50,7 @@ protected void updateChain() {
3950
double currentTime = simulator.getCurrentTime();
4051
simulator.putEvent(
4152
new BlockConfirmationEvent(currentTime, this.peerDLTNode, highestConfirmedBlock),
42-
currentTime);
53+
0);
4354
}
4455
}
4556

src/main/java/jabs/ledgerdata/BlockFactory.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package jabs.ledgerdata;
22

3-
import jabs.ledgerdata.bitcoin.BitcoinBlock;
3+
import jabs.ledgerdata.bitcoin.BitcoinBlockWithoutTx;
44
import jabs.ledgerdata.ethereum.EthereumBlock;
55
import jabs.ledgerdata.pbft.PBFTBlock;
66
import jabs.network.node.nodes.bitcoin.BitcoinMinerNode;
@@ -22,6 +22,11 @@ public final class BlockFactory {
2222
public static final int INV_MESSAGE_OVERHEAD = 1;
2323
public static final int ETHEREUM_HELLO_MESSAGE_SIZE = 16;
2424

25+
private static final long[] BITCOIN_COMPACT_BLOCK_SIZE_2020_BINS = {
26+
30, 3624, 7668, 11910, 16644, 21828, 27558, 30672, 31662, 32544, 33420, 34878, 35544, 36198, 36840, 37476,
27+
38130, 38838, 39630, 40674, 42732, 72714
28+
};
29+
2530
private static final long[] BITCOIN_BLOCK_SIZE_2020_BINS = {
2631
196, 119880, 254789, 396047, 553826, 726752, 917631, 1021479, 1054560, 1084003, 1113136, 1138722, 1161695,
2732
1183942, 1205734, 1227090, 1248408, 1270070, 1293647, 1320186, 1354939, 1423459, 2422858
@@ -36,9 +41,13 @@ public static int sampleBitcoinBlockSize(RandomnessEngine randomnessEngine) {
3641
return (int) randomnessEngine.sampleDistributionWithBins(BITCOIN_BLOCK_SIZE_2020, BITCOIN_BLOCK_SIZE_2020_BINS);
3742
}
3843

39-
public static BitcoinBlock sampleBitcoinBlock(Simulator simulator, RandomnessEngine randomnessEngine,
40-
BitcoinMinerNode creator, BitcoinBlock parent, double difficulty) {
41-
return new BitcoinBlock(sampleBitcoinBlockSize(randomnessEngine), parent.getHeight() + 1,
44+
public static int sampleBitcoinCompactBlockSize(RandomnessEngine randomnessEngine) {
45+
return (int) randomnessEngine.sampleDistributionWithBins(BITCOIN_BLOCK_SIZE_2020, BITCOIN_BLOCK_SIZE_2020_BINS);
46+
}
47+
48+
public static BitcoinBlockWithoutTx sampleBitcoinBlock(Simulator simulator, RandomnessEngine randomnessEngine,
49+
BitcoinMinerNode creator, BitcoinBlockWithoutTx parent, double difficulty) {
50+
return new BitcoinBlockWithoutTx(sampleBitcoinBlockSize(randomnessEngine), parent.getHeight() + 1,
4251
simulator.getCurrentTime(), creator, parent, difficulty);
4352
}
4453

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package jabs.ledgerdata;
2+
3+
public class TxCompactID extends BasicData {
4+
5+
protected TxCompactID(int size) {
6+
super(size);
7+
}
8+
9+
}

src/main/java/jabs/ledgerdata/bitcoin/BitcoinBlockWithTx.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77

88
import static jabs.ledgerdata.BlockFactory.BITCOIN_BLOCK_HEADER_SIZE;
99

10-
public class BitcoinBlockWithTx extends BitcoinBlock {
10+
public class BitcoinBlockWithTx extends BitcoinBlockWithoutTx {
1111
private final Set<BitcoinTx> Txs;
1212

13-
public BitcoinBlockWithTx(int height, double creationTime, BitcoinBlock parent, BitcoinMinerNode creator,
13+
public BitcoinBlockWithTx(int height, double creationTime, BitcoinBlockWithoutTx parent, BitcoinMinerNode creator,
1414
Set<BitcoinTx> txs, double difficulty) {
1515
super(0, height, creationTime, creator, parent, difficulty);
16-
Txs = txs;
16+
this.Txs = txs;
1717

1818
int totalSize = BITCOIN_BLOCK_HEADER_SIZE;
1919
for (BitcoinTx tx:txs) {

src/main/java/jabs/ledgerdata/bitcoin/BitcoinBlock.java renamed to src/main/java/jabs/ledgerdata/bitcoin/BitcoinBlockWithoutTx.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55

66
import static jabs.ledgerdata.BlockFactory.BITCOIN_INV_SIZE;
77

8-
public class BitcoinBlock extends SingleParentBlock<BitcoinBlock> {
8+
public class BitcoinBlockWithoutTx extends SingleParentBlock<BitcoinBlockWithoutTx> {
99
protected final double difficulty;
10-
public BitcoinBlock(int size, int height, double creationTime, Node creator, BitcoinBlock parent, double difficulty) {
10+
public BitcoinBlockWithoutTx(int size, int height, double creationTime, Node creator, BitcoinBlockWithoutTx parent, double difficulty) {
1111
super(size, height, creationTime, creator, parent, BITCOIN_INV_SIZE);
1212
this.difficulty = difficulty;
1313
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package jabs.ledgerdata.bitcoin;
2+
3+
import jabs.network.node.nodes.Node;
4+
5+
import java.util.HashSet;
6+
import java.util.Set;
7+
8+
import static jabs.ledgerdata.BlockFactory.BITCOIN_BLOCK_HEADER_SIZE;
9+
10+
public class BitcoinCompactBlock extends BitcoinBlockWithoutTx {
11+
private final Set<BitcoinTxCompactID> TxCompactIDs = new HashSet<>();
12+
13+
public BitcoinCompactBlock(int height, double creationTime, Node creator, BitcoinBlockWithoutTx parent,
14+
Set<BitcoinTx> txs, double difficulty) {
15+
super(0, height, creationTime, creator, parent, difficulty);
16+
17+
int totalSize = BITCOIN_BLOCK_HEADER_SIZE;
18+
for (BitcoinTx tx:txs) {
19+
TxCompactIDs.add(tx.getCompactID());
20+
totalSize += tx.getSize();
21+
}
22+
23+
this.size = totalSize;
24+
}
25+
26+
public BitcoinCompactBlock(BitcoinBlockWithTx block) {
27+
super(0, block.getHeight(), block.getCreationTime(), block.getCreator(), block.getParent(),
28+
block.difficulty);
29+
30+
int totalSize = BITCOIN_BLOCK_HEADER_SIZE;
31+
32+
for (BitcoinTx tx: block.getTxs()) {
33+
TxCompactIDs.add(tx.getCompactID());
34+
totalSize += tx.getSize();
35+
}
36+
37+
this.size = totalSize;
38+
}
39+
40+
public Set<BitcoinTxCompactID> getTxCompactIDs() {
41+
return TxCompactIDs;
42+
}
43+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package jabs.ledgerdata.bitcoin;
2+
3+
import jabs.network.node.nodes.Node;
4+
5+
import java.util.HashSet;
6+
import java.util.Set;
7+
8+
import static jabs.ledgerdata.BlockFactory.BITCOIN_BLOCK_HEADER_SIZE;
9+
10+
public class BitcoinCompactBlockWithoutTx extends BitcoinBlockWithoutTx {
11+
private final Set<BitcoinTxCompactID> TxCompactIDs = new HashSet<>();
12+
13+
public BitcoinCompactBlockWithoutTx(int size, int height, double creationTime, Node creator, BitcoinBlockWithoutTx parent,
14+
Set<BitcoinTx> txs, double difficulty) {
15+
super(size, height, creationTime, creator, parent, difficulty);
16+
}
17+
18+
// This is a very rough estimation of the size of a compact block in bitcoin
19+
public BitcoinCompactBlockWithoutTx(BitcoinBlockWithoutTx block) {
20+
super(0, block.getHeight(), block.getCreationTime(), block.getCreator(), block.getParent(),
21+
block.difficulty);
22+
23+
this.size = (int)((((double)block.getSize() - BITCOIN_BLOCK_HEADER_SIZE) / 200) * 6) + BITCOIN_BLOCK_HEADER_SIZE;
24+
}
25+
26+
public Set<BitcoinTxCompactID> getTxCompactIDs() {
27+
return TxCompactIDs;
28+
}
29+
}

src/main/java/jabs/ledgerdata/bitcoin/BitcoinTx.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@
55
import static jabs.ledgerdata.BlockFactory.BITCOIN_INV_SIZE;
66

77
public class BitcoinTx extends Tx<BitcoinTx> {
8+
private final BitcoinTxCompactID compactID = new BitcoinTxCompactID();
89
public BitcoinTx(int size) {
910
super(size, BITCOIN_INV_SIZE);
1011
}
12+
13+
public BitcoinTxCompactID getCompactID() {
14+
return this.compactID;
15+
}
1116
}

0 commit comments

Comments
 (0)