Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relay entry BLS verification #559

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ func submitRelayEntryGenesis(c *cli.Context) error {
entry := &event.Entry{
RequestID: big.NewInt(0),
Value: value,
GroupID: big.NewInt(0),
GroupID: make([]byte, 0),
PreviousEntry: big.NewInt(0),
Timestamp: time.Now().UTC(),
}
Expand Down Expand Up @@ -196,7 +196,7 @@ func submitRelayEntrySeed(c *cli.Context) error {
entry := &event.Entry{
RequestID: big.NewInt(int64(requestID)),
Value: value,
GroupID: big.NewInt(int64(requestID)),
GroupID: big.NewInt(int64(requestID)).Bytes(),
PreviousEntry: previousValue,
Timestamp: time.Now().UTC(),
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/smoketest.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ func SmokeTest(c *cli.Context) error {
chainHandle.ThresholdRelay().SubmitRelayEntry(&event.Entry{
RequestID: big.NewInt(int64(135)),
Value: big.NewInt(int64(154)),
GroupID: big.NewInt(int64(168)),
GroupID: big.NewInt(int64(168)).Bytes(),
PreviousEntry: &big.Int{},
})

Expand Down
19 changes: 19 additions & 0 deletions contracts/solidity/contracts/KeepGroupStub.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity ^0.4.24;


/**
* @title KeepGroupStub
* @dev A simplified Keep Group contract to help local development.
*/
contract KeepGroupStub {

uint256 internal _randomBeaconValue;

/**
* @dev Triggers the selection process of a new candidate group.
*/
function runGroupSelection(uint256 randomBeaconValue) public {
_randomBeaconValue = randomBeaconValue;
}

}
11 changes: 6 additions & 5 deletions contracts/solidity/contracts/KeepRandomBeaconImplV1.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pragma solidity ^0.4.24;

import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "./BLS.sol";


interface GroupContract {
Expand All @@ -19,7 +20,7 @@ contract KeepRandomBeaconImplV1 is Ownable {

// These are the public events that are used by clients
event RelayEntryRequested(uint256 requestID, uint256 payment, uint256 blockReward, uint256 seed, uint blockNumber);
event RelayEntryGenerated(uint256 requestID, uint256 requestResponse, uint256 requestGroupID, uint256 previousEntry, uint blockNumber);
event RelayEntryGenerated(uint256 requestID, uint256 requestResponse, bytes requestGroupID, uint256 previousEntry, uint blockNumber);
event RelayResetEvent(uint256 lastValidRelayEntry, uint256 lastValidRelayTxHash, uint256 lastValidRelayBlock);
event SubmitGroupPublicKeyEvent(byte[] groupPublicKey, uint256 requestID, uint256 activationBlockHeight);

Expand All @@ -33,7 +34,7 @@ contract KeepRandomBeaconImplV1 is Ownable {
mapping (uint256 => address) internal _requestPayer;
mapping (uint256 => uint256) internal _requestPayment;
mapping (uint256 => uint256) internal _blockReward;
mapping (uint256 => uint256) internal _requestGroup;
mapping (uint256 => bytes) internal _requestGroup;

/**
* @dev Prevent receiving ether without explicitly calling a function.
Expand Down Expand Up @@ -142,10 +143,10 @@ contract KeepRandomBeaconImplV1 is Ownable {
* @param groupSignature The generated random number.
* @param groupID Public key of the group that generated the threshold signature.
*/
function relayEntry(uint256 requestID, uint256 groupSignature, uint256 groupID, uint256 previousEntry) public {
function relayEntry(uint256 requestID, uint256 groupSignature, bytes groupID, uint256 previousEntry) public {

require(BLS.verify(groupID, abi.encodePacked(previousEntry), bytes32(groupSignature)));

// TODO: validate groupSignature using BLS.sol

_requestGroup[requestID] = groupID;
emit RelayEntryGenerated(requestID, groupSignature, groupID, previousEntry, block.number);
GroupContract(_groupContract).runGroupSelection(groupSignature);
Expand Down
3 changes: 3 additions & 0 deletions contracts/solidity/migrations/2_deploy_contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const StakingProxy = artifacts.require("./StakingProxy.sol");
const TokenStaking = artifacts.require("./TokenStaking.sol");
const TokenGrant = artifacts.require("./TokenGrant.sol");
const KeepRandomBeaconImplV1 = artifacts.require("./KeepRandomBeaconImplV1.sol");
const KeepRandomBeaconUpgradeExample = artifacts.require("./KeepRandomBeaconUpgradeExample.sol");
const KeepGroupImplV1 = artifacts.require("./KeepGroupImplV1.sol");
const KeepGroup = artifacts.require("./KeepGroup.sol");
const KeepRandomBeacon = artifacts.require("./KeepRandomBeacon.sol");
Expand All @@ -31,6 +32,8 @@ module.exports = (deployer) => {
await deployer.deploy(StakingProxy);
await deployer.deploy(TokenStaking, KeepToken.address, StakingProxy.address, withdrawalDelay);
await deployer.deploy(TokenGrant, KeepToken.address, StakingProxy.address, withdrawalDelay);
await deployer.link(BLS, KeepRandomBeaconImplV1);
await deployer.link(BLS, KeepRandomBeaconUpgradeExample);
await deployer.deploy(KeepRandomBeaconImplV1);
await deployer.deploy(KeepRandomBeacon, KeepRandomBeaconImplV1.address);
await deployer.deploy(KeepGroupImplV1);
Expand Down
13 changes: 8 additions & 5 deletions contracts/solidity/test/TestKeepGroupSelection.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ const KeepRandomBeaconProxy = artifacts.require('./KeepRandomBeacon.sol');
const KeepRandomBeaconImplV1 = artifacts.require('./KeepRandomBeaconImplV1.sol');
const KeepGroupProxy = artifacts.require('./KeepGroup.sol');
const KeepGroupImplV1 = artifacts.require('./KeepGroupImplV1.sol');
const BN = require('bn.js');


function generateTickets(randomBeaconValue, stakerValue, stakerWeight) {
let tickets = [];
for (let i = 1; i <= stakerWeight; i++) {
let ticketValue = new BigNumber('0x' + abi.soliditySHA3(
["uint", "uint", "uint"],
[randomBeaconValue, stakerValue, i]
[new BN(randomBeaconValue), stakerValue, i]
).toString('hex'));
let ticket = {
value: ticketValue,
Expand All @@ -42,7 +43,7 @@ function mineBlocks(blocks) {
contract('TestKeepGroupSelection', function(accounts) {

let token, stakingProxy, stakingContract, minimumStake, groupThreshold, groupSize,
randomBeaconValue, naturalThreshold,
previousEntry, randomBeaconValue, naturalThreshold,
timeoutInitial, timeoutSubmission, timeoutChallenge,
keepRandomBeaconImplV1, keepRandomBeaconProxy, keepRandomBeaconImplViaProxy,
keepGroupImplV1, keepGroupProxy, keepGroupImplViaProxy, groupPubKey,
Expand Down Expand Up @@ -73,7 +74,7 @@ contract('TestKeepGroupSelection', function(accounts) {
timeoutSubmission = 40;
timeoutChallenge = 60;

randomBeaconValue = 123456789;
previousEntry = '61647192470559497961835987041772849466909869278998228659325527399967350471301';

keepGroupImplV1 = await KeepGroupImplV1.new();
keepGroupProxy = await KeepGroupProxy.new(keepGroupImplV1.address);
Expand All @@ -84,7 +85,9 @@ contract('TestKeepGroupSelection', function(accounts) {

naturalThreshold = await keepGroupImplViaProxy.naturalThreshold();

groupPubKey = "0x1000000000000000000000000000000000000000000000000000000000000000";
// Data generated using client Go code with master secret key 123
groupPubKey = "0x1f1954b33144db2b5c90da089e8bde287ec7089d5d6433f3b6becaefdb678b1b2a9de38d14bef2cf9afc3c698a4211fa7ada7b4f036a2dfef0dc122b423259d0";
randomBeaconValue = '14338479826386391162410575915611605755963697664966940200639296307898208140504';

// Stake tokens as account one so it has minimum stake to be able to get into a group.
await token.approveAndCall(stakingContract.address, minimumStake*1000, "", {from: staker1});
Expand All @@ -101,7 +104,7 @@ contract('TestKeepGroupSelection', function(accounts) {
tickets3 = generateTickets(randomBeaconValue, staker3, 3000);

await keepRandomBeaconImplViaProxy.setGroupContract(keepGroupProxy.address);
await keepRandomBeaconImplViaProxy.relayEntry(1, randomBeaconValue, 1, 1);
await keepRandomBeaconImplViaProxy.relayEntry(1, new BigNumber(randomBeaconValue), groupPubKey, new BigNumber(previousEntry));
});

it("should be able to get staking weight", async function() {
Expand Down
42 changes: 42 additions & 0 deletions contracts/solidity/test/TestRelayEntry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import BigNumber from 'bignumber.js';
const KeepRandomBeaconProxy = artifacts.require('./KeepRandomBeacon.sol');
const KeepRandomBeaconImplV1 = artifacts.require('./KeepRandomBeaconImplV1.sol');
const KeepGroupStub = artifacts.require('./KeepGroupStub.sol');


contract('TestRelayEntry', function() {

let keepRandomBeaconImplV1, keepRandomBeaconProxy, keepRandomBeaconImplViaProxy, relayEntryGeneratedEvent,
keepGroupStub;

beforeEach(async () => {

// Initialize Keep Random Beacon contract
keepRandomBeaconImplV1 = await KeepRandomBeaconImplV1.new();
keepRandomBeaconProxy = await KeepRandomBeaconProxy.new(keepRandomBeaconImplV1.address);
keepRandomBeaconImplViaProxy = await KeepRandomBeaconImplV1.at(keepRandomBeaconProxy.address);
await keepRandomBeaconImplViaProxy.initialize(1,1);

keepGroupStub = await KeepGroupStub.new();
await keepRandomBeaconImplViaProxy.setGroupContract(keepGroupStub.address);

relayEntryGeneratedEvent = keepRandomBeaconImplViaProxy.RelayEntryGenerated();
});

it("should be able to submit valid relay entry", async function() {
let requestID = 1;

// Data generated using client Go code with master secret key 123
let groupPubKey = "0x1f1954b33144db2b5c90da089e8bde287ec7089d5d6433f3b6becaefdb678b1b2a9de38d14bef2cf9afc3c698a4211fa7ada7b4f036a2dfef0dc122b423259d0";
let previousEntry = new BigNumber('0x884b130ed81751b63d0f5882483d4a24a7640bdf371f23b78dbeb520c84e3a85');
let groupSignature = new BigNumber('0x1fb34abfa2a9844a58776650e399bca3e08ab134e42595e03e3efc5a0472bcd8');

await keepRandomBeaconImplViaProxy.relayEntry(requestID, groupSignature, groupPubKey, previousEntry);

relayEntryGeneratedEvent.get(function(_, result){
assert.equal(result[0].args.requestResponse.equals(groupSignature), true, "Should emit event with successfully submitted groupSignature.");
});

});

});
2 changes: 1 addition & 1 deletion pkg/beacon/relay/event/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
type Entry struct {
RequestID *big.Int
Value *big.Int
GroupID *big.Int
GroupID []byte
PreviousEntry *big.Int
Timestamp time.Time
Seed *big.Int
Expand Down
2 changes: 1 addition & 1 deletion pkg/beacon/relay/relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (n *Node) GenerateRelayEntryIfEligible(
Value: rightSizeSignature,
PreviousEntry: previousValue,
Timestamp: time.Now().UTC(),
GroupID: &big.Int{},
GroupID: make([]byte, 0),
}

relayChain.SubmitRelayEntry(
Expand Down
2 changes: 1 addition & 1 deletion pkg/chain/ethereum/ethereum.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func (ec *ethereumChain) OnRelayEntryGenerated(
func(
requestID *big.Int,
requestResponse *big.Int,
requestGroupID *big.Int,
requestGroupID []byte,
previousEntry *big.Int,
blockNumber *big.Int,
) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/chain/ethereum/keep_random_beacon.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ func (krb *KeepRandomBeacon) RequestRelayEntry(
// SubmitRelayEntry submits a group signature for consideration.
func (krb *KeepRandomBeacon) SubmitRelayEntry(
requestID *big.Int,
groupID *big.Int,
groupID []byte,
previousEntry *big.Int,
groupSignature *big.Int,
) (*types.Transaction, error) {
Expand Down Expand Up @@ -205,7 +205,7 @@ func (krb *KeepRandomBeacon) WatchRelayEntryRequested(
type relayEntryGeneratedFunc func(
requestID *big.Int,
requestResponse *big.Int,
requestGroupID *big.Int,
requestGroupID []byte,
previousEntry *big.Int,
blockNumber *big.Int,
)
Expand Down
4 changes: 2 additions & 2 deletions pkg/chain/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func (c *localChain) SubmitRelayEntry(entry *event.Entry) *async.RelayEntryPromi
c.groupRelayEntriesMutex.Lock()
defer c.groupRelayEntriesMutex.Unlock()

existing, exists := c.groupRelayEntries[entry.GroupID.String()+entry.RequestID.String()]
existing, exists := c.groupRelayEntries[string(entry.GroupID)+entry.RequestID.String()]
if exists {
if existing != entry.Value {
err := fmt.Errorf(
Expand All @@ -159,7 +159,7 @@ func (c *localChain) SubmitRelayEntry(entry *event.Entry) *async.RelayEntryPromi

return relayEntryPromise
}
c.groupRelayEntries[entry.GroupID.String()+entry.RequestID.String()] = entry.Value
c.groupRelayEntries[string(entry.GroupID)+entry.RequestID.String()] = entry.Value

c.handlerMutex.Lock()
for _, handler := range c.relayEntryHandlers {
Expand Down
2 changes: 1 addition & 1 deletion pkg/chain/local/local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func TestLocalSubmitRelayEntry(t *testing.T) {
relayEntryPromise := chainHandle.SubmitRelayEntry(
&event.Entry{
RequestID: big.NewInt(int64(19)),
GroupID: big.NewInt(int64(1)),
GroupID: []byte("1"),
},
)

Expand Down