From d8ed4257df05505cbd46b5b11ce447f9443ab214 Mon Sep 17 00:00:00 2001 From: markspanbroek Date: Mon, 25 Apr 2022 17:12:37 +0400 Subject: [PATCH] [contracts] Make contract interactions optional in the node (#91) Adds --eth-deployment parameter. Does not crash when deployment json is missing or incorrect. --- dagger/conf.nim | 6 +++++ dagger/contracts/deployment.nim | 10 +++++++-- dagger/contracts/interactions.nim | 33 +++++++++++++++++++++++----- dagger/dagger.nim | 6 ++++- dagger/node.nim | 12 +++++----- tests/contracts/testInteractions.nim | 11 ++++++---- tests/dagger/testnode.nim | 2 +- 7 files changed, 60 insertions(+), 20 deletions(-) diff --git a/dagger/conf.nim b/dagger/conf.nim index e1f3d561..5ef7f770 100644 --- a/dagger/conf.nim +++ b/dagger/conf.nim @@ -154,6 +154,12 @@ type name: "eth-account" .}: EthAddress + ethDeployment* {. + desc: "The json file describing the contract deployment" + defaultValue: string.default + name: "eth-deployment" + .}: string + of initNode: discard diff --git a/dagger/contracts/deployment.nim b/dagger/contracts/deployment.nim index bfe9c833..2b95a651 100644 --- a/dagger/contracts/deployment.nim +++ b/dagger/contracts/deployment.nim @@ -16,5 +16,11 @@ proc deployment*(file = defaultFile): Deployment = Deployment(json: parseFile(file)) proc address*(deployment: Deployment, Contract: typedesc): ?Address = - let address = deployment.json["contracts"][$Contract]["address"].getStr() - Address.init(address) + if deployment.json == nil: + return none Address + + try: + let address = deployment.json["contracts"][$Contract]["address"].getStr() + Address.init(address) + except KeyError: + none Address diff --git a/dagger/contracts/interactions.nim b/dagger/contracts/interactions.nim index 0f732f09..26e32b6e 100644 --- a/dagger/contracts/interactions.nim +++ b/dagger/contracts/interactions.nim @@ -1,4 +1,5 @@ import pkg/ethers +import pkg/chronicles import ../purchasing import ../sales import ../proving @@ -10,6 +11,7 @@ import ./proofs export purchasing export sales export proving +export chronicles type ContractInteractions* = ref object @@ -19,11 +21,16 @@ type proc new*(_: type ContractInteractions, signer: Signer, - deployment: Deployment): ContractInteractions = - let contract = Storage.new(!deployment.address(Storage), signer) + deployment: Deployment): ?ContractInteractions = + + without address =? deployment.address(Storage): + error "Unable to determine address of the Storage smart contract" + return none ContractInteractions + + let contract = Storage.new(address, signer) let market = OnChainMarket.new(contract) let proofs = OnChainProofs.new(contract) - ContractInteractions( + some ContractInteractions( purchasing: Purchasing.new(market), sales: Sales.new(market), proving: Proving.new(proofs) @@ -31,16 +38,30 @@ proc new*(_: type ContractInteractions, proc new*(_: type ContractInteractions, providerUrl: string, - account = Address.default): ContractInteractions = + deploymentFile: string = string.default, + account = Address.default): ?ContractInteractions = + let provider = JsonRpcProvider.new(providerUrl) + var signer: Signer if account == Address.default: signer = provider.getSigner() else: signer = provider.getSigner(account) - ContractInteractions.new(signer, deployment()) -proc new*(_: type ContractInteractions): ContractInteractions = + var deploy: Deployment + try: + if deploymentFile == string.default: + deploy = deployment() + else: + deploy = deployment(deploymentFile) + except IOError as e: + error "Unable to read deployment json", msg = e.msg + return none ContractInteractions + + ContractInteractions.new(signer, deploy) + +proc new*(_: type ContractInteractions): ?ContractInteractions = ContractInteractions.new("ws://localhost:8545") proc start*(interactions: ContractInteractions) {.async.} = diff --git a/dagger/dagger.nim b/dagger/dagger.nim index 96ffd3aa..aebb593c 100644 --- a/dagger/dagger.nim +++ b/dagger/dagger.nim @@ -122,7 +122,11 @@ proc new*(T: type DaggerServer, config: DaggerConf): T = engine = BlockExcEngine.new(localStore, wallet, network, discovery) store = NetworkStore.new(engine, localStore) erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider) - contracts = ContractInteractions.new(config.ethProvider, config.ethAccount) + contracts = ContractInteractions.new( + config.ethProvider, + config.ethDeployment, + config.ethAccount + ) daggerNode = DaggerNodeRef.new(switch, store, engine, erasure, discovery, contracts) restServer = RestServerRef.new( daggerNode.initRestApi(), diff --git a/dagger/node.nim b/dagger/node.nim index c68e0510..8420fc2e 100644 --- a/dagger/node.nim +++ b/dagger/node.nim @@ -43,7 +43,7 @@ type engine*: BlockExcEngine erasure*: Erasure discovery*: Discovery - contracts*: ContractInteractions + contracts*: ?ContractInteractions proc start*(node: DaggerNodeRef) {.async.} = await node.switch.start() @@ -51,8 +51,8 @@ proc start*(node: DaggerNodeRef) {.async.} = await node.erasure.start() await node.discovery.start() - if not node.contracts.isNil: - await node.contracts.start() + if contracts =? node.contracts: + await contracts.start() node.networkId = node.switch.peerInfo.peerId notice "Started dagger node", id = $node.networkId, addrs = node.switch.peerInfo.addrs @@ -65,8 +65,8 @@ proc stop*(node: DaggerNodeRef) {.async.} = await node.erasure.stop() await node.discovery.stop() - if not node.contracts.isNil: - await node.contracts.stop() + if contracts =? node.contracts: + await contracts.stop() proc findPeer*( node: DaggerNodeRef, @@ -244,7 +244,7 @@ proc new*( engine: BlockExcEngine, erasure: Erasure, discovery: Discovery, - contracts: ContractInteractions): T = + contracts: ?ContractInteractions): T = T( switch: switch, blockStore: store, diff --git a/tests/contracts/testInteractions.nim b/tests/contracts/testInteractions.nim index 3101354e..744e6c32 100644 --- a/tests/contracts/testInteractions.nim +++ b/tests/contracts/testInteractions.nim @@ -1,3 +1,4 @@ +import std/os import ./ethertest import dagger/contracts import ./examples @@ -7,18 +8,20 @@ ethersuite "Storage Contract Interactions": var contracts: ContractInteractions setup: - contracts = ContractInteractions.new() + contracts = !ContractInteractions.new() test "can be instantiated with a signer and deployment info": let signer = provider.getSigner() let deployment = deployment() - check ContractInteractions.new(signer, deployment) != nil + check ContractInteractions.new(signer, deployment).isSome test "can be instantiated with a provider url and account": let url = "http://localhost:8545" let account = Address.example - check ContractInteractions.new(url) != nil - check ContractInteractions.new(url, account) != nil + let deployment = "vendor" / "dagger-contracts" / "deployment-localhost.json" + check ContractInteractions.new(url).isSome + check ContractInteractions.new(url, account = account).isSome + check ContractInteractions.new(url, deploymentFile = deployment).isSome test "provides purchasing": check contracts.purchasing != nil diff --git a/tests/dagger/testnode.nim b/tests/dagger/testnode.nim index 80ea311b..8c115351 100644 --- a/tests/dagger/testnode.nim +++ b/tests/dagger/testnode.nim @@ -36,7 +36,7 @@ suite "Test Node": store: NetworkStore node: DaggerNodeRef discovery: Discovery - contracts: ContractInteractions + contracts: ?ContractInteractions setup: file = open(path.splitFile().dir /../ "fixtures" / "test.jpg")