Skip to content

Commit 52fba22

Browse files
committed
Started creating the contract to actually verify signatures legitimately
1 parent 957c3ee commit 52fba22

File tree

6 files changed

+212
-47
lines changed

6 files changed

+212
-47
lines changed

contracts/Validation.sol

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright (c) 2016-2018 Clearmatics Technologies Ltd
2+
// SPDX-License-Identifier: LGPL-3.0+
3+
pragma solidity ^0.4.23;
4+
5+
import "./ECVerify.sol";
6+
7+
contract Validation {
8+
address Owner;
9+
10+
event broadcastSig(address owner);
11+
event broadcastHashData(bytes header, bytes parentHash, bytes rootHash);
12+
event broadcastHash(bytes32 blockHash);
13+
14+
address[] validators;
15+
16+
/*
17+
* @param _validators list of validators at block 0
18+
*/
19+
constructor (address[] _validators) public {
20+
Owner = msg.sender;
21+
for (uint i = 0; i < _validators.length; i++) {
22+
validators.push(_validators[i]);
23+
}
24+
}
25+
26+
/*
27+
*
28+
*/
29+
function GetValidators() public view returns (address[] _validators) {
30+
return validators;
31+
}
32+
33+
/*
34+
* @param header header rlp encoded, with extraData signatures removed
35+
* @param prefixHeader the new prefix for the signed hash header
36+
* @param prefixExtraData the new prefix for the extraData field
37+
*/
38+
function ValidateBlock(bytes header, bytes prefixHeader, bytes prefixExtraData) public {
39+
uint256 length = header.length;
40+
bytes32 blockHash = keccak256(header);
41+
42+
emit broadcastHash(blockHash);
43+
44+
bytes memory headerStart = new bytes(length - 141);
45+
bytes memory extraData = new bytes(31);
46+
bytes memory extraDataSig = new bytes(65);
47+
bytes memory headerEnd = new bytes(42);
48+
49+
// Extract the start of the header and replace the length
50+
extractData(headerStart, header, 0, headerStart.length);
51+
assembly {
52+
let ret := staticcall(3000, 4, add(prefixHeader, 32), 2, add(headerStart, 33), 2)
53+
}
54+
55+
// Extract the real extra data and create the signed hash
56+
extractData(extraData, header, length-140, extraData.length);
57+
assembly {
58+
let ret := staticcall(3000, 4, add(prefixExtraData, 32), 1, add(extraData, 32), 1)
59+
}
60+
61+
// Extract the end of the header
62+
extractData(headerEnd, header, length-42, headerEnd.length);
63+
bytes memory newHeader = mergeHash(headerStart, extraData, headerEnd);
64+
65+
bytes32 hashData = keccak256(newHeader);
66+
67+
// Extract the signature of the hash create above
68+
extractData(extraDataSig, header, length-107, extraDataSig.length);
69+
70+
address sig_addr = ECVerify.ecrecovery(hashData, extraDataSig);
71+
72+
emit broadcastSig(sig_addr);
73+
74+
}
75+
76+
function mergeHash(bytes headerStart, bytes extraData, bytes headerEnd) internal view returns (bytes output) {
77+
// Get the lengths sorted because they're needed later...
78+
uint256 headerStartLength = headerStart.length;
79+
uint256 extraDataLength = extraData.length;
80+
uint256 extraDataStart = headerStartLength + 32;
81+
uint256 headerEndLength = headerEnd.length;
82+
uint256 headerEndStart = extraDataLength + headerStartLength + 32 + 2;
83+
uint256 newLength = headerStartLength + extraDataLength + headerEndLength + 2; // extra two is for the prefix
84+
bytes memory header = new bytes(newLength);
85+
86+
87+
// Add in the first part of the header
88+
assembly {
89+
let ret := staticcall(3000, 4, add(headerStart, 32), headerStartLength, add(header, 32), headerStartLength)
90+
}
91+
assembly {
92+
let ret := staticcall(3000, 4, add(extraData, 32), extraDataLength, add(header, extraDataStart), extraDataLength)
93+
}
94+
assembly {
95+
let ret := staticcall(3000, 4, add(headerEnd, 32), headerEndLength, add(header, headerEndStart), headerEndLength)
96+
}
97+
98+
output = header;
99+
}
100+
101+
/*
102+
* @param data memory allocation for the data you need to extract
103+
* @param sig array from which the data should be extracted
104+
* @param start index which the data starts within the byte array
105+
* @param length total length of the data to be extracted
106+
*/
107+
function extractData(bytes data, bytes input, uint start, uint length) private pure {
108+
for (uint i=0; i<length; i++) {
109+
data[i] = input[start+i];
110+
}
111+
}
112+
113+
}

