Better command line options for Ethereum (#181)

* [contracts] ContractInteractions.new() now requires account parameter

* [cli] Only perform Ethereum interactions when --eth-account is specified

* [cli] Add --persistence option that is disabled by default

* [cli] Use Option for ethDeployment parameter

* [node] Better error reporting when Ethereum node cannot be reached
This commit is contained in:
markspanbroek 2022-08-09 06:29:06 +02:00 committed by GitHub
parent eebcf7e7b2
commit 097a4cfd67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 30 deletions

View File

@ -52,6 +52,21 @@ proc stop*(s: CodexServer) {.async.} =
s.runHandle.complete() s.runHandle.complete()
proc new(_: type ContractInteractions, config: CodexConf): ?ContractInteractions =
if not config.persistence:
if config.ethAccount.isSome:
warn "Ethereum account was set, but persistence is not enabled"
return
without account =? config.ethAccount:
error "Persistence enabled, but no Ethereum account was set"
quit QuitFailure
if deployment =? config.ethDeployment:
ContractInteractions.new(config.ethProvider, account, deployment)
else:
ContractInteractions.new(config.ethProvider, account)
proc new*(T: type CodexServer, config: CodexConf): T = proc new*(T: type CodexServer, config: CodexConf): T =
const SafePermissions = {UserRead, UserWrite} const SafePermissions = {UserRead, UserWrite}
@ -125,11 +140,7 @@ proc new*(T: type CodexServer, config: CodexConf): T =
engine = BlockExcEngine.new(localStore, wallet, network, discovery, peerStore, pendingBlocks) engine = BlockExcEngine.new(localStore, wallet, network, discovery, peerStore, pendingBlocks)
store = NetworkStore.new(engine, localStore) store = NetworkStore.new(engine, localStore)
erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider) erasure = Erasure.new(store, leoEncoderProvider, leoDecoderProvider)
contracts = ContractInteractions.new( contracts = ContractInteractions.new(config)
config.ethProvider,
config.ethDeployment,
config.ethAccount
)
codexNode = CodexNodeRef.new(switch, store, engine, erasure, blockDiscovery, contracts) codexNode = CodexNodeRef.new(switch, store, engine, erasure, blockDiscovery, contracts)
restServer = RestServerRef.new( restServer = RestServerRef.new(
codexNode.initRestApi(config), codexNode.initRestApi(config),

View File

@ -142,6 +142,12 @@ type
name: "cache-size" name: "cache-size"
abbr: "c" }: Natural abbr: "c" }: Natural
persistence* {.
desc: "Enables persistence mechanism, requires an Ethereum node"
defaultValue: false
name: "persistence"
.}: bool
ethProvider* {. ethProvider* {.
desc: "The URL of the JSON-RPC API of the Ethereum node" desc: "The URL of the JSON-RPC API of the Ethereum node"
defaultValue: "ws://localhost:8545" defaultValue: "ws://localhost:8545"
@ -150,15 +156,15 @@ type
ethAccount* {. ethAccount* {.
desc: "The Ethereum account that is used for storage contracts" desc: "The Ethereum account that is used for storage contracts"
defaultValue: EthAddress.default defaultValue: EthAddress.none
name: "eth-account" name: "eth-account"
.}: EthAddress .}: Option[EthAddress]
ethDeployment* {. ethDeployment* {.
desc: "The json file describing the contract deployment" desc: "The json file describing the contract deployment"
defaultValue: string.default defaultValue: string.none
name: "eth-deployment" name: "eth-deployment"
.}: string .}: Option[string]
of initNode: of initNode:
discard discard

View File

@ -42,16 +42,11 @@ proc new*(_: type ContractInteractions,
proc new*(_: type ContractInteractions, proc new*(_: type ContractInteractions,
providerUrl: string, providerUrl: string,
deploymentFile: string = string.default, account: Address,
account = Address.default): ?ContractInteractions = deploymentFile: string = string.default): ?ContractInteractions =
let provider = JsonRpcProvider.new(providerUrl) let provider = JsonRpcProvider.new(providerUrl)
let signer = provider.getSigner(account)
var signer: Signer
if account == Address.default:
signer = provider.getSigner()
else:
signer = provider.getSigner(account)
var deploy: Deployment var deploy: Deployment
try: try:
@ -65,8 +60,9 @@ proc new*(_: type ContractInteractions,
ContractInteractions.new(signer, deploy) ContractInteractions.new(signer, deploy)
proc new*(_: type ContractInteractions): ?ContractInteractions = proc new*(_: type ContractInteractions,
ContractInteractions.new("ws://localhost:8545") account: Address): ?ContractInteractions =
ContractInteractions.new("ws://localhost:8545", account)
proc start*(interactions: ContractInteractions) {.async.} = proc start*(interactions: ContractInteractions) {.async.} =
await interactions.clock.start() await interactions.clock.start()

View File

@ -289,7 +289,7 @@ proc new*(
engine: BlockExcEngine, engine: BlockExcEngine,
erasure: Erasure, erasure: Erasure,
discovery: Discovery, discovery: Discovery,
contracts: ?ContractInteractions): T = contracts = ContractInteractions.none): T =
T( T(
switch: switch, switch: switch,
blockStore: store, blockStore: store,
@ -344,7 +344,11 @@ proc start*(node: CodexNodeRef) {.async.} =
# TODO: generate proof # TODO: generate proof
return @[42'u8] return @[42'u8]
await contracts.start() try:
await contracts.start()
except CatchableError as error:
error "Unable to start contract interactions: ", error=error.msg
node.contracts = ContractInteractions.none
node.networkId = node.switch.peerInfo.peerId node.networkId = node.switch.peerInfo.peerId
notice "Started codex node", id = $node.networkId, addrs = node.switch.peerInfo.addrs notice "Started codex node", id = $node.networkId, addrs = node.switch.peerInfo.addrs

View File

@ -17,7 +17,6 @@ import pkg/codex/node
import pkg/codex/manifest import pkg/codex/manifest
import pkg/codex/discovery import pkg/codex/discovery
import pkg/codex/blocktype as bt import pkg/codex/blocktype as bt
import pkg/codex/contracts
import ./helpers import ./helpers
@ -39,7 +38,6 @@ suite "Test Node":
peerStore: PeerCtxStore peerStore: PeerCtxStore
pendingBlocks: PendingBlocksManager pendingBlocks: PendingBlocksManager
discovery: DiscoveryEngine discovery: DiscoveryEngine
contracts: ?ContractInteractions
setup: setup:
file = open(path.splitFile().dir /../ "fixtures" / "test.jpg") file = open(path.splitFile().dir /../ "fixtures" / "test.jpg")
@ -54,8 +52,7 @@ suite "Test Node":
discovery = DiscoveryEngine.new(localStore, peerStore, network, blockDiscovery, pendingBlocks) discovery = DiscoveryEngine.new(localStore, peerStore, network, blockDiscovery, pendingBlocks)
engine = BlockExcEngine.new(localStore, wallet, network, discovery, peerStore, pendingBlocks) engine = BlockExcEngine.new(localStore, wallet, network, discovery, peerStore, pendingBlocks)
store = NetworkStore.new(engine, localStore) store = NetworkStore.new(engine, localStore)
contracts = ContractInteractions.new() node = CodexNodeRef.new(switch, store, engine, nil, blockDiscovery) # TODO: pass `Erasure`
node = CodexNodeRef.new(switch, store, engine, nil, blockDiscovery, contracts) # TODO: pass `Erasure`
await node.start() await node.start()

View File

@ -5,23 +5,24 @@ import ./examples
ethersuite "Storage Contract Interactions": ethersuite "Storage Contract Interactions":
let account = Address.example
var contracts: ContractInteractions var contracts: ContractInteractions
setup: setup:
contracts = !ContractInteractions.new() contracts = !ContractInteractions.new(account)
test "can be instantiated with a signer and deployment info": test "can be instantiated with a signer and deployment info":
let signer = provider.getSigner() let signer = provider.getSigner()
let deployment = deployment() let deployment = deployment()
check ContractInteractions.new(signer, deployment).isSome check ContractInteractions.new(signer, deployment).isSome
test "can be instantiated with a provider url and account": test "can be instantiated with a provider url":
let url = "http://localhost:8545" let url = "http://localhost:8545"
let account = Address.example let account = Address.example
let deployment = "vendor" / "dagger-contracts" / "deployment-localhost.json" let deployment = "vendor" / "dagger-contracts" / "deployment-localhost.json"
check ContractInteractions.new(url).isSome check ContractInteractions.new(url, account).isSome
check ContractInteractions.new(url, account = account).isSome check ContractInteractions.new(url, account, deployment).isSome
check ContractInteractions.new(url, deploymentFile = deployment).isSome
test "provides purchasing": test "provides purchasing":
check contracts.purchasing != nil check contracts.purchasing != nil

View File

@ -20,11 +20,13 @@ ethersuite "Integration tests":
node1 = startNode [ node1 = startNode [
"--api-port=8080", "--api-port=8080",
"--udp-port=8090", "--udp-port=8090",
"--persistence",
"--eth-account=" & $accounts[0] "--eth-account=" & $accounts[0]
] ]
node2 = startNode [ node2 = startNode [
"--api-port=8081", "--api-port=8081",
"--udp-port=8091", "--udp-port=8091",
"--persistence",
"--eth-account=" & $accounts[1] "--eth-account=" & $accounts[1]
] ]
baseurl1 = "http://localhost:8080/api/codex/v1" baseurl1 = "http://localhost:8080/api/codex/v1"