From 8efd35876a345773dd39a45b56db813d6b35b09f Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Wed, 8 Nov 2023 18:49:01 -0800 Subject: [PATCH 1/4] Adds processing of txns. --- contracts/Oracle.sol | 29 ++++++++++++++++++++-- contracts/PreConfirmations.sol | 13 ++++++++++ contracts/interfaces/IPreConfirmations.sol | 9 ++++--- test/OracleTest.sol | 6 ++--- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/contracts/Oracle.sol b/contracts/Oracle.sol index 92578ab..0682f97 100644 --- a/contracts/Oracle.sol +++ b/contracts/Oracle.sol @@ -14,6 +14,8 @@ import {IPreConfCommitmentStore} from './interfaces/IPreConfirmations.sol'; */ contract Oracle is Ownable { + mapping(string => address) public blockBuilderNameToAddress; + // To shutup the compiler // TODO(@ckartik): remove or make Oracle non-payable receive() external payable { @@ -39,13 +41,18 @@ contract Oracle is Ownable { preConfContract = IPreConfCommitmentStore(_preConfContract); } + // mapping of txns to bool to check if txns exists + // Stores all proccessed txns for onw + // TODO(@ckartik): This may be too restricvie in the log run as an appraoch + mapping(string => bool) txnHashes; + // Event to request block data event BlockDataRequested(uint256 blockNumber); // Event to signal the reception of block data event BlockDataReceived( - bytes32[] txnList, + string[] txnList, uint256 blockNumber, string blockBuilderName ); @@ -62,14 +69,32 @@ contract Oracle is Ownable { // Function to receive and process the block data (this would be automated in a real-world scenario) // TODO(@ckartik): Should restrict who can make this call function receiveBlockData( - bytes32[] calldata txnList, + string[] calldata txnList, uint256 blockNumber, string calldata blockBuilderName ) external { // Emit an event that the block data has been received emit BlockDataReceived(txnList, blockNumber, blockBuilderName); + address builder = blockBuilderNameToAddress[blockBuilderName]; + + for (uint256 i = 0; i < txnList.length; i++) { + txnHashes[txnList[i]] = true; + } + // Placeholder: Process the block data and determine the commitment's validity // For demonstration, we'll call this with a dummy commitment hash and isSlash flag + bytes32[] memory commitmentHashes = preConfContract.getCommitmentsByBlockNumber(blockNumber); + for (uint256 i = 0; i < commitmentHashes.length; i++) { + IPreConfCommitmentStore.PreConfCommitment memory commitment = preConfContract.getCommitment(commitmentHashes[i]); + if (commitment.commiter == builder) { + if (txnHashes[commitment.txnHash]){ + this.processCommitment(commitmentHashes[i], false); + } + else { + this.processCommitment(commitmentHashes[i], true); + } + } + } } // Function to simulate the processing of a commitment (initiate a slash or a reward) diff --git a/contracts/PreConfirmations.sol b/contracts/PreConfirmations.sol index aea3d20..e5a9598 100644 --- a/contracts/PreConfirmations.sol +++ b/contracts/PreConfirmations.sol @@ -349,6 +349,19 @@ contract PreConfCommitmentStore is Ownable { } + /** + * @dev Retrieves the list of commitments for a given block number. + * @param blockNumber The block number. + * @return A list of indexes referencing preconfimration structures for the specified block number. + */ + function getCommitmentsByBlockNumber(uint256 blockNumber) + public + view + returns (bytes32[] memory) + { + return blockCommitments[blockNumber]; + } + /** * @dev Get a commitment by its hash. * @param commitmentHash The hash of the commitment. diff --git a/contracts/interfaces/IPreConfirmations.sol b/contracts/interfaces/IPreConfirmations.sol index dbdd3f4..949a9c8 100644 --- a/contracts/interfaces/IPreConfirmations.sol +++ b/contracts/interfaces/IPreConfirmations.sol @@ -64,11 +64,14 @@ interface IPreConfCommitmentStore { bytes memory commitmentSignature ) external returns (uint256); - function getCommitment(bytes32 commitmentHash) external view returns (PreConfCommitment memory); + function getCommitmentsByBlockNumber(uint256 blockNumber) external view returns (bytes32[] memory); - function initiateSlash(bytes32 commitmentHash) external; - function initateReward(bytes32 commitmentHash) external; + function getCommitment(bytes32 commitmentIndex) external view returns (PreConfCommitment memory); + + function initiateSlash(bytes32 commitmentIndex) external; + + function initateReward(bytes32 commitmentIndex) external; function updateOracle(address newOracle) external; diff --git a/test/OracleTest.sol b/test/OracleTest.sol index 275ac6b..681dd69 100644 --- a/test/OracleTest.sol +++ b/test/OracleTest.sol @@ -23,7 +23,7 @@ contract OracleTest is Test { // Events to match against event BlockDataRequested(uint256 blockNumber); - event BlockDataReceived(bytes32[] txnList, uint256 blockNumber, string blockBuilderName); + event BlockDataReceived(string[] txnList, uint256 blockNumber, string blockBuilderName); event CommitmentProcessed(bytes32 commitmentHash, bool isSlash); function setUp() public { @@ -71,8 +71,8 @@ contract OracleTest is Test { } function test_ReceiveBlockData() public { - bytes32[] memory txnList = new bytes32[](1); - txnList[0] = keccak256("0xkartik"); + string[] memory txnList = new string[](1); + txnList[0] = string(abi.encodePacked(keccak256("0xkartik"))); uint256 blockNumber = block.number; string memory blockBuilderName = "mev builder"; vm.expectEmit(true, true, false, true); From b8c89ce6a6de61105a18350f11d1792a3ed93a5f Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Wed, 8 Nov 2023 20:43:14 -0800 Subject: [PATCH 2/4] Adds new builder to oracle internal name-address mapping. --- contracts/Oracle.sol | 4 ++++ test/OracleTest.sol | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/contracts/Oracle.sol b/contracts/Oracle.sol index 0682f97..6d5ed13 100644 --- a/contracts/Oracle.sol +++ b/contracts/Oracle.sol @@ -60,6 +60,10 @@ contract Oracle is Ownable { // Event to signal the processing of a commitment event CommitmentProcessed(bytes32 commitmentHash, bool isSlash); + function addBuilderAddress(string memory builderName, address builderAddress) external onlyOwner { + blockBuilderNameToAddress[builderName] = builderAddress; + } + // Function to request the block data function requestBlockData(uint256 blockNumber) external { // Emit an event that data request has been made diff --git a/test/OracleTest.sol b/test/OracleTest.sol index 681dd69..c0dbe92 100644 --- a/test/OracleTest.sol +++ b/test/OracleTest.sol @@ -49,10 +49,13 @@ contract OracleTest is Test { address signer = 0x6d503Fd50142C7C469C7c6B64794B55bfa6883f3; vm.deal(signer, 5 ether); - vm.prank(signer); + vm.startPrank(signer); userRegistry.registerAndStake{value: 2 ether}(); - + + // vm.prank(signer); oracle = new Oracle(address(preConfCommitmentStore)); + oracle.addBuilderAddress("mev builder", signer); + vm.stopPrank(); preConfCommitmentStore.updateOracle(address(oracle)); userRegistry.setPreconfirmationsContract(address(preConfCommitmentStore)); From 253c49dfe889d7dfbdd05e1abf9f984070f45d53 Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Thu, 9 Nov 2023 14:22:16 -0800 Subject: [PATCH 3/4] Adds url for aws-polygon rpc. --- hardhat.config.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hardhat.config.js b/hardhat.config.js index 6ebb520..bb03a13 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -9,10 +9,11 @@ module.exports = { localhost: { url: "http://127.0.0.1:8545", // Ganache default port }, - hardhat: {}, - op_docker: { - url: "http://op-geth:8545", - }, + aws: { + url: "http://34.213.237.94:8123", + chainId: 1001, + accounts: ['0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e'] //account private key + } }, docgen: { pages: "files", From d3a15f076170e7cd462f7cad70a2839f1083670a Mon Sep 17 00:00:00 2001 From: Kartik Chopra Date: Thu, 9 Nov 2023 16:15:46 -0800 Subject: [PATCH 4/4] Finishes testing of Oracle disbursing rewards for txn that was sent and commited to. --- contracts/PreConfirmations.sol | 14 ++--- contracts/UserRegistry.sol | 7 +++ contracts/interfaces/IPreConfirmations.sol | 4 +- test/OracleTest.sol | 72 +++++++++++++++++++++- test/PreConfirmationConfTest.sol | 29 +-------- 5 files changed, 89 insertions(+), 37 deletions(-) diff --git a/contracts/PreConfirmations.sol b/contracts/PreConfirmations.sol index e5a9598..5a62464 100644 --- a/contracts/PreConfirmations.sol +++ b/contracts/PreConfirmations.sol @@ -68,7 +68,7 @@ contract PreConfCommitmentStore is Ownable { uint64 blockNumber; bytes32 bidHash; string txnHash; - string commitmentHash; + bytes32 commitmentHash; bytes bidSignature; bytes commitmentSignature; } @@ -272,7 +272,6 @@ contract PreConfCommitmentStore is Ownable { * @param bid The bid amount. * @param blockNumber The block number. * @param txnHash The transaction hash. - * @param commitmentHash The commitment hash. * @param bidSignature The signature of the bid. * @param commitmentSignature The signature of the commitment. * @return commitmentIndex The index of the stored commitment @@ -281,7 +280,6 @@ contract PreConfCommitmentStore is Ownable { uint64 bid, uint64 blockNumber, string memory txnHash, - string memory commitmentHash, bytes calldata bidSignature, bytes memory commitmentSignature ) public returns (bytes32 commitmentIndex) { @@ -313,7 +311,7 @@ contract PreConfCommitmentStore is Ownable { blockNumber, bHash, txnHash, - commitmentHash, + preConfHash, bidSignature, commitmentSignature ); @@ -363,14 +361,14 @@ contract PreConfCommitmentStore is Ownable { } /** - * @dev Get a commitment by its hash. - * @param commitmentHash The hash of the commitment. + * @dev Get a commitment by its commitmentIndex. + * @param commitmentIndex The index of the commitment. * @return A PreConfCommitment structure representing the commitment. */ function getCommitment( - bytes32 commitmentHash + bytes32 commitmentIndex ) public view returns (PreConfCommitment memory) { - return commitments[commitmentHash]; + return commitments[commitmentIndex]; } /** diff --git a/contracts/UserRegistry.sol b/contracts/UserRegistry.sol index 71b4fe5..d107c42 100644 --- a/contracts/UserRegistry.sol +++ b/contracts/UserRegistry.sol @@ -102,6 +102,13 @@ contract UserRegistry is IUserRegistry, Ownable, ReentrancyGuard { preConfirmationsContract = contractAddress; } + /** + * @dev Get the amount assigned to a provider. + */ + function getProviderAmount(address provider) external view returns (uint256) { + return providerAmount[provider]; + } + /** * @dev Internal function for user registration and staking. */ diff --git a/contracts/interfaces/IPreConfirmations.sol b/contracts/interfaces/IPreConfirmations.sol index 949a9c8..6cc442e 100644 --- a/contracts/interfaces/IPreConfirmations.sol +++ b/contracts/interfaces/IPreConfirmations.sol @@ -8,6 +8,7 @@ pragma solidity ^0.8.20; interface IPreConfCommitmentStore { // Structs, events, and errors can also be included in the interface if they are used in the external functions + /// @dev Struct for all the information around preconfirmations commitment struct PreConfCommitment { bool commitmentUsed; address bidder; @@ -16,11 +17,12 @@ interface IPreConfCommitmentStore { uint64 blockNumber; bytes32 bidHash; string txnHash; - string commitmentHash; + bytes32 commitmentHash; bytes bidSignature; bytes commitmentSignature; } + event SignatureVerified( address indexed signer, string txnHash, diff --git a/test/OracleTest.sol b/test/OracleTest.sol index c0dbe92..664a75d 100644 --- a/test/OracleTest.sol +++ b/test/OracleTest.sol @@ -9,6 +9,7 @@ import "../contracts/ProviderRegistry.sol"; import "../contracts/UserRegistry.sol"; contract OracleTest is Test { + using ECDSA for bytes32; Oracle internal oracle; PreConfCommitmentStore internal preConfCommitmentStore; uint16 internal feePercent; @@ -83,6 +84,75 @@ contract OracleTest is Test { oracle.receiveBlockData(txnList, blockNumber, blockBuilderName); } + /** + constructAndStoreCommitment is a helper function to construct and store a commitment + */ + function constructAndStoreCommitment( + uint64 bid, + uint64 blockNumber, + string memory txnHash, + uint256 bidderPk, + uint256 signerPk + ) public returns (bytes32 commitmentIndex) { + bytes32 bidHash = preConfCommitmentStore.getBidHash( + txnHash, + bid, + blockNumber + ); + + + (uint8 v,bytes32 r, bytes32 s) = vm.sign(bidderPk, bidHash); + bytes memory bidSignature = abi.encodePacked(r, s, v); + + bytes32 commitmentHash = preConfCommitmentStore.getPreConfHash( + txnHash, + bid, + blockNumber, + bidHash, + _bytesToHexString(bidSignature) + ); + + (v,r,s) = vm.sign(signerPk, commitmentHash); + bytes memory commitmentSignature = abi.encodePacked(r, s, v); + + commitmentIndex = preConfCommitmentStore.storeCommitment( + bid, + blockNumber, + txnHash, + bidSignature, + commitmentSignature + ); + + return commitmentIndex; + } + + function test_ReceiveBlockDataWithCommitments() public { + string[] memory txnList = new string[](1); + txnList[0] = string(abi.encodePacked(keccak256("0xkartik"))); + uint64 blockNumber = 200; + uint64 bid = 2; + string memory blockBuilderName = "kartik builder"; + (address user, uint256 userPk) = makeAddrAndKey("alice"); + + vm.deal(user, 200000 ether); + vm.startPrank(user); + userRegistry.registerAndStake{value: 250 ether }(); + providerRegistry.registerAndStake{value: 250 ether}(); + vm.stopPrank(); + + bytes32 commitmentIndex = constructAndStoreCommitment(bid, blockNumber, txnList[0], userPk, userPk); + vm.prank(address(0x6d503Fd50142C7C469C7c6B64794B55bfa6883f3)); + oracle.addBuilderAddress("kartik builder", user); + vm.expectEmit(true, true, false, true); + emit BlockDataReceived(txnList, blockNumber, blockBuilderName); + oracle.receiveBlockData(txnList, blockNumber, blockBuilderName); + + bytes32[] memory commitmentHashes = preConfCommitmentStore.getCommitmentsByBlockNumber(blockNumber); + assertEq(commitmentHashes.length, 1); + assertEq(userRegistry.getProviderAmount(user), bid); + + } + // function test_ProcessCommitment_Slash() public { // TODO(@ckartik): Add test // } @@ -101,7 +171,7 @@ contract OracleTest is Test { ); bytes memory commitmentSignature = hex"ff7e00cf5c2d0fa9ef7c5efdca68b285a664a3aab927eb779b464207f537551f4ff81b085acf78b58ecb8c96c9a4efcb2172a0287f5bf5819b49190f6e2d2d1e1b"; - bytes32 commitmentIndex = preConfCommitmentStore.storeCommitment(bid, blockNumber, txnHash, cHash, bidSignature, commitmentSignature); + bytes32 commitmentIndex = preConfCommitmentStore.storeCommitment(bid, blockNumber, txnHash, bidSignature, commitmentSignature); bytes32 bidHash = preConfCommitmentStore.getBidHash( txnHash, diff --git a/test/PreConfirmationConfTest.sol b/test/PreConfirmationConfTest.sol index 81782d4..6eef26d 100644 --- a/test/PreConfirmationConfTest.sol +++ b/test/PreConfirmationConfTest.sol @@ -73,7 +73,7 @@ contract TestPreConfCommitmentStore is Test { assertEq(user, recoveredAddress); assertEq(digest, bidHash); - preConfCommitmentStore.storeCommitment(200 wei, 3000, "0xkartik", "0xkartik", signature, signature); + preConfCommitmentStore.storeCommitment(200 wei, 3000, "0xkartik", signature, signature); } @@ -144,8 +144,7 @@ contract TestPreConfCommitmentStore is Test { vm.prank(signer); userRegistry.registerAndStake{value: 2 ether}(); string memory txnHash = "0xkartik"; - string - memory commitmentHash = "0x31dca6c6fd15593559dabb9e25285f727fd33f07e17ec2e8da266706020034dc"; + bytes32 commitmentHash = bytes32(hex"31dca6c6fd15593559dabb9e25285f727fd33f07e17ec2e8da266706020034dc"); bytes memory signature = "0xb170d082db1bf77fa0b589b9438444010dcb1e6dd326b661b02eb92abe4c066e243bb0d214b01667750ba2c53ff1ab445fd784b441dbc1f30280c379f002cc571c"; uint64 bid = 2; @@ -164,7 +163,6 @@ contract TestPreConfCommitmentStore is Test { bid, blockNumber, txnHash, - commitmentHash, bidSignature, commitmentSignature ); @@ -175,7 +173,6 @@ contract TestPreConfCommitmentStore is Test { bid, blockNumber, txnHash, - commitmentHash, bidSignature, commitmentSignature ); @@ -211,7 +208,6 @@ contract TestPreConfCommitmentStore is Test { uint64 bid, uint64 blockNumber, string memory txnHash, - string memory commitmentHash, bytes memory bidSignature, bytes memory commitmentSignature ) internal returns (bytes32) { @@ -219,7 +215,6 @@ contract TestPreConfCommitmentStore is Test { bid, blockNumber, txnHash, - commitmentHash, bidSignature, commitmentSignature ); @@ -232,17 +227,10 @@ contract TestPreConfCommitmentStore is Test { uint64 bid, uint64 blockNumber, string memory txnHash, - string memory commitmentHash, bytes memory bidSignature, bytes memory commitmentSignature ) public { - bytes32 reconstructedIndex = keccak256( - abi.encodePacked( - commitmentHash, - commitmentSignature - ) - ); (PreConfCommitmentStore.PreConfCommitment memory commitment) = preConfCommitmentStore .getCommitment(index); @@ -260,11 +248,6 @@ contract TestPreConfCommitmentStore is Test { assert(commitments.length >= 1); - assertEq( - index, - reconstructedIndex, - "Returned hash should match the preConfHash" - ); assertEq( commitment.commitmentUsed, false, @@ -281,11 +264,6 @@ contract TestPreConfCommitmentStore is Test { txnHash, "Stored txnHash should match input txnHash" ); - assertEq( - commitment.commitmentHash, - commitmentHash, - "Stored commitmentHash should match input commitmentHash" - ); assertEq( commitment.bidSignature, bidSignature, @@ -324,7 +302,6 @@ contract TestPreConfCommitmentStore is Test { bid, blockNumber, txnHash, - commitmentHash, bidSignature, commitmentSignature ); @@ -383,7 +360,6 @@ contract TestPreConfCommitmentStore is Test { bid, blockNumber, txnHash, - commitmentHash, bidSignature, commitmentSignature ); @@ -449,7 +425,6 @@ contract TestPreConfCommitmentStore is Test { bid, blockNumber, txnHash, - commitmentHash, bidSignature, commitmentSignature );