migrations/2_deploy_contracts.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
const Recover = artifacts.require("Recover");
2+
const Validation = artifacts.require("Validation");
23

34
module.exports = async (deployer) => {
45
try {
56
deployer.deploy(Recover)
67
.then(() => Recover.deployed)
8+
.then(() => deployer.deploy(Validation, ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"]))
9+
.then(() => Validation.deployed)
710
} catch(err) {
811
console.log('ERROR on deploy:',err);
912
}

src/cli/cli.go

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,16 @@
33
package cli
44

55
import (
6-
// "strings"
7-
86
"fmt"
97
"log"
108
"strconv"
119

1210
"github.com/abiosoft/ishell"
13-
// "github.com/ethereum/go-ethereum/common"
1411
"github.com/ethereum/go-ethereum/rpc"
15-
// "github.com/ethereum/go-ethereum/rlp"
16-
// "github.com/ethereum/go-ethereum/crypto/sha3"
1712

1813
"github.com/validation/src/config"
1914
)
2015

21-
type BlockNonce [8]byte
22-
23-
const (
24-
// BloomByteLength represents the number of bytes used in a header log bloom.
25-
BloomByteLength = 256
26-
27-
// BloomBitLength represents the number of bits used in a header log bloom.
28-
BloomBitLength = 8 * BloomByteLength
29-
)
30-
31-
// Bloom represents a 2048 bit bloom filter.
32-
type Bloom [BloomByteLength]byte
33-
3416
type Block struct {
3517
Number string
3618
}
@@ -99,7 +81,10 @@ func Launch(setup config.Setup) {
9981
},
10082
})
10183

102-
// Get block N and spew out the RLP encoded block
84+
// Get block N, output three items:
85+
// * RLP encoded blockHeader
86+
// * Prefix for signed blockHeader
87+
// * Prefix for extraData minus signatures
10388
shell.AddCmd(&ishell.Cmd{
10489
Name: "getValidBlock",
10590
Help: "Request block [N] from chain [from], calculates the prefixes required for submission to chain [to]",
@@ -118,6 +103,24 @@ func Launch(setup config.Setup) {
118103
},
119104
})
120105

106+
// shell.AddCmd(&ishell.Cmd{
107+
// Name: "submitSignedBlock",
108+
// Help: "Request block [N] from chain [from], calculates the prefixes required for submission to chain [to]",
109+
// Func: func(c *ishell.Context) {
110+
// c.Println("===============================================================")
111+
// if len(c.Args) == 0 {
112+
// c.Println("Choose a block.")
113+
// } else if len(c.Args) > 1 {
114+
// c.Println("Too many arguments entered.")
115+
// } else {
116+
// block := strToHex(c.Args[0])
117+
// c.Println("RLP encode block: " + c.Args[0])
118+
// calculateRlpEncoding(client, block)
119+
// }
120+
// c.Println("===============================================================")
121+
// },
122+
// })
123+
121124
// run shell
122125
shell.Run()
123126
}
@@ -128,7 +131,6 @@ func strToHex(input string) (output string) {
128131
fmt.Println("please input decimal:", err)
129132
return
130133
}
131-
132134
output = strconv.FormatInt(int64(val), 16)
133135

134136
return "0x" + output

src/cli/rpc.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func rlpEncodeBlock(client *rpc.Client, block string) {
6161
fmt.Println("can't get requested block:", err)
6262
return
6363
} else {
64-
blockInterface := generateInterface(blockHeader)
64+
blockInterface := GenerateInterface(blockHeader)
6565
encodedBlock := EncodeBlock(blockInterface)
6666
fmt.Printf("%+x\n", encodedBlock)
6767
}
@@ -74,13 +74,25 @@ func calculateRlpEncoding(client *rpc.Client, block string) {
7474
fmt.Println("can't get requested block:", err)
7575
return
7676
} else {
77-
blockInterface := generateInterface(blockHeader)
77+
// Generate an interface to encode the standard block header
78+
blockInterface := GenerateInterface(blockHeader)
7879
encodedBlock := EncodeBlock(blockInterface)
7980
fmt.Printf("%+x\n", encodedBlock)
81+
82+
// Generate an interface to encode the blockheader without the signature in the extraData
83+
blockHeader.Extra = blockHeader.Extra[:len(blockHeader.Extra)-130]
84+
blockInterface = GenerateInterface(blockHeader)
85+
encodedBlock = EncodeBlock(blockInterface)
86+
fmt.Printf("\n%+x\n", encodedBlock[1:3])
87+
88+
// Generate an interface to encode the blockheader without the signature in the extraData
89+
encExtra, _ := hex.DecodeString(blockHeader.Extra[2:])
90+
encodedBlock = EncodeBlock(encExtra)
91+
fmt.Printf("\n%+x\n", encodedBlock[0:1])
8092
}
8193
}
8294

