Skip to content

Commit d40e83a

Browse files
rmoreliovlabsfmacleal
authored andcommitted
Add super block difficulty calculation (#3277)
1 parent e845ae2 commit d40e83a

26 files changed

+469
-151
lines changed

rskj-core/src/main/java/co/rsk/RskContext.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ public class RskContext implements NodeContext, NodeBootstrapper {
180180
private Genesis genesis;
181181
private CompositeEthereumListener compositeEthereumListener;
182182
private DifficultyCalculator difficultyCalculator;
183+
private SuperDifficultyCalculator superDifficultyCalculator;
183184
private ForkDetectionDataCalculator forkDetectionDataCalculator;
184185
private ProofOfWorkRule proofOfWorkRule;
185186
private ForkDetectionDataRule forkDetectionDataRule;
@@ -494,7 +495,8 @@ public synchronized BlockExecutor getBlockExecutor() {
494495
getReceiptStore(),
495496
getRepositoryLocator(),
496497
getTransactionExecutorFactory(),
497-
getRskSystemProperties()
498+
getRskSystemProperties(),
499+
getSuperDifficultyCalculator()
498500
);
499501
}
500502

@@ -1125,7 +1127,7 @@ public synchronized BlockValidationRule getBlockValidationRule() {
11251127
rskSystemProperties.getNetworkConstants(),
11261128
rskSystemProperties.getBitcoinjNetworkConstants()
11271129
);
1128-
final SuperBlockRule superBlockRule = new SuperBlockRule(rskSystemProperties.getActivationConfig(), getBlockStore(), getReceiptStore());
1130+
final SuperBlockRule superBlockRule = new SuperBlockRule(rskSystemProperties.getActivationConfig(), getBlockStore(), getReceiptStore(), getSuperDifficultyCalculator());
11291131
blockValidationRule = new BlockCompositeRule(
11301132
new TxsMinGasPriceRule(),
11311133
new BlockTxsMaxGasPriceRule(rskSystemProperties.getActivationConfig()),
@@ -1813,7 +1815,7 @@ private BlockValidator getBlockHeaderValidator() {
18131815
rskSystemProperties.getNetworkConstants(),
18141816
rskSystemProperties.getBitcoinjNetworkConstants()
18151817
);
1816-
final SuperBlockRule superBlockRule = new SuperBlockRule(rskSystemProperties.getActivationConfig(), getBlockStore(), getReceiptStore());
1818+
final SuperBlockRule superBlockRule = new SuperBlockRule(rskSystemProperties.getActivationConfig(), getBlockStore(), getReceiptStore(), getSuperDifficultyCalculator());
18171819

18181820
final BlockHeaderValidationRule blockHeaderValidationRule = new BlockHeaderCompositeRule(
18191821
getProofOfWorkRule(),
@@ -1920,6 +1922,17 @@ private DifficultyCalculator getDifficultyCalculator() {
19201922
return difficultyCalculator;
19211923
}
19221924

1925+
private SuperDifficultyCalculator getSuperDifficultyCalculator() {
1926+
if (superDifficultyCalculator == null) {
1927+
RskSystemProperties rskSystemProperties = getRskSystemProperties();
1928+
superDifficultyCalculator = new SuperDifficultyCalculator(
1929+
rskSystemProperties.getNetworkConstants()
1930+
);
1931+
}
1932+
1933+
return superDifficultyCalculator;
1934+
}
1935+
19231936
private BlockToMineBuilder getBlockToMineBuilder() {
19241937
if (blockToMineBuilder == null) {
19251938
blockToMineBuilder = new BlockToMineBuilder(
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* This file is part of RskJ
3+
* Copyright (C) 2017 RSK Labs Ltd.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
19+
package co.rsk.core;
20+
21+
import org.ethereum.config.Constants;
22+
import org.ethereum.core.Block;
23+
24+
import java.math.BigInteger;
25+
26+
public class SuperDifficultyCalculator {
27+
private final Constants constants;
28+
29+
public SuperDifficultyCalculator(Constants constants) {
30+
this.constants = constants;
31+
}
32+
33+
public BlockDifficulty calcSuperDifficulty(Block block, Block superParentBlock) {
34+
final var shouldUpdateDifficulty = block.getNumber() % constants.getSuperBlockRetargetingInterval().longValue() == 0;
35+
36+
if (shouldUpdateDifficulty) {
37+
return getSuperBlockDifficulty(block, superParentBlock);
38+
}
39+
40+
return superParentBlock.getSuperBlockFields().getSuperDifficulty();
41+
}
42+
43+
private BlockDifficulty getSuperBlockDifficulty(Block curBlock, Block retargetingBlock) {
44+
var currentTimestamp = curBlock.getTimestamp() - retargetingBlock.getTimestamp();
45+
46+
if (currentTimestamp <= 0) {
47+
currentTimestamp = 1;
48+
}
49+
50+
final var correctionFactor = constants.getSuperBlockExpectedRetargetIntervalInSeconds()
51+
.divide(BigInteger.valueOf(currentTimestamp));
52+
53+
final var multipliedCorrectionFactor = correctionFactor.shiftLeft(constants.getSuperBlockDifficultyCorrectionFactorShift());
54+
55+
return calcSuperDifficultyWithTimeStamps(
56+
retargetingBlock.getSuperBlockFields().getSuperDifficulty(),
57+
multipliedCorrectionFactor,
58+
constants.getSuperBlockDifficultyMinCorrectionFactor(),
59+
constants.getSuperBlockDifficultyMaxCorrectionFactor(),
60+
constants.getSuperBlockDifficultyCorrectionFactorShift());
61+
}
62+
63+
private static BlockDifficulty calcSuperDifficultyWithTimeStamps(
64+
BlockDifficulty oldDifficulty,
65+
BigInteger correctionFactor,
66+
BigInteger superBlockDifficultyMinCorrectionFactor,
67+
BigInteger superBlockDifficultyMaxCorrectionFactor,
68+
Integer superBlockDifficultyCorrectionFactorShift) {
69+
70+
var correctionFactorToUse = BigInteger.ZERO;
71+
72+
if (correctionFactor.compareTo(superBlockDifficultyMinCorrectionFactor) < 0) {
73+
correctionFactorToUse = superBlockDifficultyMinCorrectionFactor;
74+
} else if (correctionFactor.compareTo(superBlockDifficultyMaxCorrectionFactor) > 0) {
75+
correctionFactorToUse = superBlockDifficultyMaxCorrectionFactor;
76+
} else {
77+
correctionFactorToUse = correctionFactor.shiftRight(superBlockDifficultyCorrectionFactorShift);
78+
}
79+
80+
return computeSuperBlockDifficulty(oldDifficulty, correctionFactorToUse);
81+
}
82+
83+
private static BlockDifficulty computeSuperBlockDifficulty(
84+
BlockDifficulty oldDifficulty,
85+
BigInteger correctionFactor
86+
) {
87+
var newSuperDifficulty = oldDifficulty
88+
.multiply(correctionFactor)
89+
.asBigInteger();
90+
91+
return new BlockDifficulty(newSuperDifficulty);
92+
}
93+
}

rskj-core/src/main/java/co/rsk/core/bc/BlockExecutor.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
package co.rsk.core.bc;
2020

2121
import co.rsk.config.RskSystemProperties;
22+
import co.rsk.core.BlockDifficulty;
2223
import co.rsk.core.Coin;
2324
import co.rsk.core.RskAddress;
25+
import co.rsk.core.SuperDifficultyCalculator;
2426
import co.rsk.core.TransactionExecutorFactory;
2527
import co.rsk.core.TransactionListExecutor;
2628
import co.rsk.core.types.bytes.Bytes;
@@ -30,7 +32,6 @@
3032
import co.rsk.metrics.profilers.MetricKind;
3133
import co.rsk.metrics.profilers.Profiler;
3234
import co.rsk.metrics.profilers.ProfilerFactory;
33-
import co.rsk.util.Trio;
3435
import com.google.common.annotations.VisibleForTesting;
3536
import org.ethereum.config.Constants;
3637
import org.ethereum.config.blockchain.upgrades.ActivationConfig;
@@ -78,6 +79,7 @@ public class BlockExecutor {
7879

7980
private final Map<Keccak256, ProgramResult> transactionResults = new ConcurrentHashMap<>();
8081
private final long minSequentialSetGasLimit;
82+
private final SuperDifficultyCalculator superDifficultyCalculator;
8183

8284
private boolean registerProgramResults;
8385

@@ -93,7 +95,8 @@ public BlockExecutor(BlockStore blockStore,
9395
ReceiptStore receiptStore,
9496
RepositoryLocator repositoryLocator,
9597
TransactionExecutorFactory transactionExecutorFactory,
96-
RskSystemProperties systemProperties) {
98+
RskSystemProperties systemProperties,
99+
SuperDifficultyCalculator superDifficultyCalculator) {
97100
this.activationConfig = systemProperties.getActivationConfig();
98101

99102
this.blockStore = blockStore;
@@ -103,6 +106,7 @@ public BlockExecutor(BlockStore blockStore,
103106
this.remascEnabled = systemProperties.isRemascEnabled();
104107
this.concurrentContractsDisallowed = Collections.unmodifiableSet(new HashSet<>(systemProperties.concurrentContractsDisallowed()));
105108
this.minSequentialSetGasLimit = systemProperties.getNetworkConstants().getMinSequentialSetGasLimit();
109+
this.superDifficultyCalculator = superDifficultyCalculator;
106110

107111
int numOfParallelList = Constants.getTransactionExecutionThreads();
108112
this.execServices = new ExecutorService[numOfParallelList];
@@ -187,12 +191,20 @@ private void fill(Block block, BlockResult result) {
187191
header.setTxExecutionSublistsEdges(result.getTxEdges());
188192

189193
if (activationConfig.isActive(RSKIP481, block.getNumber())) {
190-
final var superParentAndBridgeEvent =
191-
FamilyUtils.findSuperParentAndUnclesAndBridgeEvent(blockStore, receiptStore, block, result.getTransactionReceipts());
194+
final var superParentAndBridgeEvent = FamilyUtils.findSuperParentAndBridgeEvent(
195+
blockStore,
196+
receiptStore,
197+
block,
198+
result.getTransactionReceipts());
199+
200+
var superDifficulty = superParentAndBridgeEvent.superParent() == null ?
201+
BlockDifficulty.ONE :
202+
superDifficultyCalculator.calcSuperDifficulty(block, superParentAndBridgeEvent.superParent());
192203

193204
SuperBlockFields superBlockFields = makeSuperBlockFields(
194205
superParentAndBridgeEvent.superParent(),
195-
superParentAndBridgeEvent.superBridgeEvent()
206+
superParentAndBridgeEvent.superBridgeEvent(),
207+
superDifficulty
196208
);
197209
block.setSuperChainFields(superBlockFields);
198210
}
@@ -201,14 +213,15 @@ private void fill(Block block, BlockResult result) {
201213
profiler.stop(metric);
202214
}
203215

204-
private static SuperBlockFields makeSuperBlockFields(Block superParent, SuperBridgeEvent event) {
216+
private static SuperBlockFields makeSuperBlockFields(Block superParent, SuperBridgeEvent event, BlockDifficulty superDifficulty) {
205217
Bytes superParentHash = superParent == null ? null : Bytes.of(superParent.getHash().getBytes());
206218
long superParentBlockNumber = superParent == null ? 0 : superParent.getSuperBlockFields().getBlockNumber() + 1;
207219

208220
return new SuperBlockFields(
209221
superParentHash,
210222
superParentBlockNumber,
211-
event
223+
event,
224+
superDifficulty
212225
);
213226
}
214227

rskj-core/src/main/java/co/rsk/core/bc/FamilyUtils.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
package co.rsk.core.bc;
2020

2121
import co.rsk.crypto.Keccak256;
22-
import co.rsk.util.Trio;
2322
import org.apache.commons.lang3.tuple.Pair;
2423
import org.ethereum.core.Block;
2524
import org.ethereum.core.BlockHeader;
@@ -175,7 +174,7 @@ public static Set<Keccak256> getFamily(BlockStore store, long blockNumber, Kecca
175174
return family;
176175
}
177176

178-
public static FindSuperParentAndBridgeEventResponse findSuperParentAndUnclesAndBridgeEvent(
177+
public static FindSuperParentAndBridgeEventResponse findSuperParentAndBridgeEvent(
179178
BlockStore blockStore,
180179
ReceiptStore receiptStore,
181180
Block block,

rskj-core/src/main/java/co/rsk/core/bc/SuperBlockFields.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
package co.rsk.core.bc;
2020

21+
import co.rsk.core.BlockDifficulty;
2122
import co.rsk.core.types.bytes.BytesSlice;
2223
import co.rsk.crypto.Keccak256;
2324
import org.ethereum.crypto.HashUtil;
@@ -32,11 +33,14 @@ public class SuperBlockFields {
3233
private final BytesSlice parentHash;
3334
private final long blockNumber;
3435
private final SuperBridgeEvent bridgeEvent;
36+
private BlockDifficulty superDifficulty;
3537

36-
public SuperBlockFields(@Nullable BytesSlice parentHash, long blockNumber, @Nullable SuperBridgeEvent bridgeEvent) {
38+
public SuperBlockFields(@Nullable BytesSlice parentHash, long blockNumber,
39+
@Nullable SuperBridgeEvent bridgeEvent, BlockDifficulty superDifficulty) {
3740
this.parentHash = parentHash;
3841
this.blockNumber = blockNumber;
3942
this.bridgeEvent = bridgeEvent;
43+
this.superDifficulty = superDifficulty;
4044
}
4145

4246
public BytesSlice getParentHash() {
@@ -51,11 +55,20 @@ public SuperBridgeEvent getBridgeEvent() {
5155
return bridgeEvent;
5256
}
5357

58+
public BlockDifficulty getSuperDifficulty() {
59+
return superDifficulty;
60+
}
61+
62+
public void setSuperDifficulty(BlockDifficulty superDifficulty) {
63+
this.superDifficulty = superDifficulty;
64+
}
65+
5466
public byte[] getEncoded() {
5567
return RLP.encodeList(
5668
RLP.encodeElement(parentHash != null ? parentHash.copyArray() : null),
5769
RLP.encodeBigInteger(BigInteger.valueOf(blockNumber)),
58-
RLP.encodeElement(bridgeEvent != null ? bridgeEvent.getEncoded() : null)
70+
RLP.encodeElement(bridgeEvent != null ? bridgeEvent.getEncoded() : null),
71+
RLP.encodeElement(superDifficulty != null ? superDifficulty.getBytes() : null)
5972
);
6073
}
6174

@@ -64,7 +77,8 @@ public Keccak256 getHash() {
6477
byte[] encoded = RLP.encodeList(
6578
RLP.encodeElement(parentHash != null ? parentHash.copyArray() : null),
6679
RLP.encodeBigInteger(BigInteger.valueOf(blockNumber)),
67-
RLP.encodeElement(bridgeEvent != null ? bridgeEvent.getEncoded() : null)
80+
RLP.encodeElement(bridgeEvent != null ? bridgeEvent.getEncoded() : null),
81+
RLP.encodeElement(superDifficulty != null ? superDifficulty.getBytes() : null)
6882
);
6983

7084
return new Keccak256(HashUtil.keccak256(encoded));

rskj-core/src/main/java/co/rsk/util/Trio.java

Lines changed: 0 additions & 47 deletions
This file was deleted.

0 commit comments

Comments
 (0)