Skip to content

Commit 3b0d2e4

Browse files
authored
Merge pull request #1714 from keep-network/block-step
Set result publication block step to 6 blocks
2 parents c7ea98a + cdb9b19 commit 3b0d2e4

File tree

6 files changed

+62
-95
lines changed

6 files changed

+62
-95
lines changed

pkg/beacon/relay/groupselection/groupselection.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ var logger = log.Logger("keep-groupselection")
2323
// protocol.
2424
const (
2525
// The number of blocks one round takes.
26-
roundDuration = uint64(3)
26+
roundDuration = uint64(6)
2727

2828
// The delay in blocks after all rounds complete to ensure all transactions
2929
// are mined
30-
miningLag = uint64(6)
30+
miningLag = uint64(12)
3131
)
3232

3333
// Result represents the result of group selection protocol. It contains the
@@ -43,7 +43,7 @@ type Result struct {
4343
//
4444
// To minimize the submitter's cost by minimizing the number of redundant
4545
// tickets that are not selected into the group, tickets are submitted in
46-
// N rounds, each round taking 3 blocks.
46+
// N rounds, each round taking 6 blocks.
4747
// As the basic principle, the number of leading zeros in the ticket
4848
// value is subtracted from the number of rounds to determine the round
4949
// the ticket should be submitted in:
@@ -57,7 +57,7 @@ type Result struct {
5757
// the candidate not yet submitted to determine if continuing with
5858
// ticket submission still makes sense.
5959
//
60-
// After the last round, there is a 6 blocks mining lag allowing all
60+
// After the last round, there is a 12 blocks mining lag allowing all
6161
// outstanding ticket submissions to have a higher chance of being
6262
// mined before the deadline.
6363
func CandidateToNewGroup(

pkg/beacon/relay/groupselection/groupselection_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func TestSubmitTickets(t *testing.T) {
6161
t.Run(testName, func(t *testing.T) {
6262
chainConfig := &config.Chain{
6363
GroupSize: test.groupSize,
64-
TicketSubmissionTimeout: 12,
64+
TicketSubmissionTimeout: 24,
6565
}
6666

6767
chain := &stubGroupInterface{

solidity/contracts/KeepRandomBeaconOperator.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ contract KeepRandomBeaconOperator is ReentrancyGuard {
7878

7979
/// @dev Time in blocks after which the next group member is eligible
8080
/// to submit the result.
81-
uint256 public resultPublicationBlockStep = 3;
81+
uint256 public resultPublicationBlockStep = 6;
8282

8383
/// @dev Timeout in blocks for a relay entry to appear on the chain. Blocks
8484
/// are counted from the moment relay request occur.
@@ -171,7 +171,7 @@ contract KeepRandomBeaconOperator is ReentrancyGuard {
171171
// that are not selected into the group, the following approach is
172172
// recommended:
173173
//
174-
// Tickets are submitted in 11 rounds, each round taking 3 blocks.
174+
// Tickets are submitted in 11 rounds, each round taking 6 blocks.
175175
// As the basic principle, the number of leading zeros in the ticket
176176
// value is subtracted from the number of rounds to determine the round
177177
// the ticket should be submitted in:
@@ -185,10 +185,10 @@ contract KeepRandomBeaconOperator is ReentrancyGuard {
185185
// the candidate not yet submitted to determine if continuing with
186186
// ticket submission still makes sense.
187187
//
188-
// After 33 blocks, there is a 6 blocks mining lag allowing all
188+
// After 66 blocks, there is a 12 blocks mining lag allowing all
189189
// outstanding ticket submissions to have a higher chance of being
190190
// mined before the deadline.
191-
groupSelection.ticketSubmissionTimeout = 3 * 11 + 6;
191+
groupSelection.ticketSubmissionTimeout = 6 * 11 + 12;
192192

193193
groupSelection.groupSize = groupSize;
194194

solidity/contracts/stubs/KeepRandomBeaconOperatorDKGResultStub.sol

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,6 @@ contract KeepRandomBeaconOperatorDKGResultStub is KeepRandomBeaconOperator {
3131
dkgResultVerification.signatureThreshold = threshold;
3232
}
3333

34-
function setResultPublicationBlockStep(uint256 step) public {
35-
resultPublicationBlockStep = step;
36-
}
37-
3834
function getGroupSelectionRelayEntry() public view returns (uint256) {
3935
return groupSelection.seed;
4036
}

solidity/test/random_beacon_operator/TestPricingRewards.js

Lines changed: 52 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ const {createSnapshot, restoreSnapshot} = require("../helpers/snapshot.js")
55
const {contract, accounts, web3} = require("@openzeppelin/test-environment")
66
const {time} = require("@openzeppelin/test-helpers")
77

8+
const BN = web3.utils.BN
9+
const chai = require('chai')
10+
chai.use(require('bn-chai')(BN))
11+
const expect = chai.expect
12+
813
describe('KeepRandomBeaconOperator/PricingRewards', function() {
914
let serviceContract;
1015
let operatorContract;
@@ -36,10 +41,8 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
3641
let entryFeeEstimate = await serviceContract.entryFeeEstimate(0);
3742
await serviceContract.methods['requestRelayEntry()']({value: entryFeeEstimate, from: accounts[0]});
3843

39-
let delayFactor = await operatorContract.delayFactor.call();
40-
41-
let expectedDelayFactor = web3.utils.toBN(10000000000000000);
42-
assert.isTrue(expectedDelayFactor.eq(delayFactor));
44+
let delayFactor = await operatorContract.delayFactor.call();
45+
expect(delayFactor).to.eq.BN('10000000000000000')
4346
});
4447

4548
it("should correctly evaluate delay factor at the first submission block", async () => {
@@ -49,21 +52,23 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
4952
await time.advanceBlockTo(web3.utils.toBN(await web3.eth.getBlockNumber()).addn(1));
5053

5154
let delayFactor = await operatorContract.delayFactor.call();
52-
53-
let expectedDelayFactor = web3.utils.toBN(10000000000000000);
54-
assert.isTrue(expectedDelayFactor.eq(delayFactor));
55+
expect(delayFactor).to.eq.BN('10000000000000000')
5556
});
5657

5758
it("should correctly evaluate delay factor at the second submission block", async () => {
59+
let startBlock = await operatorContract.currentRequestStartBlock()
5860
let entryFeeEstimate = await serviceContract.entryFeeEstimate(0);
5961
await serviceContract.methods['requestRelayEntry()']({value: entryFeeEstimate, from: accounts[0]});
6062

6163
await time.advanceBlockTo(web3.utils.toBN(await web3.eth.getBlockNumber()).addn(2));
6264

6365
let delayFactor = await operatorContract.delayFactor.call();
64-
65-
let expectedDelayFactor = web3.utils.toBN('9896104600694443');
66-
assert.isTrue(expectedDelayFactor.eq(delayFactor));
66+
// currentRequestStartBlock = 0
67+
// T_received = 2
68+
// T_deadline = 0 + 384 + 1 = 385
69+
// T_begin = 0 + 1 = 1
70+
// [(T_deadline - T_received) / (T_deadline - T_begin)]^2 = [(385 - 2) / (385 - 1)]^2
71+
expect(delayFactor).to.eq.BN('9947984483506943')
6772
});
6873

6974
it("should correctly evaluate delay factor in the last block before timeout", async () => {
@@ -74,9 +79,12 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
7479
await time.advanceBlockTo(relayEntryTimeout.addn(await web3.eth.getBlockNumber()));
7580

7681
let delayFactor = await operatorContract.delayFactor.call();
77-
78-
let expectedDelayFactor = web3.utils.toBN('271267361111');
79-
assert.isTrue(expectedDelayFactor.eq(delayFactor));
82+
// currentRequestStartBlock = 0
83+
// T_received = 384
84+
// T_deadline = 0 + 384 + 1 = 385
85+
// T_begin = 0 + 1 = 1
86+
// [(T_deadline - T_received) / (T_deadline - T_begin)]^2 = [(385 - 384) / (385 - 1)]^2
87+
expect(delayFactor).to.eq.BN('67816840277')
8088
});
8189

8290
it("should correctly evaluate rewards for entry submitted " +
@@ -100,18 +108,9 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
100108

101109
let rewards = await operatorContract.getNewEntryRewardsBreakdown.call();
102110

103-
assert.isTrue(
104-
expectedGroupMemberReward.eq(rewards.groupMemberReward),
105-
"unexpected group member reward"
106-
);
107-
assert.isTrue(
108-
expectedSubmitterReward.eq(rewards.submitterReward),
109-
"unexpected submitter reward"
110-
);
111-
assert.isTrue(
112-
expectedSubsidy.eq(rewards.subsidy),
113-
"unexpected subsidy"
114-
);
111+
expect(rewards.groupMemberReward).to.eq.BN(expectedGroupMemberReward)
112+
expect(rewards.submitterReward).to.eq.BN(expectedSubmitterReward)
113+
expect(rewards.subsidy).to.eq.BN(expectedSubsidy)
115114
});
116115

117116
it("should correctly evaluate rewards for entry submitted " +
@@ -137,18 +136,9 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
137136

138137
let rewards = await operatorContract.getNewEntryRewardsBreakdown.call();
139138

140-
assert.isTrue(
141-
expectedGroupMemberReward.eq(rewards.groupMemberReward),
142-
"unexpected group member reward"
143-
);
144-
assert.isTrue(
145-
expectedSubmitterReward.eq(rewards.submitterReward),
146-
"unexpected submitter reward"
147-
);
148-
assert.isTrue(
149-
expectedSubsidy.eq(rewards.subsidy),
150-
"unexpected subsidy"
151-
);
139+
expect(rewards.groupMemberReward).to.eq.BN(expectedGroupMemberReward)
140+
expect(rewards.submitterReward).to.eq.BN(expectedSubmitterReward)
141+
expect(rewards.subsidy).to.eq.BN(expectedSubsidy)
152142
});
153143

154144
it("should correctly evaluate rewards for the entry submitted " +
@@ -162,10 +152,10 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
162152

163153
await time.advanceBlockTo(web3.utils.toBN(await web3.eth.getBlockNumber()).addn(2));
164154

165-
// There is one block of delay so the delay factor is 0.9896104600694443.
155+
// There is one block of delay so the delay factor is 0.9947984483506943.
166156
// Group member reward should be scaled by the delay factor:
167-
// 1987000 * 0.9896104600694443 = ~1966355
168-
let expectedGroupMemberReward = web3.utils.toBN("1966355");
157+
// 1987000 * 0.9947984483506943 = ~1966355
158+
let expectedGroupMemberReward = web3.utils.toBN("1976664");
169159

170160
// The entire entry verification fee is paid to the submitter
171161
// regardless of their gas expenditure. The submitter is free to spend
@@ -174,37 +164,28 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
174164
//
175165
// To incentivize a race for the submitter position, the submitter
176166
// receives delay penalty * group size * 0.05 as an extra reward:
177-
// 1987000 * (1 - 0.9896104600694443) * 64 * 5% = ~66060
167+
// 1987000 * (1 - 0.9947984483506943) * 64 * 5% = ~33073
178168
//
179-
// 70070000000 + 66060 = 70070066060
180-
let expectedSubmitterReward = web3.utils.toBN("70070066060");
169+
// 70070000000 + 33073 = 70070033073
170+
let expectedSubmitterReward = web3.utils.toBN("70070033073");
181171

182172
// If the amount paid out to the signing group in group rewards and the
183173
// submitter’s extra reward is less than the profit margin, the
184174
// difference is added to the beacon’s request subsidy pool to
185175
// incentivize customers to request entries.
186176
//
187177
// profit margin: 1987000 * 64 = 127168000
188-
// paid member rewards: 1966355 * 64 = 125846720
189-
// submitter extra reward: 66060
178+
// paid member rewards: 1976664 * 64 = 126506496
179+
// submitter extra reward: 33073
190180
//
191-
// 127168000 - 125846720 - 66060 = 1255220
192-
let expectedSubsidy = web3.utils.toBN("1255220");
181+
// 127168000 - 126506496 - 33073 = 628431
182+
let expectedSubsidy = web3.utils.toBN("628431");
193183

194184
let rewards = await operatorContract.getNewEntryRewardsBreakdown.call();
195185

196-
assert.isTrue(
197-
expectedGroupMemberReward.eq(rewards.groupMemberReward),
198-
"unexpected group member reward"
199-
);
200-
assert.isTrue(
201-
expectedSubmitterReward.eq(rewards.submitterReward),
202-
"unexpected submitter reward"
203-
);
204-
assert.isTrue(
205-
expectedSubsidy.eq(rewards.subsidy),
206-
"unexpected subsidy"
207-
);
186+
expect(rewards.groupMemberReward).to.eq.BN(expectedGroupMemberReward)
187+
expect(rewards.submitterReward).to.eq.BN(expectedSubmitterReward)
188+
expect(rewards.subsidy).to.eq.BN(expectedSubsidy)
208189
});
209190

210191
it("should correctly evaluate rewards for the entry submitted " +
@@ -220,10 +201,10 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
220201
await time.advanceBlockTo(relayEntryTimeout.addn(await web3.eth.getBlockNumber()));
221202

222203
// There is one block left before the timeout so the delay factor is
223-
// 0.0000271267361111.
204+
// 0.000067816840277.
224205
// Group member reward should be scaled by the delay factor:
225-
// 1382000000 * 0.0000271267361111 = ~37489
226-
let expectedGroupMemberReward = web3.utils.toBN("37489");
206+
// 1382000000 * 0.0000067816840277 = ~9372
207+
let expectedGroupMemberReward = web3.utils.toBN("9372");
227208

228209
// The entire entry verification fee is paid to the submitter
229210
// regardless of their gas expenditure. The submitter is free to spend
@@ -232,36 +213,27 @@ describe('KeepRandomBeaconOperator/PricingRewards', function() {
232213
//
233214
// To incentivize a race for the submitter position, the submitter
234215
// receives delay penalty * group size * 0.05 as an extra reward:
235-
// 1382000000 * (1 - 0.0000271267361111) * 64 * 5% = ~4422280034
216+
// 1382000000 * (1 - 0.0000067816840277) * 64 * 5% = ~4422370008
236217
//
237-
// 100040000000 + 4422280034 = 104462280034
238-
let expectedSubmitterReward = web3.utils.toBN("104462280034");
218+
// 100040000000 + 4422370008 = 104462370008
219+
let expectedSubmitterReward = web3.utils.toBN("104462370008");
239220

240221
// If the amount paid out to the signing group in group rewards and the
241222
// submitter’s extra reward is less than the profit margin, the
242223
// difference is added to the beacon’s request subsidy pool to
243224
// incentivize customers to request entries.
244225
//
245226
// profit margin: 1382000000 * 64 = 88448000000
246-
// paid member rewards: 37489 * 64 = 2399296
227+
// paid member rewards: 9372 * 64 = 599808
247228
// submitter extra reward: 4422280034
248229
//
249-
// 88448000000 - 2399296 - 4422280034 = 84023320670
250-
let expectedSubsidy = web3.utils.toBN("84023320670");
230+
// 88448000000 - 599808 - 4422370008 = 84025030184
231+
let expectedSubsidy = web3.utils.toBN("84025030184");
251232

252233
let rewards = await operatorContract.getNewEntryRewardsBreakdown.call();
253234

254-
assert.isTrue(
255-
expectedGroupMemberReward.eq(rewards.groupMemberReward),
256-
"unexpected group member reward"
257-
);
258-
assert.isTrue(
259-
expectedSubmitterReward.eq(rewards.submitterReward),
260-
"unexpected submitter reward"
261-
);
262-
assert.isTrue(
263-
expectedSubsidy.eq(rewards.subsidy),
264-
"unexpected subsidy"
265-
);
235+
expect(rewards.groupMemberReward).to.eq.BN(expectedGroupMemberReward)
236+
expect(rewards.submitterReward).to.eq.BN(expectedSubmitterReward)
237+
expect(rewards.subsidy).to.eq.BN(expectedSubsidy)
266238
});
267239
});

solidity/test/random_beacon_operator/TestPublishDkgResult.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('KeepRandomBeaconOperator/PublishDkgResult', function () {
1515
const groupSize = 20;
1616
const groupThreshold = 11;
1717
const dkgResultSignatureThreshold = 15;
18-
const resultPublicationBlockStep = 3;
18+
const resultPublicationBlockStep = 6;
1919

2020
let resultPublicationTime, token, stakingContract, operatorContract,
2121
owner = accounts[0], beneficiary = accounts[4], ticket,
@@ -46,7 +46,6 @@ describe('KeepRandomBeaconOperator/PublishDkgResult', function () {
4646
await operatorContract.setGroupSize(groupSize);
4747
await operatorContract.setGroupThreshold(groupThreshold);
4848
await operatorContract.setDKGResultSignatureThreshold(dkgResultSignatureThreshold);
49-
await operatorContract.setResultPublicationBlockStep(resultPublicationBlockStep);
5049

5150
const operator1StakingWeight = 100;
5251
const operator2StakingWeight = 200;

0 commit comments

Comments
 (0)