83-
func generateInterface(blockHeader Header) (rest interface{}) {
95+
func GenerateInterface(blockHeader Header) (rest interface{}) {
8496
blockInterface := []interface{}{}
8597
s := reflect.ValueOf(&blockHeader).Elem()
8698

src/cli/rpc_test.go

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,18 @@
22

33
package cli_test
44

5-
import (
6-
7-
"io/ioutil"
8-
"encoding/json"
9-
"encoding/hex"
10-
"testing"
11-
12-
"github.com/validation/src/cli"
13-
"github.com/stretchr/testify/assert"
14-
)
15-
16-
func Test_EncodeBlock(t *testing.T) {
17-
// read a fake block
18-
raw, _ := ioutil.ReadFile("../block.json")
19-
20-
const expectedRlpHex = "f90256a0ad34f0f919e4b06b18b0c674b8b9f6738a4878c76e837c8f31a2079f21dced1ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0db37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a83fd82da80845b28beecb861d78301080a846765746887676f312e392e33856c696e75780000000000000000e0ac79c5577889dfb5745ace9c5dfebe1a11bb19ced9b98b427e7bd4c85765ce17154e658440915743ec442fb64756483bc592616754d13a3c62fce5a56ac9f501a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"
21-
22-
marshalledBlock := cli.Header{}
23-
json.Unmarshal(raw, &marshalledBlock)
24-
25-
// Now RLP encode the block
26-
hash := cli.EncodeBlock(marshalledBlock)
27-
assert.Equal(t, expectedRlpHex, hex.EncodeToString(hash))
28-
}
5+
// func Test_EncodeBlock(t *testing.T) {
6+
// // read a fake block
7+
// raw, _ := ioutil.ReadFile("../block.json")
8+
//
9+
// const expectedRlpHex = "f90256a0ad34f0f919e4b06b18b0c674b8b9f6738a4878c76e837c8f31a2079f21dced1ca01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0db37435caa1fca7e1aa5b4da1c69fdf1d127232519eb3b1b5069825e6c62f5dca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020a83fd82da80845b28beecb861d78301080a846765746887676f312e392e33856c696e75780000000000000000e0ac79c5577889dfb5745ace9c5dfebe1a11bb19ced9b98b427e7bd4c85765ce17154e658440915743ec442fb64756483bc592616754d13a3c62fce5a56ac9f501a00000000000000000000000000000000000000000000000000000000000000000880000000000000000"
10+
//
11+
// var marshalledBlock cli.Header
12+
// json.Unmarshal(raw, &marshalledBlock)
13+
//
14+
// // Now RLP encode the block
15+
// blockInterface := cli.GenerateInterface(marshalledBlock)
16+
// fmt.Printf("%+v\n", marshalledBlock.Extra)
17+
// hash := cli.EncodeBlock(blockInterface)
18+
// assert.Equal(t, expectedRlpHex, hex.EncodeToString(hash))
19+
// }

test/validation.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright (c) 2016-2018 Clearmatics Technologies Ltd
2+
// SPDX-License-Identifier: LGPL-3.0+
3+
4+
const Web3 = require('web3');
5+
const Web3Utils = require('web3-utils');
6+
const Web3Abi = require('web3-eth-abi');
7+
const Web3Accounts = require('web3-eth-accounts');
8+
const rlp = require('rlp');
9+
10+
const Validation = artifacts.require("Validation");
11+
12+
13+
const web3 = new Web3();
14+
15+
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8501'));
16+
17+
function hexToBytes(hex) {
18+
for (var bytes = [], c = 0; c < hex.length; c += 2)
19+
bytes.push(parseInt(hex.substr(c, 2), 16));
20+
return bytes;
21+
}
22+
23+
function bytesToHex(bytes) {
24+
for (var hex = [], i = 0; i < bytes.length; i++) {
25+
hex.push((bytes[i] >>> 4).toString(16));
26+
hex.push((bytes[i] & 0xF).toString(16));
27+
}
28+
return hex.join("");
29+
}
30+
31+
contract.only('validation.js', (accounts) => {
32+
const joinHex = arr => '0x' + arr.map(el => el.slice(2)).join('')
33+
34+
const validators = ["0x2be5ab0e43b6dc2908d5321cf318f35b80d0c10d", "0x8671e5e08d74f338ee1c462340842346d797afd3"];
35+
36+
it('Test: GetValidators()', async () => {
37+
const validation = await Validation.new(validators);
38+
const accounts = web3.eth.accounts;
39+
const signer = accounts[0];
40+
41+
const validatorsReceipt = await validation.GetValidators();
42+
assert.equal(validators[0], validatorsReceipt[0])
43+
})
44+
});

0 commit comments

Comments
 (0)