@arbitrum/nitro-contracts 1.0.0-beta.1
Sign up to get free protection for your applications and to get access to all the features.
- package/.prettierrc +5 -0
- package/.solhint.json +18 -0
- package/deploy/BridgeStubCreator.js +10 -0
- package/deploy/HashProofHelper.js +13 -0
- package/deploy/InboxStubCreator.js +17 -0
- package/deploy/OneStepProofEntryCreator.js +19 -0
- package/deploy/OneStepProver0Creator.js +14 -0
- package/deploy/OneStepProverHostIoCreator.js +14 -0
- package/deploy/OneStepProverMathCreator.js +14 -0
- package/deploy/OneStepProverMemoryCreator.js +14 -0
- package/deploy/SequencerInboxStubCreator.js +13 -0
- package/deploy/ValueArrayTesterCreator.js +13 -0
- package/hardhat.config.ts +47 -0
- package/hardhat.prod-config.js +18 -0
- package/package.json +49 -0
- package/scripts/build.bash +5 -0
- package/src/bridge/Bridge.sol +168 -0
- package/src/bridge/IBridge.sol +68 -0
- package/src/bridge/IInbox.sol +80 -0
- package/src/bridge/IMessageProvider.sol +11 -0
- package/src/bridge/IOutbox.sol +52 -0
- package/src/bridge/ISequencerInbox.sol +85 -0
- package/src/bridge/Inbox.sol +414 -0
- package/src/bridge/Messages.sol +38 -0
- package/src/bridge/Outbox.sol +188 -0
- package/src/bridge/SequencerInbox.sol +274 -0
- package/src/challenge/ChallengeLib.sol +135 -0
- package/src/challenge/ChallengeManager.sol +367 -0
- package/src/challenge/IChallengeManager.sol +75 -0
- package/src/challenge/IChallengeResultReceiver.sol +13 -0
- package/src/libraries/AddressAliasHelper.sol +29 -0
- package/src/libraries/AdminFallbackProxy.sol +153 -0
- package/src/libraries/ArbitrumProxy.sol +20 -0
- package/src/libraries/Constants.sol +10 -0
- package/src/libraries/CryptographyPrimitives.sol +323 -0
- package/src/libraries/DelegateCallAware.sol +44 -0
- package/src/libraries/Error.sol +38 -0
- package/src/libraries/IGasRefunder.sol +35 -0
- package/src/libraries/MerkleLib.sol +46 -0
- package/src/libraries/MessageTypes.sol +14 -0
- package/src/libraries/SecondaryLogicUUPSUpgradeable.sol +58 -0
- package/src/libraries/UUPSNotUpgradeable.sol +56 -0
- package/src/mocks/BridgeStub.sol +115 -0
- package/src/mocks/Counter.sol +13 -0
- package/src/mocks/ExecutionManager.sol +41 -0
- package/src/mocks/InboxStub.sol +131 -0
- package/src/mocks/MockResultReceiver.sol +59 -0
- package/src/mocks/SequencerInboxStub.sol +42 -0
- package/src/mocks/SimpleProxy.sol +19 -0
- package/src/node-interface/NodeInterface.sol +50 -0
- package/src/osp/HashProofHelper.sol +154 -0
- package/src/osp/IOneStepProofEntry.sol +20 -0
- package/src/osp/IOneStepProver.sol +27 -0
- package/src/osp/OneStepProofEntry.sol +129 -0
- package/src/osp/OneStepProver0.sol +566 -0
- package/src/osp/OneStepProverHostIo.sol +357 -0
- package/src/osp/OneStepProverMath.sol +514 -0
- package/src/osp/OneStepProverMemory.sol +313 -0
- package/src/precompiles/ArbAddressTable.sol +60 -0
- package/src/precompiles/ArbAggregator.sol +62 -0
- package/src/precompiles/ArbBLS.sol +53 -0
- package/src/precompiles/ArbDebug.sol +39 -0
- package/src/precompiles/ArbFunctionTable.sol +29 -0
- package/src/precompiles/ArbGasInfo.sol +121 -0
- package/src/precompiles/ArbInfo.sol +15 -0
- package/src/precompiles/ArbOwner.sol +65 -0
- package/src/precompiles/ArbOwnerPublic.sol +18 -0
- package/src/precompiles/ArbRetryableTx.sol +89 -0
- package/src/precompiles/ArbStatistics.sol +29 -0
- package/src/precompiles/ArbSys.sol +134 -0
- package/src/precompiles/ArbosActs.sol +41 -0
- package/src/precompiles/ArbosTest.sol +14 -0
- package/src/rollup/BridgeCreator.sol +120 -0
- package/src/rollup/IRollupCore.sol +152 -0
- package/src/rollup/IRollupLogic.sol +183 -0
- package/src/rollup/Node.sol +99 -0
- package/src/rollup/RollupAdminLogic.sol +322 -0
- package/src/rollup/RollupCore.sol +627 -0
- package/src/rollup/RollupCreator.sol +133 -0
- package/src/rollup/RollupEventBridge.sol +46 -0
- package/src/rollup/RollupLib.sol +135 -0
- package/src/rollup/RollupUserLogic.sol +712 -0
- package/src/rollup/ValidatorUtils.sol +243 -0
- package/src/rollup/ValidatorWallet.sol +76 -0
- package/src/rollup/ValidatorWalletCreator.sol +43 -0
- package/src/state/Deserialize.sol +321 -0
- package/src/state/GlobalState.sol +44 -0
- package/src/state/Instructions.sol +159 -0
- package/src/state/Machine.sol +65 -0
- package/src/state/MerkleProof.sol +99 -0
- package/src/state/Module.sol +33 -0
- package/src/state/ModuleMemory.sol +42 -0
- package/src/state/PcArray.sol +45 -0
- package/src/state/PcStack.sol +32 -0
- package/src/state/StackFrame.sol +63 -0
- package/src/state/Value.sol +65 -0
- package/src/state/ValueArray.sol +47 -0
- package/src/state/ValueStack.sol +39 -0
- package/src/test-helpers/CryptographyPrimitivesTester.sol +27 -0
- package/src/test-helpers/MessageTester.sol +34 -0
- package/src/test-helpers/ValueArrayTester.sol +34 -0
- package/test/contract/arbRollup.spec.ts +869 -0
- package/test/contract/common/challengeLib.ts +43 -0
- package/test/contract/common/globalStateLib.ts +17 -0
- package/test/contract/common/rolluplib.ts +259 -0
- package/test/contract/cryptographyPrimitives.spec.ts +82 -0
- package/test/contract/sequencerInboxForceInclude.spec.ts +516 -0
- package/test/contract/utils.ts +40 -0
- package/test/prover/hash-proofs.ts +75 -0
- package/test/prover/one-step-proof.ts +93 -0
- package/test/prover/proofs/.gitkeep +0 -0
- package/test/prover/value-arrays.ts +11 -0
- package/tsconfig.json +13 -0
@@ -0,0 +1,43 @@
|
|
1
|
+
import { BigNumber } from '@ethersproject/bignumber'
|
2
|
+
import { solidityKeccak256 } from 'ethers/lib/utils'
|
3
|
+
|
4
|
+
export enum MachineStatus {
|
5
|
+
RUNNING = 0,
|
6
|
+
FINISHED = 1,
|
7
|
+
ERRORED = 2,
|
8
|
+
TOO_FAR = 3,
|
9
|
+
}
|
10
|
+
|
11
|
+
export function hashChallengeState(
|
12
|
+
segmentsStart: BigNumber,
|
13
|
+
segmentsLength: BigNumber,
|
14
|
+
segments: string[],
|
15
|
+
) {
|
16
|
+
return solidityKeccak256(
|
17
|
+
['uint256', 'uint256', 'bytes32[]'],
|
18
|
+
[segmentsStart, segmentsLength, segments],
|
19
|
+
)
|
20
|
+
}
|
21
|
+
|
22
|
+
export function blockStateHash(
|
23
|
+
machineStatus: BigNumber,
|
24
|
+
globalStateHash: string,
|
25
|
+
) {
|
26
|
+
const machineStatusNum = machineStatus.toNumber()
|
27
|
+
if (machineStatusNum === MachineStatus.FINISHED) {
|
28
|
+
return solidityKeccak256(
|
29
|
+
['string', 'bytes32'],
|
30
|
+
['Block state:', globalStateHash],
|
31
|
+
)
|
32
|
+
} else if (machineStatusNum === MachineStatus.ERRORED) {
|
33
|
+
return solidityKeccak256(
|
34
|
+
['string', 'bytes32'],
|
35
|
+
['Block state, errored:', globalStateHash],
|
36
|
+
)
|
37
|
+
} else if (machineStatusNum === MachineStatus.TOO_FAR) {
|
38
|
+
return solidityKeccak256(['string', 'bytes32'], ['Block state, too far:'])
|
39
|
+
} else {
|
40
|
+
console.log(machineStatus.toNumber())
|
41
|
+
throw new Error('BAD_BLOCK_STATUS')
|
42
|
+
}
|
43
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import {
|
2
|
+
GlobalStateStruct,
|
3
|
+
} from '../../../build/types/RollupUserLogic'
|
4
|
+
import { solidityKeccak256 } from 'ethers/lib/utils'
|
5
|
+
|
6
|
+
export function hash(state: GlobalStateStruct) {
|
7
|
+
return solidityKeccak256(
|
8
|
+
['string', 'bytes32', 'bytes32', 'uint64', 'uint64'],
|
9
|
+
[
|
10
|
+
'Global state:',
|
11
|
+
state.bytes32Vals[0],
|
12
|
+
state.bytes32Vals[1],
|
13
|
+
state.u64Vals[0],
|
14
|
+
state.u64Vals[1],
|
15
|
+
],
|
16
|
+
)
|
17
|
+
}
|
@@ -0,0 +1,259 @@
|
|
1
|
+
import { ethers } from "hardhat";
|
2
|
+
import { Interface, LogDescription } from "@ethersproject/abi";
|
3
|
+
import { Signer } from "@ethersproject/abstract-signer";
|
4
|
+
import { BigNumberish, BigNumber } from "@ethersproject/bignumber";
|
5
|
+
import { BytesLike } from "@ethersproject/bytes";
|
6
|
+
import { ContractTransaction, PayableOverrides } from "@ethersproject/contracts";
|
7
|
+
import { Provider } from "@ethersproject/providers";
|
8
|
+
import { RollupUserLogic, RollupAdminLogic, SequencerInbox } from "../../../build/types";
|
9
|
+
import {
|
10
|
+
RollupLib,
|
11
|
+
NodeCreatedEvent,
|
12
|
+
} from "../../../build/types/RollupUserLogic";
|
13
|
+
type AssertionStruct = RollupLib.AssertionStruct;
|
14
|
+
type ExecutionStateStruct = RollupLib.ExecutionStateStruct;
|
15
|
+
import { blockStateHash, hashChallengeState } from "./challengeLib";
|
16
|
+
import * as globalStateLib from "./globalStateLib";
|
17
|
+
import { constants } from "ethers";
|
18
|
+
import { GlobalStateStruct } from "../../../build/types/ChallengeManager";
|
19
|
+
|
20
|
+
export interface Node {
|
21
|
+
nodeNum: number;
|
22
|
+
proposedBlock: number;
|
23
|
+
assertion: AssertionStruct;
|
24
|
+
inboxMaxCount: BigNumber;
|
25
|
+
nodeHash: BytesLike;
|
26
|
+
wasmModuleRoot: BytesLike;
|
27
|
+
}
|
28
|
+
|
29
|
+
export function nodeHash(
|
30
|
+
hasSibling: boolean,
|
31
|
+
lastHash: BytesLike,
|
32
|
+
assertionExecHash: BytesLike,
|
33
|
+
inboxAcc: BytesLike
|
34
|
+
): BytesLike {
|
35
|
+
return ethers.utils.solidityKeccak256(
|
36
|
+
["bool", "bytes32", "bytes32", "bytes32"],
|
37
|
+
[hasSibling, lastHash, assertionExecHash, inboxAcc]
|
38
|
+
);
|
39
|
+
}
|
40
|
+
|
41
|
+
const globalStateEquals = (globalState1: GlobalStateStruct, globalState2: GlobalStateStruct) => {
|
42
|
+
return (
|
43
|
+
globalState1.bytes32Vals[0] === globalState2.bytes32Vals[0] &&
|
44
|
+
globalState1.bytes32Vals[1] === globalState2.bytes32Vals[1] &&
|
45
|
+
BigNumber.from(globalState1.u64Vals[0]).eq(globalState2.u64Vals[0]) &&
|
46
|
+
BigNumber.from(globalState1.u64Vals[1]).eq(globalState2.u64Vals[1])
|
47
|
+
);
|
48
|
+
};
|
49
|
+
|
50
|
+
export const executionStateEquals = (
|
51
|
+
executionState1: ExecutionStateStruct,
|
52
|
+
executionState2: ExecutionStateStruct
|
53
|
+
) => {
|
54
|
+
return (
|
55
|
+
globalStateEquals(executionState1.globalState, executionState2.globalState) &&
|
56
|
+
BigNumber.from(executionState1.machineStatus).eq(executionState2.machineStatus)
|
57
|
+
);
|
58
|
+
};
|
59
|
+
|
60
|
+
export const assertionEquals = (assertion1: AssertionStruct, assertion2: AssertionStruct) => {
|
61
|
+
return (
|
62
|
+
executionStateEquals(assertion1.beforeState, assertion2.beforeState) &&
|
63
|
+
executionStateEquals(assertion1.afterState, assertion2.afterState) &&
|
64
|
+
BigNumber.from(assertion1.numBlocks).eq(assertion2.numBlocks)
|
65
|
+
);
|
66
|
+
};
|
67
|
+
|
68
|
+
export function executionStateHash(e: ExecutionStateStruct, inboxMaxCount: BigNumberish) {
|
69
|
+
return ethers.utils.solidityKeccak256(
|
70
|
+
["bytes32", "uint256", "uint8"],
|
71
|
+
[globalStateLib.hash(e.globalState), inboxMaxCount, e.machineStatus]
|
72
|
+
);
|
73
|
+
}
|
74
|
+
|
75
|
+
export function executionStructHash(e: ExecutionStateStruct) {
|
76
|
+
return ethers.utils.solidityKeccak256(
|
77
|
+
["bytes32", "uint8"],
|
78
|
+
[globalStateLib.hash(e.globalState), e.machineStatus]
|
79
|
+
);
|
80
|
+
}
|
81
|
+
|
82
|
+
export function assertionExecutionHash(a: AssertionStruct): BytesLike {
|
83
|
+
const seg0 = blockStateHash(
|
84
|
+
BigNumber.from(a.beforeState.machineStatus),
|
85
|
+
globalStateLib.hash(a.beforeState.globalState)
|
86
|
+
);
|
87
|
+
const seg1 = blockStateHash(
|
88
|
+
BigNumber.from(a.afterState.machineStatus),
|
89
|
+
globalStateLib.hash(a.afterState.globalState)
|
90
|
+
);
|
91
|
+
return hashChallengeState(BigNumber.from(0), BigNumber.from(a.numBlocks), [seg0, seg1]);
|
92
|
+
}
|
93
|
+
|
94
|
+
async function nodeFromNodeCreatedLog(blockNumber: number, log: LogDescription): Promise<Node> {
|
95
|
+
if (log.name != "NodeCreated") {
|
96
|
+
throw Error("wrong event type");
|
97
|
+
}
|
98
|
+
const parsedEv = log.args as NodeCreatedEvent["args"];
|
99
|
+
|
100
|
+
const node: Node = {
|
101
|
+
assertion: parsedEv.assertion,
|
102
|
+
nodeHash: parsedEv.nodeHash,
|
103
|
+
wasmModuleRoot: parsedEv.wasmModuleRoot,
|
104
|
+
nodeNum: parsedEv.nodeNum.toNumber(),
|
105
|
+
proposedBlock: blockNumber,
|
106
|
+
inboxMaxCount: parsedEv.inboxMaxCount,
|
107
|
+
};
|
108
|
+
return node;
|
109
|
+
}
|
110
|
+
|
111
|
+
async function nodeFromTx(abi: Interface, tx: ContractTransaction): Promise<Node> {
|
112
|
+
const receipt = await tx.wait();
|
113
|
+
if (receipt.logs == undefined) {
|
114
|
+
throw Error("expected receipt to have logs");
|
115
|
+
}
|
116
|
+
const evs = receipt.logs
|
117
|
+
.map((log) => {
|
118
|
+
try {
|
119
|
+
return abi.parseLog(log);
|
120
|
+
} catch (e) {
|
121
|
+
return undefined;
|
122
|
+
}
|
123
|
+
})
|
124
|
+
.filter((ev) => ev && ev.name == "NodeCreated");
|
125
|
+
if (evs.length != 1) {
|
126
|
+
throw Error("unique event not found");
|
127
|
+
}
|
128
|
+
|
129
|
+
return nodeFromNodeCreatedLog(receipt.blockNumber, evs[0]!);
|
130
|
+
}
|
131
|
+
|
132
|
+
export class RollupContract {
|
133
|
+
constructor(public rollup: RollupUserLogic) {}
|
134
|
+
|
135
|
+
connect(signerOrProvider: Signer | Provider | string): RollupContract {
|
136
|
+
return new RollupContract(this.rollup.connect(signerOrProvider));
|
137
|
+
}
|
138
|
+
|
139
|
+
async stakeOnNewNode(
|
140
|
+
sequencerInbox: SequencerInbox,
|
141
|
+
parentNode: {
|
142
|
+
nodeHash: BytesLike;
|
143
|
+
inboxMaxCount: BigNumber;
|
144
|
+
},
|
145
|
+
assertion: AssertionStruct,
|
146
|
+
siblingNode?: Node,
|
147
|
+
stakeToAdd?: BigNumber
|
148
|
+
): Promise<{
|
149
|
+
tx: ContractTransaction;
|
150
|
+
node: Node;
|
151
|
+
expectedNewNodeHash: BytesLike;
|
152
|
+
}> {
|
153
|
+
const inboxPosition = BigNumber.from(assertion.afterState.globalState.u64Vals[0]).toNumber();
|
154
|
+
const afterInboxAcc =
|
155
|
+
inboxPosition > 0 ? await sequencerInbox.inboxAccs(inboxPosition - 1) : constants.HashZero;
|
156
|
+
const newNodeHash = nodeHash(
|
157
|
+
!!siblingNode,
|
158
|
+
(siblingNode || parentNode).nodeHash,
|
159
|
+
assertionExecutionHash(assertion),
|
160
|
+
afterInboxAcc
|
161
|
+
);
|
162
|
+
const tx = stakeToAdd
|
163
|
+
? await this.rollup.newStakeOnNewNode(assertion, newNodeHash, parentNode.inboxMaxCount, {
|
164
|
+
value: stakeToAdd,
|
165
|
+
})
|
166
|
+
: await this.rollup.stakeOnNewNode(assertion, newNodeHash, parentNode.inboxMaxCount);
|
167
|
+
const node = await nodeFromTx(this.rollup.interface, tx);
|
168
|
+
return { tx, node, expectedNewNodeHash: newNodeHash };
|
169
|
+
}
|
170
|
+
|
171
|
+
stakeOnExistingNode(nodeNum: BigNumberish, nodeHash: BytesLike): Promise<ContractTransaction> {
|
172
|
+
return this.rollup.stakeOnExistingNode(nodeNum, nodeHash);
|
173
|
+
}
|
174
|
+
|
175
|
+
confirmNextNode(
|
176
|
+
node: Node,
|
177
|
+
): Promise<ContractTransaction> {
|
178
|
+
return this.rollup.confirmNextNode(
|
179
|
+
node.assertion.afterState.globalState.bytes32Vals[0],
|
180
|
+
node.assertion.afterState.globalState.bytes32Vals[1]
|
181
|
+
);
|
182
|
+
}
|
183
|
+
|
184
|
+
rejectNextNode(stakerAddress: string): Promise<ContractTransaction> {
|
185
|
+
return this.rollup.rejectNextNode(stakerAddress);
|
186
|
+
}
|
187
|
+
|
188
|
+
async createChallenge(
|
189
|
+
staker1Address: string,
|
190
|
+
staker2Address: string,
|
191
|
+
node1: Node,
|
192
|
+
node2: Node
|
193
|
+
): Promise<ContractTransaction> {
|
194
|
+
return this.rollup.createChallenge(
|
195
|
+
[staker1Address, staker2Address],
|
196
|
+
[node1.nodeNum, node2.nodeNum],
|
197
|
+
[node1.assertion.beforeState.machineStatus, node1.assertion.afterState.machineStatus],
|
198
|
+
[node1.assertion.beforeState.globalState, node1.assertion.afterState.globalState],
|
199
|
+
node1.assertion.numBlocks,
|
200
|
+
assertionExecutionHash(node2.assertion),
|
201
|
+
[node1.proposedBlock, node2.proposedBlock],
|
202
|
+
[node1.wasmModuleRoot, node2.wasmModuleRoot]
|
203
|
+
);
|
204
|
+
}
|
205
|
+
|
206
|
+
addToDeposit(staker: string, overrides: PayableOverrides = {}): Promise<ContractTransaction> {
|
207
|
+
return this.rollup.addToDeposit(staker, overrides);
|
208
|
+
}
|
209
|
+
|
210
|
+
reduceDeposit(amount: BigNumberish): Promise<ContractTransaction> {
|
211
|
+
return this.rollup.reduceDeposit(amount);
|
212
|
+
}
|
213
|
+
|
214
|
+
returnOldDeposit(stakerAddress: string): Promise<ContractTransaction> {
|
215
|
+
return this.rollup.returnOldDeposit(stakerAddress);
|
216
|
+
}
|
217
|
+
|
218
|
+
latestConfirmed(): Promise<BigNumber> {
|
219
|
+
return this.rollup.latestConfirmed();
|
220
|
+
}
|
221
|
+
|
222
|
+
getNodeStateHash(index: BigNumberish): Promise<string> {
|
223
|
+
return this.rollup.getNode(index).then((n) => n.stateHash);
|
224
|
+
}
|
225
|
+
|
226
|
+
latestStakedNode(staker: string): Promise<BigNumber> {
|
227
|
+
return this.rollup.latestStakedNode(staker);
|
228
|
+
}
|
229
|
+
|
230
|
+
currentRequiredStake(): Promise<BigNumber> {
|
231
|
+
return this.rollup.currentRequiredStake();
|
232
|
+
}
|
233
|
+
}
|
234
|
+
|
235
|
+
export async function forceCreateNode(
|
236
|
+
rollupAdmin: RollupAdminLogic,
|
237
|
+
sequencerInbox: SequencerInbox,
|
238
|
+
parentNode: Node,
|
239
|
+
assertion: AssertionStruct,
|
240
|
+
siblingNode?: Node
|
241
|
+
): Promise<{ tx: ContractTransaction; node: Node }> {
|
242
|
+
const inboxPosition = BigNumber.from(assertion.afterState.globalState.u64Vals[0]).toNumber();
|
243
|
+
const afterInboxAcc =
|
244
|
+
inboxPosition > 0 ? await sequencerInbox.inboxAccs(inboxPosition - 1) : constants.HashZero;
|
245
|
+
const newNodeHash = nodeHash(
|
246
|
+
!!siblingNode,
|
247
|
+
(siblingNode || parentNode).nodeHash,
|
248
|
+
assertionExecutionHash(assertion),
|
249
|
+
afterInboxAcc
|
250
|
+
);
|
251
|
+
const tx = await rollupAdmin.forceCreateNode(
|
252
|
+
parentNode.nodeNum,
|
253
|
+
parentNode.inboxMaxCount,
|
254
|
+
assertion,
|
255
|
+
newNodeHash
|
256
|
+
);
|
257
|
+
const node = await nodeFromTx(rollupAdmin.interface, tx);
|
258
|
+
return { tx, node };
|
259
|
+
}
|
@@ -0,0 +1,82 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2020, Offchain Labs, Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
/* eslint-env node, mocha */
|
18
|
+
|
19
|
+
import { ethers } from 'hardhat'
|
20
|
+
import { BytesLike } from '@ethersproject/bytes'
|
21
|
+
import { expect } from 'chai'
|
22
|
+
import { CryptographyPrimitivesTester } from '../../build/types'
|
23
|
+
|
24
|
+
let cryptographyPrimitivesTester: CryptographyPrimitivesTester
|
25
|
+
|
26
|
+
describe('CryptographyPrimitives', () => {
|
27
|
+
before(async () => {
|
28
|
+
const CryptographyPrimitivesTester = await ethers.getContractFactory(
|
29
|
+
'CryptographyPrimitivesTester'
|
30
|
+
)
|
31
|
+
cryptographyPrimitivesTester = (await CryptographyPrimitivesTester.deploy()) as CryptographyPrimitivesTester
|
32
|
+
await cryptographyPrimitivesTester.deployed()
|
33
|
+
})
|
34
|
+
|
35
|
+
it('calculates sha256 compression function correctly', async () => {
|
36
|
+
// test vectors from https://homes.esat.kuleuven.be/~nsmart/MPC/sha-256-test.txt
|
37
|
+
|
38
|
+
const initialHashState =
|
39
|
+
'0x6a09e667bb67ae853c6ef372a54ff53a510e527f9b05688c1f83d9ab5be0cd19'
|
40
|
+
|
41
|
+
const input1: [BytesLike, BytesLike] = [
|
42
|
+
ethers.constants.HashZero,
|
43
|
+
ethers.constants.HashZero,
|
44
|
+
]
|
45
|
+
|
46
|
+
const input2: [BytesLike, BytesLike] = [
|
47
|
+
'0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f',
|
48
|
+
'0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f',
|
49
|
+
]
|
50
|
+
|
51
|
+
const input3: [BytesLike, BytesLike] = [
|
52
|
+
'0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
|
53
|
+
'0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',
|
54
|
+
]
|
55
|
+
|
56
|
+
const input4: [BytesLike, BytesLike] = [
|
57
|
+
'0x243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89',
|
58
|
+
'0x452821E638D01377BE5466CF34E90C6CC0AC29B7C97C50DD3f84D5B5b5470917',
|
59
|
+
]
|
60
|
+
|
61
|
+
const output1 =
|
62
|
+
'0xda5698be17b9b46962335799779fbeca8ce5d491c0d26243bafef9ea1837a9d8'
|
63
|
+
const output2 =
|
64
|
+
'0xfc99a2df88f42a7a7bb9d18033cdc6a20256755f9d5b9a5044a9cc315abe84a7'
|
65
|
+
const output3 =
|
66
|
+
'0xef0c748df4da50a8d6c43c013edc3ce76c9d9fa9a1458ade56eb86c0a64492d2'
|
67
|
+
const output4 =
|
68
|
+
'0xcf0ae4eb67d38ffeb94068984b22abde4e92bc548d14585e48dca8882d7b09ce'
|
69
|
+
expect(
|
70
|
+
await cryptographyPrimitivesTester.sha256Block(input1, initialHashState)
|
71
|
+
).to.equal(output1)
|
72
|
+
expect(
|
73
|
+
await cryptographyPrimitivesTester.sha256Block(input2, initialHashState)
|
74
|
+
).to.equal(output2)
|
75
|
+
expect(
|
76
|
+
await cryptographyPrimitivesTester.sha256Block(input3, initialHashState)
|
77
|
+
).to.equal(output3)
|
78
|
+
expect(
|
79
|
+
await cryptographyPrimitivesTester.sha256Block(input4, initialHashState)
|
80
|
+
).to.equal(output4)
|
81
|
+
})
|
82
|
+
})
|