Skip to content
This repository was archived by the owner on Mar 19, 2019. It is now read-only.

Commit 806e407

Browse files
authored
added boilerplate code for multihash (#320)
* added boilerplate code for multihash * minor * remove ringhash from RingMined event * Optimized bytesToBytes32() (#321) * minor improvement
1 parent c64dfa5 commit 806e407

File tree

4 files changed

+125
-69
lines changed

4 files changed

+125
-69
lines changed

contracts/LoopringProtocol.sol

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,12 @@ contract LoopringProtocol {
6666
/// validUntil (second), lrcFee, and cancelAmount.
6767
/// @param option This indicates when a order should be considered
6868
/// as 'completely filled'.
69-
/// @param v Order ECDSA signature parameter v.
70-
/// @param r Order ECDSA signature parameters r.
71-
/// @param s Order ECDSA signature parameters s.
69+
/// @param sig Order's signature.
7270
function cancelOrder(
7371
address[6] addresses,
7472
uint[6] values,
7573
uint8 option,
76-
uint8 v,
77-
bytes32 r,
78-
bytes32 s
74+
bytes sig
7975
)
8076
external;
8177

@@ -110,15 +106,7 @@ contract LoopringProtocol {
110106
/// amountS, amountB, validSince (second),
111107
/// validUntil (second), lrcFee, and rateAmountS.
112108
/// @param optionList This indicates when a order should be considered
113-
/// @param vList List of v for each order. This list is 1-larger than
114-
/// the previous lists, with the last element being the
115-
/// v value of the ring signature.
116-
/// @param rList List of r for each order. This list is 1-larger than
117-
/// the previous lists, with the last element being the
118-
/// r value of the ring signature.
119-
/// @param sList List of s for each order. This list is 1-larger than
120-
/// the previous lists, with the last element being the
121-
/// s value of the ring signature.
109+
/// @param sigList Signature lists.
122110
/// @param miner Miner address.
123111
/// @param feeSelections -
124112
/// Bits to indicate fee selections. `1` represents margin
@@ -127,9 +115,7 @@ contract LoopringProtocol {
127115
address[5][] addressesList,
128116
uint[6][] valuesList,
129117
bool[] optionList,
130-
uint8[] vList,
131-
bytes32[] rList,
132-
bytes32[] sList,
118+
bytes[] sigList,
133119
address miner,
134120
uint8 feeSelections
135121
)

contracts/LoopringProtocolImpl.sol

Lines changed: 16 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pragma experimental "ABIEncoderV2";
2121
import "./lib/AddressUtil.sol";
2222
import "./lib/ERC20.sol";
2323
import "./lib/MathUint.sol";
24+
import "./lib/MultihashUtil.sol";
2425
import "./BrokerRegistry.sol";
2526
import "./BrokerTracker.sol";
2627
import "./LoopringProtocol.sol";
@@ -96,9 +97,7 @@ contract LoopringProtocolImpl is LoopringProtocol {
9697
address[5][] addressesList;
9798
uint[6][] valuesList;
9899
uint8[] optionList;
99-
uint8[] vList;
100-
bytes32[] rList;
101-
bytes32[] sList;
100+
bytes[] sigList;
102101
address miner;
103102
uint8 feeSelections;
104103
uint64 ringIndex;
@@ -144,9 +143,7 @@ contract LoopringProtocolImpl is LoopringProtocol {
144143
address[6] addresses,
145144
uint[6] orderValues,
146145
uint8 option,
147-
uint8 v,
148-
bytes32 r,
149-
bytes32 s
146+
bytes sig
150147
)
151148
external
152149
{
@@ -185,12 +182,10 @@ contract LoopringProtocolImpl is LoopringProtocol {
185182

186183
bytes32 orderHash = calculateOrderHash(order);
187184

188-
verifySignature(
185+
MultihashUtil.verifySignature(
189186
order.signer,
190187
orderHash,
191-
v,
192-
r,
193-
s
188+
sig
194189
);
195190

196191
if (order.signer != order.owner) {
@@ -258,9 +253,7 @@ contract LoopringProtocolImpl is LoopringProtocol {
258253
address[5][] addressesList,
259254
uint[6][] valuesList,
260255
uint8[] optionList,
261-
uint8[] vList,
262-
bytes32[] rList,
263-
bytes32[] sList,
256+
bytes[] sigList,
264257
address miner,
265258
uint8 feeSelections
266259
)
@@ -270,9 +263,7 @@ contract LoopringProtocolImpl is LoopringProtocol {
270263
addressesList,
271264
valuesList,
272265
optionList,
273-
vList,
274-
rList,
275-
sList,
266+
sigList,
276267
miner,
277268
feeSelections,
278269
ringIndex,
@@ -349,10 +340,10 @@ contract LoopringProtocolImpl is LoopringProtocol {
349340
"invalid ring size"
350341
);
351342

352-
uint sigSize = ctx.ringSize << 1;
353-
require(sigSize == ctx.vList.length, "invalid vList size");
354-
require(sigSize == ctx.rList.length, "invalid rList size");
355-
require(sigSize == ctx.sList.length, "invalid sList size");
343+
require(
344+
(ctx.ringSize << 1) == ctx.sigList.length,
345+
"invalid signature size"
346+
);
356347
}
357348

358349
/// @dev Assemble input data into structs so we can pass them to other functions.
@@ -399,13 +390,11 @@ contract LoopringProtocolImpl is LoopringProtocol {
399390

400391
order.orderHash = calculateOrderHash(order);
401392

402-
verifySignature(
393+
MultihashUtil.verifySignature(
403394
order.signer,
404395
order.orderHash,
405-
ctx.vList[i],
406-
ctx.rList[i],
407-
ctx.sList[i]
408-
);
396+
ctx.sigList[i]
397+
);
409398

410399
if (order.signer != order.owner) {
411400
BrokerRegistry brokerRegistry = BrokerRegistry(brokerRegistryAddress);
@@ -464,12 +453,10 @@ contract LoopringProtocolImpl is LoopringProtocol {
464453
for (uint i = 0; i < ctx.ringSize; i++) {
465454
j = i + ctx.ringSize;
466455

467-
verifySignature(
456+
MultihashUtil.verifySignature(
468457
ctx.orders[i].authAddr,
469458
ctx.ringHash,
470-
ctx.vList[j],
471-
ctx.rList[j],
472-
ctx.sList[j]
459+
ctx.sigList[i]
473460
);
474461
}
475462
}
@@ -927,28 +914,6 @@ contract LoopringProtocolImpl is LoopringProtocol {
927914
);
928915
}
929916

930-
/// @dev Verify signer's signature.
931-
function verifySignature(
932-
address signer,
933-
bytes32 hash,
934-
uint8 v,
935-
bytes32 r,
936-
bytes32 s
937-
)
938-
private
939-
pure
940-
{
941-
require(
942-
signer == ecrecover(
943-
keccak256("\x19Ethereum Signed Message:\n32", hash),
944-
v,
945-
r,
946-
s
947-
),
948-
"bad signature"
949-
);
950-
}
951-
952917
function getTradingPairCutoffs(
953918
address orderOwner,
954919
address token1,

contracts/lib/BytesUtil.sol

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
3+
Copyright 2017 Loopring Project Ltd (Loopring Foundation).
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
pragma solidity 0.4.23;
18+
pragma experimental "v0.5.0";
19+
pragma experimental "ABIEncoderV2";
20+
21+
22+
/// @title Utility Functions for bytes
23+
/// @author Daniel Wang - <[email protected]>
24+
library BytesUtil {
25+
function bytesToBytes32(
26+
bytes b,
27+
uint offset
28+
)
29+
public
30+
pure
31+
returns (bytes32 out)
32+
{
33+
require(b.length >= offset + 32);
34+
bytes32 temp;
35+
assembly {
36+
temp := mload(add(add(b, 0x20), offset))
37+
}
38+
return temp;
39+
}
40+
}

contracts/lib/MultihashUtil.sol

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
3+
Copyright 2017 Loopring Project Ltd (Loopring Foundation).
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
pragma solidity 0.4.23;
18+
pragma experimental "v0.5.0";
19+
pragma experimental "ABIEncoderV2";
20+
21+
import "./BytesUtil.sol";
22+
23+
24+
/// @title Utility Functions for Multihash signature verificaiton
25+
/// @author Daniel Wang - <[email protected]>
26+
/// For more information:
27+
/// - https://github.com/saurfang/ipfs-multihash-on-solidity
28+
/// - https://github.com/multiformats/multihash
29+
/// - https://github.com/multiformats/js-multihash
30+
library MultihashUtil {
31+
32+
string public constant SIG_PREFIX = "\x19Ethereum Signed Message:\n32";
33+
34+
function verifySignature(
35+
address signer,
36+
bytes32 plaintext,
37+
bytes multihash
38+
)
39+
public
40+
pure
41+
{
42+
uint8 algorithm = uint8(multihash[0]);
43+
uint8 size = uint8(multihash[1]);
44+
require(multihash.length == (2 + size), "bad multihash size");
45+
46+
// Currently we default 0 to be the Ethereum's default signature.
47+
if (algorithm == 0) {
48+
require(size == 65, "bad multihash size");
49+
require(
50+
signer == ecrecover(
51+
keccak256(
52+
SIG_PREFIX,
53+
plaintext
54+
),
55+
uint8(multihash[2]),
56+
BytesUtil.bytesToBytes32(multihash, 3),
57+
BytesUtil.bytesToBytes32(multihash, 11)
58+
),
59+
"bad signature"
60+
);
61+
} else {
62+
revert("unsupported algorithm");
63+
}
64+
}
65+
}

0 commit comments

Comments
 (0)