From ee687ba1cad384dfecc5f5a542bd916d9e191b84 Mon Sep 17 00:00:00 2001 From: shotaronowhere Date: Mon, 27 Jun 2022 11:14:45 +0100 Subject: [PATCH 1/5] feat(bridge): sender subgraph --- subgraph-fastbridge/fastbridge/README.md | 3 + .../fastbridge/abis/FastBridgeSender.json | 235 ++++++++++++++++++ subgraph-fastbridge/fastbridge/package.json | 16 ++ subgraph-fastbridge/fastbridge/schema.graphql | 35 +++ .../fastbridge/src/FastBridgeSender.ts | 149 +++++++++++ subgraph-fastbridge/fastbridge/subgraph.yaml | 32 +++ subgraph-fastbridge/fastbridge/tsconfig.json | 6 + 7 files changed, 476 insertions(+) create mode 100644 subgraph-fastbridge/fastbridge/README.md create mode 100644 subgraph-fastbridge/fastbridge/abis/FastBridgeSender.json create mode 100644 subgraph-fastbridge/fastbridge/package.json create mode 100644 subgraph-fastbridge/fastbridge/schema.graphql create mode 100644 subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts create mode 100644 subgraph-fastbridge/fastbridge/subgraph.yaml create mode 100644 subgraph-fastbridge/fastbridge/tsconfig.json diff --git a/subgraph-fastbridge/fastbridge/README.md b/subgraph-fastbridge/fastbridge/README.md new file mode 100644 index 000000000..ce49744df --- /dev/null +++ b/subgraph-fastbridge/fastbridge/README.md @@ -0,0 +1,3 @@ +# @kleros/kleros-v2-fastbridge + +🚧 ⚖️ 🚧 diff --git a/subgraph-fastbridge/fastbridge/abis/FastBridgeSender.json b/subgraph-fastbridge/fastbridge/abis/FastBridgeSender.json new file mode 100644 index 000000000..e75077ce9 --- /dev/null +++ b/subgraph-fastbridge/fastbridge/abis/FastBridgeSender.json @@ -0,0 +1,235 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "FastBridgeSender", + "sourceName": "src/bridge/FastBridgeSender.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochPeriod", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_safeBridgeReceiver", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "fastMessage", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "fastMessageHash", + "type": "bytes32" + } + ], + "name": "MessageReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "batchID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "batchSize", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "batchMerkleRoot", + "type": "bytes32" + } + ], + "name": "SendBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "canonicalBridgeMessageID", + "type": "bytes32" + } + ], + "name": "SentSafe", + "type": "event" + }, + { + "inputs": [], + "name": "ARB_SYS", + "outputs": [ + { + "internalType": "contract IArbSys", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "batch", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentBatchID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "fastOutbox", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "safeBridgeReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sendBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "sendFast", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "sendSafeFallback", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/subgraph-fastbridge/fastbridge/package.json b/subgraph-fastbridge/fastbridge/package.json new file mode 100644 index 000000000..057f1e4bc --- /dev/null +++ b/subgraph-fastbridge/fastbridge/package.json @@ -0,0 +1,16 @@ +{ + "name": "@kleros/kleros-v2-fastbridge", + "license": "MIT", + "scripts": { + "codegen": "graph codegen", + "build": "graph build", + "deploy": "graph deploy --node https://api.thegraph.com/deploy/ fastbridge", + "create-local": "graph create --node http://localhost:8020/ fastbridge", + "remove-local": "graph remove --node http://localhost:8020/ fastbridge", + "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 fastbridge" + }, + "dependencies": { + "@graphprotocol/graph-cli": "^0.30.3", + "@graphprotocol/graph-ts": "^0.27.0" + } +} diff --git a/subgraph-fastbridge/fastbridge/schema.graphql b/subgraph-fastbridge/fastbridge/schema.graphql new file mode 100644 index 000000000..1d3e1f764 --- /dev/null +++ b/subgraph-fastbridge/fastbridge/schema.graphql @@ -0,0 +1,35 @@ +type FastMessage @entity(immutable: true) { + id: ID! + batchID: BigInt! + nonce: BigInt! + message: Bytes! + receiver: Receiver! + sender: Sender! + hash: Bytes! +} + +type Proof @entity(immutable: true) { + id: ID! + batchID: BigInt! + nonce: BigInt! + data: Bytes! + fastMessage: FastMessage! +} + +type Receiver @entity(immutable: true) { + id: ID! + fastMessages: [FastMessage!]! @derivedFrom(field: "receiver") +} + +type Sender @entity(immutable: true) { + id: ID! + fastMessages: [FastMessage!]! @derivedFrom(field: "sender") +} + +type Batch @entity { + id: ID! + epochFinal: BigInt! + batchSize: BigInt! + merkleRoot: Bytes + sentSafe: Boolean +} \ No newline at end of file diff --git a/subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts b/subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts new file mode 100644 index 000000000..76ebbd082 --- /dev/null +++ b/subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts @@ -0,0 +1,149 @@ +import { Bytes, ByteArray, BigInt, crypto} from "@graphprotocol/graph-ts" + +import { + FastBridgeSender, + MessageReceived, + SendBatch, + SentSafe +} from "../generated/FastBridgeSender/FastBridgeSender" +import { FastMessage, Sender, Batch, Proof, Receiver } from "../generated/schema" + +export function handleSentSafe(event: SentSafe): void { + const batch = Batch.load(event.params.epoch.toString()) + if (batch){ + batch.sentSafe = true + event.params.canonicalBridgeMessageID + } + +} + +export function handleMessageReceived(event: MessageReceived): void { + const contract = FastBridgeSender.bind(event.address) + + const batchID = contract.currentBatchID() + const leafHash = event.params.fastMessageHash + const message = event.params.fastMessage + const nonce = BigInt.fromByteArray(firstSlotReverse(message)) + + const fastMessage = new FastMessage(batchID.toString()+","+nonce.toString()) + + fastMessage.message = message + fastMessage.hash = leafHash + fastMessage.batchID = batchID + fastMessage.nonce = nonce + + const receiverAddress = getAddress(message,44).toHexString() + const senderAddress = getAddress(message,144).toHexString() + + const receiver = new Receiver(receiverAddress) + receiver.save() + + const sender = new Sender(senderAddress) + sender.save() + + fastMessage.receiver = receiverAddress + fastMessage.sender = senderAddress + fastMessage.save(); +} + +export function handleSendBatch(event: SendBatch): void { + const layers: ByteArray[][] = [] + const layerZero: ByteArray[] = [] + + const epochInitial = event.params.batchID + const epochFinal = event.params.epoch + const batchSize = event.params.batchSize + const currentBatchID = event.params.batchID + + let batch = new Batch(currentBatchID.toString()) + + batch.epochFinal = epochFinal + batch.batchSize = batchSize + + let count = 0 + const _epochFinal = epochFinal.toU32() + + for (let i = epochInitial.toU32(); i<=_epochFinal; i++){ + let fastMessage = FastMessage.load(i.toString()+","+count.toString()); + while (fastMessage != null){ + layerZero.push(fastMessage.hash) + count++; + fastMessage = FastMessage.load(i.toString()+","+count.toString()); + } + } +layers.push(layerZero) + // Get next layer until we reach the root + while (layers[layers.length - 1].length > 1) { + layers.push(getNextLayer(layers[layers.length - 1])) + } + + // PROOF + for(let idx = 0; idx < layerZero.length; idx++){ + let proof: ByteArray[] = [] + let _proof = new Proof(currentBatchID.toString()+","+idx.toString()); + let _idx = idx + for (let i = 0; i < layers.length ; i++){ + const pairIdx = idx % 2 === 0 ? idx + 1 : idx - 1; + if (pairIdx < layers[i].length) { + proof.push(layers[i][pairIdx]); + } + _idx /= 2; + } + _proof.data = Bytes.fromByteArray(Flatten(proof)) + _proof.fastMessage = currentBatchID.toString()+","+idx.toString() + _proof.batchID = currentBatchID + _proof.nonce = BigInt.fromU32(idx) + _proof.save() + } + batch.merkleRoot = event.params.batchMerkleRoot + batch.sentSafe = false + batch.save() +} + +function Flatten(a: ByteArray[]): ByteArray { + let out = new ByteArray(32*a.length); + for (let i = 0; i < a.length; i++) out.set(a[i],i*32) + return out; +} + +function getNextLayer(elements: ByteArray[]): ByteArray[] { + return elements.reduce((layer, el, idx, arr) => { + if (idx % 2 === 0) { + // Hash the current element with its pair element + if (idx == arr.length - 1){ + layer.push(el); + } else { + layer.push(crypto.keccak256(concatAndSortByteArrays(el, arr[idx + 1]))); + } + } + + return layer; + }, [] as ByteArray[]); +} + + +function firstSlotReverse(a: ByteArray): ByteArray { + let out = new ByteArray(32); + for (let i = 0; i < 32; i++) out[i] = a[31-i]; + return out; +} + +function getAddress(input: ByteArray, offset: i32): ByteArray { + let out = new ByteArray(20); + for (let i = 0; i < 20; i++) out[i] = input[i+offset]; + return out; +} + +function concatAndSortByteArrays(a: ByteArray, b: ByteArray): ByteArray { + let out: ByteArray + for (let i = 0; i < 32; i++){ + if (a[i] > b[i]){ + out = b.concat(a) + return out; + } else if (b[i] < a[i]){ + out = a.concat(b) + return out; + } + } + return a +} \ No newline at end of file diff --git a/subgraph-fastbridge/fastbridge/subgraph.yaml b/subgraph-fastbridge/fastbridge/subgraph.yaml new file mode 100644 index 000000000..34461c84f --- /dev/null +++ b/subgraph-fastbridge/fastbridge/subgraph.yaml @@ -0,0 +1,32 @@ +specVersion: 0.0.4 +schema: + file: ./schema.graphql +dataSources: + - kind: ethereum + name: FastBridgeSender + network: arbitrum-rinkeby + source: + address: "0x1077D69D660c08fB5a1996D4805D9e657f7BA39e" + abi: FastBridgeSender + startBlock: 12545049 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + entities: + - FastMessage + - Proof + - Sender + - Receiver + - Batch + abis: + - name: FastBridgeSender + file: ./abis/FastBridgeSender.json + eventHandlers: + - event: SentSafe(indexed uint256,bytes32) + handler: handleSentSafe + - event: MessageReceived(bytes,bytes32) + handler: handleMessageReceived + - event: SendBatch(indexed uint256,uint256,uint256,bytes32) + handler: handleSendBatch + file: ./src/FastBridgeSender.ts diff --git a/subgraph-fastbridge/fastbridge/tsconfig.json b/subgraph-fastbridge/fastbridge/tsconfig.json new file mode 100644 index 000000000..61e440c6e --- /dev/null +++ b/subgraph-fastbridge/fastbridge/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@graphprotocol/graph-ts/types/tsconfig.base.json", + "include": [ + "src" + ] +} From 69e431f2f5287a60bca0b6ac2aeacd4e163c87cc Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Tue, 2 Aug 2022 14:13:23 +0100 Subject: [PATCH 2/5] refactor: subfolder removed --- package.json | 1 + subgraph-fastbridge/.eslintrc.json | 10 ++ subgraph-fastbridge/.prettierrc | 3 + subgraph-fastbridge/README.md | 3 + .../abis/FastBridgeSender.json | 0 subgraph-fastbridge/fastbridge/README.md | 3 - .../fastbridge/src/FastBridgeSender.ts | 149 ----------------- .../{fastbridge => }/package.json | 4 +- .../{fastbridge => }/schema.graphql | 0 subgraph-fastbridge/src/FastBridgeSender.ts | 155 ++++++++++++++++++ .../{fastbridge => }/subgraph.yaml | 0 .../{fastbridge => }/tsconfig.json | 4 +- yarn.lock | 9 + 13 files changed, 184 insertions(+), 157 deletions(-) create mode 100644 subgraph-fastbridge/.eslintrc.json create mode 100644 subgraph-fastbridge/.prettierrc create mode 100644 subgraph-fastbridge/README.md rename subgraph-fastbridge/{fastbridge => }/abis/FastBridgeSender.json (100%) delete mode 100644 subgraph-fastbridge/fastbridge/README.md delete mode 100644 subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts rename subgraph-fastbridge/{fastbridge => }/package.json (84%) rename subgraph-fastbridge/{fastbridge => }/schema.graphql (100%) create mode 100644 subgraph-fastbridge/src/FastBridgeSender.ts rename subgraph-fastbridge/{fastbridge => }/subgraph.yaml (100%) rename subgraph-fastbridge/{fastbridge => }/tsconfig.json (70%) diff --git a/package.json b/package.json index 70734b25a..40a49620c 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "evidence-display", "klerosjs", "subgraph", + "subgraph-fastbridge", "web" ], "packageManager": "yarn@3.1.1", diff --git a/subgraph-fastbridge/.eslintrc.json b/subgraph-fastbridge/.eslintrc.json new file mode 100644 index 000000000..8256ebd88 --- /dev/null +++ b/subgraph-fastbridge/.eslintrc.json @@ -0,0 +1,10 @@ +{ + "root": true, + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "extends": [ + "plugin:@typescript-eslint/recommended", + "prettier", + "prettier/@typescript-eslint" + ] +} diff --git a/subgraph-fastbridge/.prettierrc b/subgraph-fastbridge/.prettierrc new file mode 100644 index 000000000..9d4892be8 --- /dev/null +++ b/subgraph-fastbridge/.prettierrc @@ -0,0 +1,3 @@ +{ + "printWidth": 80 +} diff --git a/subgraph-fastbridge/README.md b/subgraph-fastbridge/README.md new file mode 100644 index 000000000..dfb6faf8e --- /dev/null +++ b/subgraph-fastbridge/README.md @@ -0,0 +1,3 @@ +# @kleros/kleros-v2-subgraph-fastbridge + +🚧 ⚖️ 🚧 diff --git a/subgraph-fastbridge/fastbridge/abis/FastBridgeSender.json b/subgraph-fastbridge/abis/FastBridgeSender.json similarity index 100% rename from subgraph-fastbridge/fastbridge/abis/FastBridgeSender.json rename to subgraph-fastbridge/abis/FastBridgeSender.json diff --git a/subgraph-fastbridge/fastbridge/README.md b/subgraph-fastbridge/fastbridge/README.md deleted file mode 100644 index ce49744df..000000000 --- a/subgraph-fastbridge/fastbridge/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# @kleros/kleros-v2-fastbridge - -🚧 ⚖️ 🚧 diff --git a/subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts b/subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts deleted file mode 100644 index 76ebbd082..000000000 --- a/subgraph-fastbridge/fastbridge/src/FastBridgeSender.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { Bytes, ByteArray, BigInt, crypto} from "@graphprotocol/graph-ts" - -import { - FastBridgeSender, - MessageReceived, - SendBatch, - SentSafe -} from "../generated/FastBridgeSender/FastBridgeSender" -import { FastMessage, Sender, Batch, Proof, Receiver } from "../generated/schema" - -export function handleSentSafe(event: SentSafe): void { - const batch = Batch.load(event.params.epoch.toString()) - if (batch){ - batch.sentSafe = true - event.params.canonicalBridgeMessageID - } - -} - -export function handleMessageReceived(event: MessageReceived): void { - const contract = FastBridgeSender.bind(event.address) - - const batchID = contract.currentBatchID() - const leafHash = event.params.fastMessageHash - const message = event.params.fastMessage - const nonce = BigInt.fromByteArray(firstSlotReverse(message)) - - const fastMessage = new FastMessage(batchID.toString()+","+nonce.toString()) - - fastMessage.message = message - fastMessage.hash = leafHash - fastMessage.batchID = batchID - fastMessage.nonce = nonce - - const receiverAddress = getAddress(message,44).toHexString() - const senderAddress = getAddress(message,144).toHexString() - - const receiver = new Receiver(receiverAddress) - receiver.save() - - const sender = new Sender(senderAddress) - sender.save() - - fastMessage.receiver = receiverAddress - fastMessage.sender = senderAddress - fastMessage.save(); -} - -export function handleSendBatch(event: SendBatch): void { - const layers: ByteArray[][] = [] - const layerZero: ByteArray[] = [] - - const epochInitial = event.params.batchID - const epochFinal = event.params.epoch - const batchSize = event.params.batchSize - const currentBatchID = event.params.batchID - - let batch = new Batch(currentBatchID.toString()) - - batch.epochFinal = epochFinal - batch.batchSize = batchSize - - let count = 0 - const _epochFinal = epochFinal.toU32() - - for (let i = epochInitial.toU32(); i<=_epochFinal; i++){ - let fastMessage = FastMessage.load(i.toString()+","+count.toString()); - while (fastMessage != null){ - layerZero.push(fastMessage.hash) - count++; - fastMessage = FastMessage.load(i.toString()+","+count.toString()); - } - } -layers.push(layerZero) - // Get next layer until we reach the root - while (layers[layers.length - 1].length > 1) { - layers.push(getNextLayer(layers[layers.length - 1])) - } - - // PROOF - for(let idx = 0; idx < layerZero.length; idx++){ - let proof: ByteArray[] = [] - let _proof = new Proof(currentBatchID.toString()+","+idx.toString()); - let _idx = idx - for (let i = 0; i < layers.length ; i++){ - const pairIdx = idx % 2 === 0 ? idx + 1 : idx - 1; - if (pairIdx < layers[i].length) { - proof.push(layers[i][pairIdx]); - } - _idx /= 2; - } - _proof.data = Bytes.fromByteArray(Flatten(proof)) - _proof.fastMessage = currentBatchID.toString()+","+idx.toString() - _proof.batchID = currentBatchID - _proof.nonce = BigInt.fromU32(idx) - _proof.save() - } - batch.merkleRoot = event.params.batchMerkleRoot - batch.sentSafe = false - batch.save() -} - -function Flatten(a: ByteArray[]): ByteArray { - let out = new ByteArray(32*a.length); - for (let i = 0; i < a.length; i++) out.set(a[i],i*32) - return out; -} - -function getNextLayer(elements: ByteArray[]): ByteArray[] { - return elements.reduce((layer, el, idx, arr) => { - if (idx % 2 === 0) { - // Hash the current element with its pair element - if (idx == arr.length - 1){ - layer.push(el); - } else { - layer.push(crypto.keccak256(concatAndSortByteArrays(el, arr[idx + 1]))); - } - } - - return layer; - }, [] as ByteArray[]); -} - - -function firstSlotReverse(a: ByteArray): ByteArray { - let out = new ByteArray(32); - for (let i = 0; i < 32; i++) out[i] = a[31-i]; - return out; -} - -function getAddress(input: ByteArray, offset: i32): ByteArray { - let out = new ByteArray(20); - for (let i = 0; i < 20; i++) out[i] = input[i+offset]; - return out; -} - -function concatAndSortByteArrays(a: ByteArray, b: ByteArray): ByteArray { - let out: ByteArray - for (let i = 0; i < 32; i++){ - if (a[i] > b[i]){ - out = b.concat(a) - return out; - } else if (b[i] < a[i]){ - out = a.concat(b) - return out; - } - } - return a -} \ No newline at end of file diff --git a/subgraph-fastbridge/fastbridge/package.json b/subgraph-fastbridge/package.json similarity index 84% rename from subgraph-fastbridge/fastbridge/package.json rename to subgraph-fastbridge/package.json index 057f1e4bc..013414092 100644 --- a/subgraph-fastbridge/fastbridge/package.json +++ b/subgraph-fastbridge/package.json @@ -1,5 +1,5 @@ { - "name": "@kleros/kleros-v2-fastbridge", + "name": "@kleros/kleros-v2-subgraph-fastbridge", "license": "MIT", "scripts": { "codegen": "graph codegen", @@ -10,7 +10,7 @@ "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 fastbridge" }, "dependencies": { - "@graphprotocol/graph-cli": "^0.30.3", + "@graphprotocol/graph-cli": "^0.33.0", "@graphprotocol/graph-ts": "^0.27.0" } } diff --git a/subgraph-fastbridge/fastbridge/schema.graphql b/subgraph-fastbridge/schema.graphql similarity index 100% rename from subgraph-fastbridge/fastbridge/schema.graphql rename to subgraph-fastbridge/schema.graphql diff --git a/subgraph-fastbridge/src/FastBridgeSender.ts b/subgraph-fastbridge/src/FastBridgeSender.ts new file mode 100644 index 000000000..d9b367897 --- /dev/null +++ b/subgraph-fastbridge/src/FastBridgeSender.ts @@ -0,0 +1,155 @@ +import { Bytes, ByteArray, BigInt, crypto } from "@graphprotocol/graph-ts"; + +import { + FastBridgeSender, + MessageReceived, + SendBatch, + SentSafe, +} from "../generated/FastBridgeSender/FastBridgeSender"; +import { + FastMessage, + Sender, + Batch, + Proof, + Receiver, +} from "../generated/schema"; + +export function handleSentSafe(event: SentSafe): void { + const batch = Batch.load(event.params.epoch.toString()); + if (batch) { + batch.sentSafe = true; + event.params.canonicalBridgeMessageID; + } +} + +export function handleMessageReceived(event: MessageReceived): void { + const contract = FastBridgeSender.bind(event.address); + + const batchID = contract.currentBatchID(); + const leafHash = event.params.fastMessageHash; + const message = event.params.fastMessage; + const nonce = BigInt.fromByteArray(firstSlotReverse(message)); + + const fastMessage = new FastMessage( + batchID.toString() + "," + nonce.toString() + ); + + fastMessage.message = message; + fastMessage.hash = leafHash; + fastMessage.batchID = batchID; + fastMessage.nonce = nonce; + + const receiverAddress = getAddress(message, 44).toHexString(); + const senderAddress = getAddress(message, 144).toHexString(); + + const receiver = new Receiver(receiverAddress); + receiver.save(); + + const sender = new Sender(senderAddress); + sender.save(); + + fastMessage.receiver = receiverAddress; + fastMessage.sender = senderAddress; + fastMessage.save(); +} + +export function handleSendBatch(event: SendBatch): void { + const layers: ByteArray[][] = []; + const layerZero: ByteArray[] = []; + + const epochInitial = event.params.batchID; + const epochFinal = event.params.epoch; + const batchSize = event.params.batchSize; + const currentBatchID = event.params.batchID; + + let batch = new Batch(currentBatchID.toString()); + + batch.epochFinal = epochFinal; + batch.batchSize = batchSize; + + let count = 0; + const _epochFinal = epochFinal.toU32(); + + for (let i = epochInitial.toU32(); i <= _epochFinal; i++) { + let fastMessage = FastMessage.load(i.toString() + "," + count.toString()); + while (fastMessage != null) { + layerZero.push(fastMessage.hash); + count++; + fastMessage = FastMessage.load(i.toString() + "," + count.toString()); + } + } + layers.push(layerZero); + // Get next layer until we reach the root + while (layers[layers.length - 1].length > 1) { + layers.push(getNextLayer(layers[layers.length - 1])); + } + + // PROOF + for (let idx = 0; idx < layerZero.length; idx++) { + let proof: ByteArray[] = []; + let _proof = new Proof(currentBatchID.toString() + "," + idx.toString()); + let _idx = idx; + for (let i = 0; i < layers.length; i++) { + const pairIdx = idx % 2 === 0 ? idx + 1 : idx - 1; + if (pairIdx < layers[i].length) { + proof.push(layers[i][pairIdx]); + } + _idx /= 2; + } + _proof.data = Bytes.fromByteArray(Flatten(proof)); + _proof.fastMessage = currentBatchID.toString() + "," + idx.toString(); + _proof.batchID = currentBatchID; + _proof.nonce = BigInt.fromU32(idx); + _proof.save(); + } + batch.merkleRoot = event.params.batchMerkleRoot; + batch.sentSafe = false; + batch.save(); +} + +function Flatten(a: ByteArray[]): ByteArray { + let out = new ByteArray(32 * a.length); + for (let i = 0; i < a.length; i++) out.set(a[i], i * 32); + return out; +} + +function getNextLayer(elements: ByteArray[]): ByteArray[] { + return elements.reduce((layer, el, idx, arr) => { + if (idx % 2 === 0) { + // Hash the current element with its pair element + if (idx == arr.length - 1) { + layer.push(el); + } else { + layer.push(crypto.keccak256(concatAndSortByteArrays(el, arr[idx + 1]))); + } + } + + return layer; + }, [] as ByteArray[]); +} + +function firstSlotReverse(a: ByteArray): ByteArray { + let out = new ByteArray(32); + for (let i = 0; i < 32; i++) out[i] = a[31 - i]; + return out; +} + +function getAddress(input: ByteArray, offset: i32): ByteArray { + let out = new ByteArray(20); + for (let i = 0; i < 20; i++) out[i] = input[i + offset]; + return out; +} + +function concatAndSortByteArrays(a: ByteArray, b: ByteArray): ByteArray { + let out: ByteArray; + for (let i = 0; i < 32; i++) { + if (a[i] > b[i]) { + out = b.concat(a); + return out; + } else if (b[i] < a[i]) { + out = a.concat(b); + return out; + } + } + return a; +} diff --git a/subgraph-fastbridge/fastbridge/subgraph.yaml b/subgraph-fastbridge/subgraph.yaml similarity index 100% rename from subgraph-fastbridge/fastbridge/subgraph.yaml rename to subgraph-fastbridge/subgraph.yaml diff --git a/subgraph-fastbridge/fastbridge/tsconfig.json b/subgraph-fastbridge/tsconfig.json similarity index 70% rename from subgraph-fastbridge/fastbridge/tsconfig.json rename to subgraph-fastbridge/tsconfig.json index 61e440c6e..5c5d17c92 100644 --- a/subgraph-fastbridge/fastbridge/tsconfig.json +++ b/subgraph-fastbridge/tsconfig.json @@ -1,6 +1,4 @@ { "extends": "@graphprotocol/graph-ts/types/tsconfig.base.json", - "include": [ - "src" - ] + "include": ["src"] } diff --git a/yarn.lock b/yarn.lock index a0a194809..07b4dd297 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2429,6 +2429,15 @@ __metadata: languageName: unknown linkType: soft +"@kleros/kleros-v2-subgraph-fastbridge@workspace:subgraph-fastbridge": + version: 0.0.0-use.local + resolution: "@kleros/kleros-v2-subgraph-fastbridge@workspace:subgraph-fastbridge" + dependencies: + "@graphprotocol/graph-cli": ^0.33.0 + "@graphprotocol/graph-ts": ^0.27.0 + languageName: unknown + linkType: soft + "@kleros/kleros-v2-subgraph@workspace:subgraph": version: 0.0.0-use.local resolution: "@kleros/kleros-v2-subgraph@workspace:subgraph" From 0b7c751f69688f4f19c21ce2bc145d3f0e841a2c Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Wed, 10 Aug 2022 14:09:29 +0100 Subject: [PATCH 3/5] feat: bridge subgraph update script --- .../abis/FastBridgeSender.json | 175 ++++-------------- subgraph-fastbridge/scripts/updateAbis.sh | 18 ++ subgraph-fastbridge/subgraph.yaml | 4 +- 3 files changed, 57 insertions(+), 140 deletions(-) create mode 100755 subgraph-fastbridge/scripts/updateAbis.sh diff --git a/subgraph-fastbridge/abis/FastBridgeSender.json b/subgraph-fastbridge/abis/FastBridgeSender.json index e75077ce9..9d09c420a 100644 --- a/subgraph-fastbridge/abis/FastBridgeSender.json +++ b/subgraph-fastbridge/abis/FastBridgeSender.json @@ -1,18 +1,16 @@ { - "_format": "hh-sol-artifact-1", - "contractName": "FastBridgeSender", - "sourceName": "src/bridge/FastBridgeSender.sol", + "address": "0x0b9e03455Fed83f209Fa7ce596c93ba6aBAd1f46", "abi": [ { "inputs": [ { - "internalType": "uint256", - "name": "_epochPeriod", - "type": "uint256" + "internalType": "contract ISafeBridge", + "name": "_safebridge", + "type": "address" }, { - "internalType": "address", - "name": "_safeBridgeReceiver", + "internalType": "contract IFastBridgeReceiver", + "name": "_fastBridgeReceiver", "type": "address" } ], @@ -24,76 +22,32 @@ "inputs": [ { "indexed": false, - "internalType": "bytes", - "name": "fastMessage", - "type": "bytes" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "fastMessageHash", - "type": "bytes32" - } - ], - "name": "MessageReceived", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "batchID", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "batchSize", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" + "internalType": "address", + "name": "target", + "type": "address" }, { "indexed": false, "internalType": "bytes32", - "name": "batchMerkleRoot", + "name": "messageHash", "type": "bytes32" - } - ], - "name": "SendBatch", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "epoch", - "type": "uint256" }, { "indexed": false, - "internalType": "bytes32", - "name": "canonicalBridgeMessageID", - "type": "bytes32" + "internalType": "bytes", + "name": "message", + "type": "bytes" } ], - "name": "SentSafe", + "name": "OutgoingMessage", "type": "event" }, { "inputs": [], - "name": "ARB_SYS", + "name": "fastBridgeReceiver", "outputs": [ { - "internalType": "contract IArbSys", + "internalType": "contract IFastBridgeReceiver", "name": "", "type": "address" } @@ -101,46 +55,14 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "batch", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], - "name": "batchSize", + "name": "fastSender", "outputs": [ { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "currentBatchID", - "outputs": [ - { - "internalType": "uint256", + "internalType": "address", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -148,12 +70,12 @@ }, { "inputs": [], - "name": "epochPeriod", + "name": "safebridge", "outputs": [ { - "internalType": "uint256", + "internalType": "contract ISafeBridge", "name": "", - "type": "uint256" + "type": "address" } ], "stateMutability": "view", @@ -161,39 +83,18 @@ }, { "inputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "name": "fastOutbox", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "safeBridgeReceiver", - "outputs": [ { "internalType": "address", - "name": "", + "name": "_receiver", "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "sendBatch", + "name": "sendFast", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -211,25 +112,23 @@ "type": "bytes" } ], - "name": "sendFast", + "name": "sendSafe", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" }, { "inputs": [ { - "internalType": "uint256", - "name": "_epoch", - "type": "uint256" + "internalType": "address", + "name": "_fastSender", + "type": "address" } ], - "name": "sendSafeFallback", + "name": "setFastSender", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" } - ], - "linkReferences": {}, - "deployedLinkReferences": {} + ] } diff --git a/subgraph-fastbridge/scripts/updateAbis.sh b/subgraph-fastbridge/scripts/updateAbis.sh new file mode 100755 index 000000000..5d8fb3a38 --- /dev/null +++ b/subgraph-fastbridge/scripts/updateAbis.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +function update() #file #dataSourceIndex +{ + local f="$1" + local dataSourceIndex="$2" + cat $f | jq '. | {address: .address, abi: .abi}' > abis/$(basename $f) + + address=$(cat abis/$(basename $f) | jq '.address') + yq -i ".dataSources[$dataSourceIndex].source.address=$address" $SCRIPT_DIR/../subgraph.yaml + + blockNumber="$(cat $f | jq '.receipt.blockNumber')" + yq -i ".dataSources[$dataSourceIndex].source.startBlock=$blockNumber" $SCRIPT_DIR/../subgraph.yaml +} + +update "$SCRIPT_DIR/../../contracts/deployments/arbitrumRinkeby/FastBridgeSender.json" 0 \ No newline at end of file diff --git a/subgraph-fastbridge/subgraph.yaml b/subgraph-fastbridge/subgraph.yaml index 34461c84f..e9b02c6c5 100644 --- a/subgraph-fastbridge/subgraph.yaml +++ b/subgraph-fastbridge/subgraph.yaml @@ -6,9 +6,9 @@ dataSources: name: FastBridgeSender network: arbitrum-rinkeby source: - address: "0x1077D69D660c08fB5a1996D4805D9e657f7BA39e" + address: "0x0b9e03455Fed83f209Fa7ce596c93ba6aBAd1f46" abi: FastBridgeSender - startBlock: 12545049 + startBlock: 9610369 mapping: kind: ethereum/events apiVersion: 0.0.6 From f00741128c6e0e29f442d5ee5ecef655ffcfc833 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Mon, 22 Aug 2022 22:44:35 +0100 Subject: [PATCH 4/5] feat: updated and reployed the fastbridge subgraph, added a local graph node config --- contracts/README.md | 4 +- contracts/deploy/02-home-chain.ts | 4 +- ...rToEthereum.json => FastBridgeSender.json} | 0 ...rToEthereum.json => FastBridgeSender.json} | 0 contracts/test/integration/index.ts | 4 +- subgraph-fastbridge/README.md | 107 +++++++- .../abis/FastBridgeSender.json | 167 ++++++++++--- .../abis/FastBridgeSenderToEthereum.json | 231 ++++++++++++++++++ subgraph-fastbridge/docker-compose.yml | 40 +++ subgraph-fastbridge/package.json | 11 +- subgraph-fastbridge/schema.graphql | 1 + subgraph-fastbridge/scripts/updateAbis.sh | 2 +- subgraph-fastbridge/src/FastBridgeSender.ts | 7 +- subgraph-fastbridge/subgraph.yaml | 10 +- 14 files changed, 534 insertions(+), 54 deletions(-) rename contracts/deployments/arbitrumGoerli/{FastBridgeSenderToEthereum.json => FastBridgeSender.json} (100%) rename contracts/deployments/arbitrumRinkeby/{FastBridgeSenderToEthereum.json => FastBridgeSender.json} (100%) create mode 100644 subgraph-fastbridge/abis/FastBridgeSenderToEthereum.json create mode 100644 subgraph-fastbridge/docker-compose.yml diff --git a/contracts/README.md b/contracts/README.md index 18b5d10cb..ebd019c8e 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -20,7 +20,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [PNK](https://goerli-rollup-explorer.arbitrum.io/token/0x4DEeeFD054434bf6721eF39Aa18EfB3fd0D12610/token-transfers) - [DisputeKitClassic](https://goerli-rollup-explorer.arbitrum.io/address/0x8F1a2B8F9b04320375856580Fc6B1669Cb12a9EE) - [DisputeResolver](https://goerli-rollup-explorer.arbitrum.io/address/0x04Fb43F2Ce076867b5ba38750Ecb2cc6BDe78D61) -- [FastBridgeSenderToEthereum](https://goerli-rollup-explorer.arbitrum.io/address/0xcFc0b84419583ff7b32fD5139B789cE858517d4C) +- [FastBridgeSender](https://goerli-rollup-explorer.arbitrum.io/address/0xcFc0b84419583ff7b32fD5139B789cE858517d4C) - [HomeGatewayToEthereum](https://goerli-rollup-explorer.arbitrum.io/address/0xc7e3BF90299f6BD9FA7c3703837A9CAbB5743636) - [IncrementalNG](https://goerli-rollup-explorer.arbitrum.io/address/0x99c1f883f0f5de1737099F1BCB268d1f8D450f8b) - [KlerosCore](https://goerli-rollup-explorer.arbitrum.io/address/0x87142b7E9C7D026776499120D902AF8896C07894) @@ -38,7 +38,7 @@ Refresh the list of deployed contracts by running `./scripts/generateDeployments - [PNK](https://testnet.arbiscan.io/token/0x364530164a2338cdba211f72c1438eb811b5c639) - [DisputeKitClassic](https://testnet.arbiscan.io/address/0xA2c538AA05BBCc44c213441f6f3777223D2BF9e5) - [DisputeResolver](https://testnet.arbiscan.io/address/0x67e8191F61466c57A17542A52F9f39f336A242fD) -- [FastBridgeSenderToEthereum](https://testnet.arbiscan.io/address/0xf8A4a85e7153374A1b9BDA763a84252eC286843b) +- [FastBridgeSender](https://testnet.arbiscan.io/address/0xf8A4a85e7153374A1b9BDA763a84252eC286843b) - [HomeGatewayToEthereum](https://testnet.arbiscan.io/address/0x4e894c2B60214beC53B60D09F39544518296C07B) - [IncrementalNG](https://testnet.arbiscan.io/address/0x078dAd05373d19d7fd6829735b765F12242a4300) - [KlerosCore](https://testnet.arbiscan.io/address/0x815d709EFCF5E69e2e9E2F8d3815d762496a2f0F) diff --git a/contracts/deploy/02-home-chain.ts b/contracts/deploy/02-home-chain.ts index e5795579e..93bc9410d 100644 --- a/contracts/deploy/02-home-chain.ts +++ b/contracts/deploy/02-home-chain.ts @@ -21,7 +21,7 @@ const deployHomeGateway: DeployFunction = async (hre: HardhatRuntimeEnvironment) const fastBridgeReceiver = await deployments.get("FastBridgeReceiverOnEthereum"); const arbSysMock = await deploy("ArbSysMock", { from: deployer, log: true }); - const fastBridgeSender = await deploy("FastBridgeSenderToEthereumMock", { + const fastBridgeSender = await deploy("FastBridgeSenderMock", { from: deployer, contract: "FastBridgeSenderMock", args: [epochPeriod, fastBridgeReceiver.address, arbSysMock.address], @@ -63,7 +63,7 @@ const deployHomeGateway: DeployFunction = async (hre: HardhatRuntimeEnvironment) const liveDeployer = async () => { const fastBridgeReceiver = await hre.companionNetworks.foreign.deployments.get("FastBridgeReceiverOnEthereum"); - const fastBridgeSender = await deploy("FastBridgeSenderToEthereum", { + const fastBridgeSender = await deploy("FastBridgeSender", { from: deployer, contract: "FastBridgeSender", args: [epochPeriod, fastBridgeReceiver.address], diff --git a/contracts/deployments/arbitrumGoerli/FastBridgeSenderToEthereum.json b/contracts/deployments/arbitrumGoerli/FastBridgeSender.json similarity index 100% rename from contracts/deployments/arbitrumGoerli/FastBridgeSenderToEthereum.json rename to contracts/deployments/arbitrumGoerli/FastBridgeSender.json diff --git a/contracts/deployments/arbitrumRinkeby/FastBridgeSenderToEthereum.json b/contracts/deployments/arbitrumRinkeby/FastBridgeSender.json similarity index 100% rename from contracts/deployments/arbitrumRinkeby/FastBridgeSenderToEthereum.json rename to contracts/deployments/arbitrumRinkeby/FastBridgeSender.json diff --git a/contracts/test/integration/index.ts b/contracts/test/integration/index.ts index c02394e13..e2303788b 100644 --- a/contracts/test/integration/index.ts +++ b/contracts/test/integration/index.ts @@ -8,7 +8,7 @@ import { FastBridgeReceiverOnEthereum, ForeignGatewayOnEthereum, ArbitrableExample, - FastBridgeSenderToEthereumMock, + FastBridgeSenderMock, HomeGatewayToEthereum, DisputeKitClassic, InboxMock, @@ -62,7 +62,7 @@ describe("Integration tests", async () => { fastBridgeReceiver = (await ethers.getContract("FastBridgeReceiverOnEthereum")) as FastBridgeReceiverOnEthereum; foreignGateway = (await ethers.getContract("ForeignGatewayOnEthereum")) as ForeignGatewayOnEthereum; arbitrable = (await ethers.getContract("ArbitrableExample")) as ArbitrableExample; - fastBridgeSender = (await ethers.getContract("FastBridgeSenderToEthereumMock")) as FastBridgeSenderToEthereumMock; + fastBridgeSender = (await ethers.getContract("FastBridgeSenderMock")) as FastBridgeSenderMock; homeGateway = (await ethers.getContract("HomeGatewayToEthereum")) as HomeGatewayToEthereum; inbox = (await ethers.getContract("InboxMock")) as InboxMock; }); diff --git a/subgraph-fastbridge/README.md b/subgraph-fastbridge/README.md index dfb6faf8e..a14a5257d 100644 --- a/subgraph-fastbridge/README.md +++ b/subgraph-fastbridge/README.md @@ -1,3 +1,108 @@ # @kleros/kleros-v2-subgraph-fastbridge -🚧 ⚖️ 🚧 +## Deployments + +- [kleros/fastbridge-arbitrum-rinkeby](https://thegraph.com/hosted-service/subgraph/kleros/fastbridge-arbitrum-rinkeby) + +## Build + +```bash +$ yarn + +$ yarn codegen + +$ yarn build +``` + +## Deployment to The Graph (hosted service) + +### Authentication + +Get an API key from the thegraph.com, then authenticate. + +```bash +$ yarn run graph auth --product hosted-service +``` + +### Deployment + +```bash +yarn deploy +``` + +## Deployment to a local Graph node + +_Credits to the [scaffold-eth service package](https://github.com/scaffold-eth/scaffold-eth/tree/b03d07f15882db626300ffa04f222736b2a22f81/packages/services/graph-node)_ + +Preconfigured Docker image for running a Graph Node. + +## Usage + +**Prerequisite**: docker and docker-compose. + +```bash +$ docker-compose up -d +Starting graph-node_postgres_1 ... done +Starting graph-node_ipfs_1 ... done +Starting graph-node_graph-node_1 ... done + +$ docker-compose logs -f +... +``` + +This will start docker containers for the following services: + +- IPFS, +- Postgres +- **Graph Node** connecting to the Arbitrum Rinkeby official RPC + +This also creates persistent data directories for IPFS and Postgres in `./data/ipfs` and `./data/postgres`. + +Once this is up and running, you can use [`graph-cli`](https://github.com/graphprotocol/graph-cli) to create and deploy your subgraph to the running Graph Node. + +```bash +# First time only. +$ yarn create-local +Created subgraph: fastbridge + +$ yarn deploy-local --version-label v0.0.1 +✔ Apply migrations +✔ Load subgraph from subgraph.yaml + Compile data source: FastBridgeSender => build/FastBridgeSender/FastBridgeSender.wasm +✔ Compile subgraph + Copy schema file build/schema.graphql + Write subgraph file build/FastBridgeSender/abis/FastBridgeSender.json + Write subgraph manifest build/subgraph.yaml +✔ Write compiled subgraph to build/ + Add file to IPFS build/schema.graphql + .. Qmb3Uahj4qKh5u3V4KuraXJqsrUVwPtvva1KQQSb5tLov9 + Add file to IPFS build/FastBridgeSender/abis/FastBridgeSender.json + .. QmQas2SuTQH6zybTVMGBym76kyBoTp7MwkogcmtHAeMoRj + Add file to IPFS build/FastBridgeSender/FastBridgeSender.wasm + .. QmSLfCYp19WW5JEiaKdmcGFgBCJ5DA723dEkM6QvXE2eCa +✔ Upload subgraph to IPFS + +Build completed: QmWjRVXec6auQdnpvYJ7F8vW7PzkJHYJhFtorWZAhtP9A3 + +Deployed to http://localhost:8000/subgraphs/name/fastbridge/graphql + +Subgraph endpoints: +Queries (HTTP): http://localhost:8000/subgraphs/name/fastbridge +``` + +## Access + +### Graph Node + +- GraphiQL: `http://localhost:8000/` +- HTTP: `http://localhost:8000/subgraphs/name/` +- WebSockets: `ws://localhost:8001/subgraphs/name/` +- Admin: `http://localhost:8020/` + +### IPFS + +- `127.0.0.1:5001` or `/ip4/127.0.0.1/tcp/5001` + +### Postgres + +- `postgresql://graph-node:let-me-in@localhost:5432/graph-node` diff --git a/subgraph-fastbridge/abis/FastBridgeSender.json b/subgraph-fastbridge/abis/FastBridgeSender.json index 9d09c420a..4fed10ef1 100644 --- a/subgraph-fastbridge/abis/FastBridgeSender.json +++ b/subgraph-fastbridge/abis/FastBridgeSender.json @@ -1,16 +1,16 @@ { - "address": "0x0b9e03455Fed83f209Fa7ce596c93ba6aBAd1f46", + "address": "0xf8A4a85e7153374A1b9BDA763a84252eC286843b", "abi": [ { "inputs": [ { - "internalType": "contract ISafeBridge", - "name": "_safebridge", - "type": "address" + "internalType": "uint256", + "name": "_epochPeriod", + "type": "uint256" }, { - "internalType": "contract IFastBridgeReceiver", - "name": "_fastBridgeReceiver", + "internalType": "address", + "name": "_safeBridgeReceiver", "type": "address" } ], @@ -20,34 +20,78 @@ { "anonymous": false, "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "batchID", + "type": "uint256" + }, { "indexed": false, - "internalType": "address", - "name": "target", - "type": "address" + "internalType": "uint256", + "name": "batchSize", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" }, { "indexed": false, "internalType": "bytes32", - "name": "messageHash", + "name": "batchMerkleRoot", "type": "bytes32" - }, + } + ], + "name": "BatchOutgoing", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { "indexed": false, "internalType": "bytes", - "name": "message", + "name": "fastMessage", "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "fastMessageHash", + "type": "bytes32" } ], - "name": "OutgoingMessage", + "name": "MessageReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "canonicalBridgeMessageID", + "type": "bytes32" + } + ], + "name": "SentSafe", "type": "event" }, { "inputs": [], - "name": "fastBridgeReceiver", + "name": "ARB_SYS", "outputs": [ { - "internalType": "contract IFastBridgeReceiver", + "internalType": "contract IArbSys", "name": "", "type": "address" } @@ -55,14 +99,33 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "batch", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], - "name": "fastSender", + "name": "batchSize", "outputs": [ { - "internalType": "address", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", @@ -70,12 +133,25 @@ }, { "inputs": [], - "name": "safebridge", + "name": "currentBatchID", "outputs": [ { - "internalType": "contract ISafeBridge", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" } ], "stateMutability": "view", @@ -83,18 +159,39 @@ }, { "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "fastOutbox", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "safeBridgeReceiver", + "outputs": [ { "internalType": "address", - "name": "_receiver", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "_calldata", - "type": "bytes" } ], - "name": "sendFast", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sendBatch", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -112,22 +209,22 @@ "type": "bytes" } ], - "name": "sendSafe", + "name": "sendFast", "outputs": [], - "stateMutability": "payable", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "_fastSender", - "type": "address" + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" } ], - "name": "setFastSender", + "name": "sendSafeFallback", "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "payable", "type": "function" } ] diff --git a/subgraph-fastbridge/abis/FastBridgeSenderToEthereum.json b/subgraph-fastbridge/abis/FastBridgeSenderToEthereum.json new file mode 100644 index 000000000..4fed10ef1 --- /dev/null +++ b/subgraph-fastbridge/abis/FastBridgeSenderToEthereum.json @@ -0,0 +1,231 @@ +{ + "address": "0xf8A4a85e7153374A1b9BDA763a84252eC286843b", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epochPeriod", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_safeBridgeReceiver", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "batchID", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "batchSize", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "batchMerkleRoot", + "type": "bytes32" + } + ], + "name": "BatchOutgoing", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes", + "name": "fastMessage", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "fastMessageHash", + "type": "bytes32" + } + ], + "name": "MessageReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "canonicalBridgeMessageID", + "type": "bytes32" + } + ], + "name": "SentSafe", + "type": "event" + }, + { + "inputs": [], + "name": "ARB_SYS", + "outputs": [ + { + "internalType": "contract IArbSys", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "batch", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "batchSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentBatchID", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "fastOutbox", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "safeBridgeReceiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "sendBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_receiver", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "sendFast", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "sendSafeFallback", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ] +} diff --git a/subgraph-fastbridge/docker-compose.yml b/subgraph-fastbridge/docker-compose.yml new file mode 100644 index 000000000..4b269237d --- /dev/null +++ b/subgraph-fastbridge/docker-compose.yml @@ -0,0 +1,40 @@ +version: "3" +services: + graph-node: + image: graphprotocol/graph-node:latest + ports: + - "8000:8000" + - "8001:8001" + - "8020:8020" + - "8030:8030" + - "8040:8040" + depends_on: + - ipfs + - postgres + environment: + postgres_host: postgres + postgres_user: graph-node + postgres_pass: let-me-in + postgres_db: graph-node + ipfs: "ipfs:5001" + ethereum: "arbitrum-rinkeby:https://rinkeby.arbitrum.io/rpc" + GRAPH_LOG: debug + extra_hosts: + - "host.docker.internal:host-gateway" + ipfs: + image: ipfs/go-ipfs:v0.10.0 + ports: + - "5001:5001" + volumes: + - ./data/ipfs:/data/ipfs + postgres: + image: postgres + ports: + - "5432:5432" + command: ["postgres", "-cshared_preload_libraries=pg_stat_statements"] + environment: + POSTGRES_USER: graph-node + POSTGRES_PASSWORD: let-me-in + POSTGRES_DB: graph-node + volumes: + - ./data/postgres:/var/lib/postgresql/data diff --git a/subgraph-fastbridge/package.json b/subgraph-fastbridge/package.json index 013414092..8c76fa70b 100644 --- a/subgraph-fastbridge/package.json +++ b/subgraph-fastbridge/package.json @@ -4,13 +4,16 @@ "scripts": { "codegen": "graph codegen", "build": "graph build", - "deploy": "graph deploy --node https://api.thegraph.com/deploy/ fastbridge", - "create-local": "graph create --node http://localhost:8020/ fastbridge", - "remove-local": "graph remove --node http://localhost:8020/ fastbridge", - "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 fastbridge" + "deploy": "graph deploy --node https://api.thegraph.com/deploy/ kleros/fastbridge-arbitrum-rinkeby", + "create-local": "graph create --node http://localhost:8020/ kleros/fastbridge-arbitrum-rinkeby", + "remove-local": "graph remove --node http://localhost:8020/ kleros/fastbridge-arbitrum-rinkeby", + "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 kleros/fastbridge-arbitrum-rinkeby" }, "dependencies": { "@graphprotocol/graph-cli": "^0.33.0", "@graphprotocol/graph-ts": "^0.27.0" + }, + "volta": { + "node": "16.17.0" } } diff --git a/subgraph-fastbridge/schema.graphql b/subgraph-fastbridge/schema.graphql index 1d3e1f764..5957a4d09 100644 --- a/subgraph-fastbridge/schema.graphql +++ b/subgraph-fastbridge/schema.graphql @@ -32,4 +32,5 @@ type Batch @entity { batchSize: BigInt! merkleRoot: Bytes sentSafe: Boolean + canonicalBridgeMessageID: Bytes } \ No newline at end of file diff --git a/subgraph-fastbridge/scripts/updateAbis.sh b/subgraph-fastbridge/scripts/updateAbis.sh index 5d8fb3a38..292a23064 100755 --- a/subgraph-fastbridge/scripts/updateAbis.sh +++ b/subgraph-fastbridge/scripts/updateAbis.sh @@ -15,4 +15,4 @@ function update() #file #dataSourceIndex yq -i ".dataSources[$dataSourceIndex].source.startBlock=$blockNumber" $SCRIPT_DIR/../subgraph.yaml } -update "$SCRIPT_DIR/../../contracts/deployments/arbitrumRinkeby/FastBridgeSender.json" 0 \ No newline at end of file +update "$SCRIPT_DIR/../../contracts/deployments/arbitrumRinkeby/FastBridgeSender.json" 0 diff --git a/subgraph-fastbridge/src/FastBridgeSender.ts b/subgraph-fastbridge/src/FastBridgeSender.ts index d9b367897..3092d062e 100644 --- a/subgraph-fastbridge/src/FastBridgeSender.ts +++ b/subgraph-fastbridge/src/FastBridgeSender.ts @@ -3,7 +3,7 @@ import { Bytes, ByteArray, BigInt, crypto } from "@graphprotocol/graph-ts"; import { FastBridgeSender, MessageReceived, - SendBatch, + BatchOutgoing, SentSafe, } from "../generated/FastBridgeSender/FastBridgeSender"; import { @@ -18,7 +18,8 @@ export function handleSentSafe(event: SentSafe): void { const batch = Batch.load(event.params.epoch.toString()); if (batch) { batch.sentSafe = true; - event.params.canonicalBridgeMessageID; + batch.canonicalBridgeMessageID = event.params.canonicalBridgeMessageID; + batch.save(); } } @@ -53,7 +54,7 @@ export function handleMessageReceived(event: MessageReceived): void { fastMessage.save(); } -export function handleSendBatch(event: SendBatch): void { +export function handleBatchOutgoing(event: BatchOutgoing): void { const layers: ByteArray[][] = []; const layerZero: ByteArray[] = []; diff --git a/subgraph-fastbridge/subgraph.yaml b/subgraph-fastbridge/subgraph.yaml index e9b02c6c5..8b24a0d3c 100644 --- a/subgraph-fastbridge/subgraph.yaml +++ b/subgraph-fastbridge/subgraph.yaml @@ -1,4 +1,6 @@ specVersion: 0.0.4 +description: Fast Bridge Sender on Arbitrum Rinkeby. +repository: https://github.com/kleros/kleros-v2/tree/master/subgraph-fastbridge schema: file: ./schema.graphql dataSources: @@ -6,9 +8,9 @@ dataSources: name: FastBridgeSender network: arbitrum-rinkeby source: - address: "0x0b9e03455Fed83f209Fa7ce596c93ba6aBAd1f46" + address: "0xf8A4a85e7153374A1b9BDA763a84252eC286843b" abi: FastBridgeSender - startBlock: 9610369 + startBlock: 14453120 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -27,6 +29,6 @@ dataSources: handler: handleSentSafe - event: MessageReceived(bytes,bytes32) handler: handleMessageReceived - - event: SendBatch(indexed uint256,uint256,uint256,bytes32) - handler: handleSendBatch + - event: BatchOutgoing(indexed uint256,uint256,uint256,bytes32) + handler: handleBatchOutgoing file: ./src/FastBridgeSender.ts From 2aed0e0f9455d3e94a26f94435e909782edfb845 Mon Sep 17 00:00:00 2001 From: jaybuidl Date: Mon, 22 Aug 2022 23:05:21 +0100 Subject: [PATCH 5/5] fix: keeping the linter happy --- subgraph-fastbridge/src/FastBridgeSender.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/subgraph-fastbridge/src/FastBridgeSender.ts b/subgraph-fastbridge/src/FastBridgeSender.ts index 3092d062e..284fce806 100644 --- a/subgraph-fastbridge/src/FastBridgeSender.ts +++ b/subgraph-fastbridge/src/FastBridgeSender.ts @@ -63,7 +63,7 @@ export function handleBatchOutgoing(event: BatchOutgoing): void { const batchSize = event.params.batchSize; const currentBatchID = event.params.batchID; - let batch = new Batch(currentBatchID.toString()); + const batch = new Batch(currentBatchID.toString()); batch.epochFinal = epochFinal; batch.batchSize = batchSize; @@ -87,8 +87,8 @@ export function handleBatchOutgoing(event: BatchOutgoing): void { // PROOF for (let idx = 0; idx < layerZero.length; idx++) { - let proof: ByteArray[] = []; - let _proof = new Proof(currentBatchID.toString() + "," + idx.toString()); + const proof: ByteArray[] = []; + const _proof = new Proof(currentBatchID.toString() + "," + idx.toString()); let _idx = idx; for (let i = 0; i < layers.length; i++) { const pairIdx = idx % 2 === 0 ? idx + 1 : idx - 1; @@ -109,7 +109,7 @@ export function handleBatchOutgoing(event: BatchOutgoing): void { } function Flatten(a: ByteArray[]): ByteArray { - let out = new ByteArray(32 * a.length); + const out = new ByteArray(32 * a.length); for (let i = 0; i < a.length; i++) out.set(a[i], i * 32); return out; } @@ -118,7 +118,7 @@ function getNextLayer(elements: ByteArray[]): ByteArray[] { return elements.reduce((layer, el, idx, arr) => { if (idx % 2 === 0) { // Hash the current element with its pair element - if (idx == arr.length - 1) { + if (idx === arr.length - 1) { layer.push(el); } else { layer.push(crypto.keccak256(concatAndSortByteArrays(el, arr[idx + 1]))); @@ -130,13 +130,13 @@ function getNextLayer(elements: ByteArray[]): ByteArray[] { } function firstSlotReverse(a: ByteArray): ByteArray { - let out = new ByteArray(32); + const out = new ByteArray(32); for (let i = 0; i < 32; i++) out[i] = a[31 - i]; return out; } function getAddress(input: ByteArray, offset: i32): ByteArray { - let out = new ByteArray(20); + const out = new ByteArray(20); for (let i = 0; i < 20; i++) out[i] = input[i + offset]; return out; }