Hyperledger Burrow初體驗

環境

os:ubuntu18.04
burrow:v0.30.2
solc:0.6.3-develop
go:1.14

下載、編譯Burrow

git clone https://github.com/hyperledger/burrow.git
cd burrow
git checkout v0.30.2
make build
cp bin/burrow .

需要修改下Makefile才能編譯通過,部分代碼樣式有問題 check不能通過
build: check build_burrow 修改成 build: build_burrow

burrow子命令

❯ ./burrow --help

Usage: burrow [--version] [--directory=<working directory>] COMMAND [arg...]

The EVM smart contract machine with Tendermint consensus

Options:
  -v, --version     Print the Burrow version
  -C, --directory   Change directory before running

Commands:
  start             Start a Burrow node
  spec              Build a GenesisSpec that acts as a template for a GenesisDoc and the configure command
  configure         Create Burrow configuration by consuming a GenesisDoc or GenesisSpec, creating keys, and emitting the config
  keys              A tool for doing a bunch of cool stuff with keys
  explore           Dump objects from an offline Burrow .burrow directory
  deploy            Deploy and test contracts
  natives           Dump Solidity interface contracts for Burrow native contracts
  vent              Start the Vent EVM event and blocks consumer service to populated databases from smart contracts
  dump              Dump chain state to backup
  tx                Submit a transaction to a burrow node
  restore           Restore new chain from backup
  accounts          List accounts and metadata
  abi               List, decode and encode using ABI

生成配置

./burrow spec -p1 -f1 | ./burrow configure -s- > burrow.toml

相當於

./burrow spec --participant-accounts=1 --full-accounts=1 > genesis-spec.json
./burrow configure --genesis-spec=genesis-spec.json > burrow.toml

–participant-accounts=1=>p1
–full-accounts=1=>f1

burrow.toml

BurrowDir = ".burrow"

[GenesisDoc]
  GenesisTime = 2020-04-01T01:43:22Z
  ChainName = "BurrowChain_FAB3C1"
  [GenesisDoc.Params]
    ProposalThreshold = 3
  [GenesisDoc.GlobalPermissions]
    [GenesisDoc.GlobalPermissions.Base]
      Perms = "send | call | createContract | createAccount | bond | name | proposal | input | batch | hasBase | hasRole"
      SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Accounts]]
    Address = "36B2954A8683E779B0B719E24327FD0B0ADCB004"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"A0BBD9E544023C67C4B02F9A41A3F4F36490848221F5508C7D3B4187A81AF37A\"}"
    Amount = 99999999999999
    Name = "Full_0"
    [GenesisDoc.Accounts.Permissions]
      [GenesisDoc.Accounts.Permissions.Base]
        Perms = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"
        SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Accounts]]
    Address = "3123B63BF27A838CE693CADE22485049C2CCD6AA"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"957B6147025782295EEB3DE1935089C54B2A0A04DDABBD69049BF678ED5BA784\"}"
    Amount = 9999999999
    Name = "Participant_0"
    [GenesisDoc.Accounts.Permissions]
      [GenesisDoc.Accounts.Permissions.Base]
        Perms = "send | call | name | proposal | input | hasRole"
        SetBit = "send | call | name | proposal | input | hasRole"

  [[GenesisDoc.Validators]]
    Address = "36B2954A8683E779B0B719E24327FD0B0ADCB004"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"A0BBD9E544023C67C4B02F9A41A3F4F36490848221F5508C7D3B4187A81AF37A\"}"
    Amount = 9999999999
    Name = "Full_0"

    [[GenesisDoc.Validators.UnbondTo]]
      Address = "36B2954A8683E779B0B719E24327FD0B0ADCB004"
      PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"A0BBD9E544023C67C4B02F9A41A3F4F36490848221F5508C7D3B4187A81AF37A\"}"
      Amount = 9999999999

[Tendermint]
  Enabled = true
  Seeds = ""
  SeedMode = false
  PersistentPeers = ""
  ListenHost = "0.0.0.0"
  ListenPort = "26656"
  ExternalAddress = ""
  AddrBookStrict = false
  Moniker = ""
  IdentifyPeers = false
  AuthorizedPeers = ""
  CreateEmptyBlocks = "5m"

[Execution]
  TimeoutFactor = 0.33
  CallStackMaxDepth = 0
  DataStackInitialCapacity = 1024
  DataStackMaxDepth = 0

[Keys]
  GRPCServiceEnabled = true
  AllowBadFilePermissions = false
  RemoteAddress = ""
  KeysDirectory = ".keys"

[RPC]
  [RPC.Info]
    Enabled = true
    ListenHost = "0.0.0.0"
    ListenPort = "26658"
  [RPC.Profiler]
    Enabled = false
    ListenHost = "0.0.0.0"
    ListenPort = "6060"
  [RPC.GRPC]
    Enabled = true
    ListenHost = "0.0.0.0"
    ListenPort = "10997"
  [RPC.Metrics]
    Enabled = false
    ListenHost = "0.0.0.0"
    ListenPort = "9102"
    MetricsPath = "/metrics"
    BlockSampleSize = 100
  [RPC.Web3]
    Enabled = true
    ListenHost = "0.0.0.0"
    ListenPort = "26660"

[Logging]
  Trace = false
  NonBlocking = false
  [Logging.RootSink]
    [Logging.RootSink.Output]
      OutputType = "stdout"
      Format = "json"

啓動Burrow

需要制定驗證者,可以是序號(burrow.toml配置文件的validator),也可以是驗證者address

nohup ./burrow start --validator=0  >burrow.log 2>&1 &

數據目錄

❯ tree .burrow/
.burrow/
├── burrow_state.db
│   ├── 000001.log
│   ├── CURRENT
│   ├── LOCK
│   ├── LOG
│   └── MANIFEST-000000
├── config
│   ├── addrbook.json
│   └── node_key.json
└── data
    ├── blockstore.db
    │   ├── 000001.log
    │   ├── CURRENT
    │   ├── LOCK
    │   ├── LOG
    │   └── MANIFEST-000000
    ├── cs.wal
    │   └── wal
    ├── evidence.db
    │   ├── 000001.log
    │   ├── CURRENT
    │   ├── LOCK
    │   ├── LOG
    │   └── MANIFEST-000000
    └── state.db
        ├── 000001.log
        ├── CURRENT
        ├── LOCK
        ├── LOG
        └── MANIFEST-000000

交易

SENDER=36B2954A8683E779B0B719E24327FD0B0ADCB004
RECIPIENT=3123B63BF27A838CE693CADE22485049C2CCD6AA
AMOUNT=10
./burrow tx formulate send -s $SENDER -t $RECIPIENT -a $AMOUNT > tx.json

生成的配置tx.json

{
  "SendTx": {
    "Inputs": [
      {
        "Address": "36B2954A8683E779B0B719E24327FD0B0ADCB004",
        "Amount": 10
      }
    ],
    "Outputs": [
      {
        "Address": "3123B63BF27A838CE693CADE22485049C2CCD6AA",
        "Amount": 10
      }
    ]
  }
}

提交交易,會返回交易的hash

./burrow tx commit --file tx.json
B19F0824DECBDD2FEE43CB31438FA744A54F4EDEB81A1C856666EF44046C6AC7

再看看日誌,有記錄這筆交易

{"caller":"execution.go:228","component":"Executor","height":1,"log_channel":"Info","message":"Executing transaction","run_call":false,"run_id":"b93fc996-73bc-11ea-891b-c683e38da786","scope":"executor.Execute(tx txs.Tx)","time":"2020-04-01T02:02:51.254874625Z","tx":"TxEnvelope{Signatures: 1, Tx: Tx{ChainID: BurrowChain_FAB3C1-CC46B1; TxHash: B19F0824DECBDD2FEE43CB31438FA744A54F4EDEB81A1C856666EF44046C6AC7; Payload: {\"ChainID\":\"BurrowChain_FAB3C1-CC46B1\",\"Type\":\"SendTx\",\"Payload\":{\"Inputs\":[{\"Address\":\"36B2954A8683E779B0B719E24327FD0B0ADCB004\",\"Amount\":10,\"Sequence\":1}],\"Outputs\":[{\"Address\":\"3123B63BF27A838CE693CADE22485049C2CCD6AA\",\"Amount\":10}]}}}}","tx_hash":"B19F0824DECBDD2FEE43CB31438FA744A54F4EDEB81A1C856666EF44046C6AC7"}
{"ExecuteTx":"tx_hash:B19F0824DECBDD2FEE43CB31438FA744A54F4EDEB81A1C856666EF44046C6AC7","caller":"app.go:195","component":"ABCI_App","height":1,"log_channel":"Info","message":"Execution success","node_info":"Burrow_0.30.2_BurrowChain_FAB3C1-CC46B1_ValidatorID:36B2954A8683E779B0B719E24327FD0B0ADCB004","run_id":"b93fc996-73bc-11ea-891b-c683e38da786","scope":"abci.NewApp","time":"2020-04-01T02:02:51.255223345Z"}
{"caller":"execution.go:228","component":"Executor","height":2,"log_channel":"Info","message":"Executing transaction","run_call":true,"run_id":"b93fc996-73bc-11ea-891b-c683e38da786","scope":"executor.Execute(tx txs.Tx)","time":"2020-04-01T02:02:51.267540673Z","tx":"TxEnvelope{Signatures: 1, Tx: Tx{ChainID: BurrowChain_FAB3C1-CC46B1; TxHash: B19F0824DECBDD2FEE43CB31438FA744A54F4EDEB81A1C856666EF44046C6AC7; Payload: {\"ChainID\":\"BurrowChain_FAB3C1-CC46B1\",\"Type\":\"SendTx\",\"Payload\":{\"Inputs\":[{\"Address\":\"36B2954A8683E779B0B719E24327FD0B0ADCB004\",\"Amount\":10,\"Sequence\":1}],\"Outputs\":[{\"Address\":\"3123B63BF27A838CE693CADE22485049C2CCD6AA\",\"Amount\":10}]}}}}","tx_hash":"B19F0824DECBDD2FEE43CB31438FA744A54F4EDEB81A1C856666EF44046C6AC7"}
{"ExecuteTx":"tx_hash:B19F0824DECBDD2FEE43CB31438FA744A54F4EDEB81A1C856666EF44046C6AC7","caller":"app.go:218","component":"ABCI_App","height":1,"log_channel":"Info","message":"Execution success","node_info":"Burrow_0.30.2_BurrowChain_FAB3C1-CC46B1_ValidatorID:36B2954A8683E779B0B719E24327FD0B0ADCB004","run_id":"b93fc996-73bc-11ea-891b-c683e38da786","scope":"abci.NewApp","time":"2020-04-01T02:02:51.267838691Z"}

智能合約

這裏要測試的合約可以在這裏找到:https://github.com/hyperledger/burrow/tree/v0.30.2/tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked

合約主要是定義了一下幾個變量:

  bool storedBool;
  bool storedBool2;
  int storedInt;
  uint storedUint;
  address storedAddress;
  bytes32 storedBytes;
  string storedString;

執行一組job,相對應的是調用這些變量的set、get方法。

先看看deploy怎麼用的。

❯ ./burrow deploy --help

Usage: burrow deploy [--chain=<host:port>] [--keys=<host:port>] [--mempool-signing] [--dir=<root directory>] [--output=<output file>] [--wasm] [--set=<KEY=VALUE>]... [--bin-path=<path>] [--gas=<gas>] [--jobs=<concurrent playbooks>] [--address=<address>] [--fee=<fee>] [--amount=<amount>] [--local-abi] [--verbose] [--debug] [--timeout=<timeout>] [--list-proposals=<state> | --proposal-create| --proposal-verify | --proposal-vote] [FILE...]

Deploy and test contracts

Arguments:
  FILE                    path to playbook file which deploy should run. if also using the --dir flag, give the relative path to playbooks file, which should be in the same directory

Options:
  -c, --chain             chain to be used in IP:PORT format (default "127.0.0.1:10997")
  -s, --keys              IP:PORT of Burrow GRPC service which jobs should or otherwise transaction submitted unsigned for mempool signing in Burrow
  -p, --mempool-signing   Use Burrow's own keys connection to sign transactions - means that Burrow instance must have access to input account keys. Sequence numbers are set as transactions enter the mempool so concurrent transactions can be sent from same inputs.
  -i, --dir               root directory of app (will use pwd by default)
  -o, --output            filename for playbook output file. by default, this name will reflect the playbook passed (default "deploy.output.json")
  -e, --set               default sets to use; operates the same way as the [set] jobs, only before the jobs file is ran (and after default address
  -b, --bin-path          path to the bin directory jobs should use when saving binaries after the compile process defaults to --dir + /bin (default "[dir]/bin")
  -g, --gas               default gas to use; can be overridden for any single job (default "1111111111")
  -j, --jobs              default number of concurrent playbooks to run if multiple are specified (default 1)
  -a, --address           default address (or account name) to use; operates the same way as the [account] job, only before the deploy file is ran
  -n, --fee               default fee to use (default "9999")
  -m, --amount            default amount to use (default "9999")
  -v, --verbose           verbose output
      --local-abi         use local ABIs rather than fetching them from burrow
      --wasm              Compile to WASM using solang (experimental)
  -d, --debug             debug level output
      --proposal-verify   Verify any proposal, do NOT create new proposal or vote
      --proposal-vote     Vote for proposal, do NOT create new proposal
      --proposal-create   Create new proposal
  -t, --timeout           Timeout to talk to the chain in seconds (default 15)
      --list-proposals    List proposals, either all, executed, expired, or current

ADDRESS 替換成toml文件中GenesisDoc.Accounts中的ADDRESS,然後指定deploy.yaml

ADDRESS=7CEDE838329CDE8C8302AC31EEBAF0EEA4BE61E5
./burrow deploy --address $ADDRESS  tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked/deploy.yaml

執行後,報錯了,缺少solc,編譯智能合約需要用到這個程序

log_channel=Info message="Using chain" Chain=127.0.0.1:10997 Signer=
log_channel=Info message="Loading Playbook File."
log_channel=Info message="Loading playbook file" path=/root/burrow/tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked filename=/root/burrow/tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked/deploy.yaml
log_channel=Info message="*****Executing Job*****" JobName=defaultAddr Type=Account
log_channel=Info message="Setting Account" account=7CEDE838329CDE8C8302AC31EEBAF0EEA4BE61E5
log_channel=Info message="*****Executing Job*****" JobName=deployStorageK Type=Deploy
log_channel=Info message="Contract path" path=storage.sol
ERROR: exec: "solc": executable file not found in $PATHlog_channel=Info message="JOBS THAT FAILED" count=1
log_channel=Info message="Playbook result" jobNo=0 file=tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked/deploy.yaml error="exec: \"solc\": executable file not found in $PATH" time=3.589948ms

安裝一下solc

sudo add-apt-repository ppa:ethereum/ethereum
sudo add-apt-repository ppa:ethereum/ethereum-dev
sudo apt-get update
sudo apt-get install solc

再部署

./burrow deploy  --address $ADDRESS  tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked/deploy.yaml
log_channel=Info message="Using chain" Chain=127.0.0.1:10997 Signer=
log_channel=Info message="Loading Playbook File."
log_channel=Info message="Loading playbook file" path=/root/burrow/tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked filename=/root/burrow/tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked/deploy.yaml
log_channel=Info message="*****Executing Job*****" JobName=defaultAddr Type=Account
log_channel=Info message="Setting Account" account=7CEDE838329CDE8C8302AC31EEBAF0EEA4BE61E5
log_channel=Info message="*****Executing Job*****" JobName=deployStorageK Type=Deploy
log_channel=Info message="Contract path" path=storage.sol
log_channel=Info message="Warning during contract compilation" warning="Warning: This is a pre-release compiler version, please do not use it in production.\n"
log_channel=Info message="Saving Binary" contract=SimpleStorage
log_channel=Info message="Using mempool signing since no keyClient set, pass --keys to sign locally or elsewhere"
log_channel=Info message="Using mempool signing"
log_channel=Info message="Tx Return" addr=1E9CCAF198E8CF52FBA313A9F9525BC90D465221 TransactionHash=6fd94cde40379f6f53f2f0ba7c8899ac9ad0d181bef91ed9d55ad6bc4676240c
log_channel=Info message="*****Executing Job*****" JobName=setStorageBaseBool Type=Set
log_channel=Info message="Setting Variable" result=true
log_channel=Info message="*****Executing Job*****" JobName=setStorageBool Type=Call
log_channel=Info message="Function call to constant function, query-contract type job will be faster than call"
log_channel=Info message="Using mempool signing"
log_channel=Info message="No return result value"
log_channel=Info message="*****Executing Job*****" JobName=queryStorageBool Type=QueryContract
log_channel=Info message="Query contract" destination=1E9CCAF198E8CF52FBA313A9F9525BC90D465221 function=getBool data=<nil>
log_channel=Info message="Return Value" value=true
log_channel=Info message="Job Vars" name=retBool value=true
log_channel=Info message="*****Executing Job*****" JobName=assertStorageBool Type=Assert
log_channel=Info message=Assertion key=true relation=eq value=true
log_channel=Info message="Assertion Succeeded" operation="==" key=true value=true
log_channel=Info message="*****Executing Job*****" JobName=setStorageBool2 Type=Call
log_channel=Info message="Function call to constant function, query-contract type job will be faster than call"
log_channel=Info message="Using mempool signing"
log_channel=Info message="No return result value"
log_channel=Info message="*****Executing Job*****" JobName=queryStorageBool2 Type=QueryContract
log_channel=Info message="Query contract" destination=1E9CCAF198E8CF52FBA313A9F9525BC90D465221 function=getBool2 data=<nil>
log_channel=Info message="Return Value" value=true
log_channel=Info message="Job Vars" name=retBool value=true
log_channel=Info message="*****Executing Job*****" JobName=assertStorageBool2 Type=Assert
log_channel=Info message=Assertion key=true relation=eq value=true
log_channel=Info message="Assertion Succeeded" operation="==" key=true value=true
log_channel=Info message="*****Executing Job*****" JobName=setStorageBaseInt Type=Set
log_channel=Info message="Setting Variable" result=50000
log_channel=Info message="*****Executing Job*****" JobName=setStorageInt Type=Call
log_channel=Info message="Function call to constant function, query-contract type job will be faster than call"
log_channel=Info message="Using mempool signing"
log_channel=Info message="No return result value"
log_channel=Info message="*****Executing Job*****" JobName=queryStorageInt Type=QueryContract
log_channel=Info message="Query contract" destination=1E9CCAF198E8CF52FBA313A9F9525BC90D465221 function=getInt data=<nil>
log_channel=Info message="Return Value" value=50000
log_channel=Info message="Job Vars" name=retInt value=50000
log_channel=Info message="*****Executing Job*****" JobName=assertStorageInt Type=Assert
log_channel=Info message=Assertion key=50000 relation=eq value=50000
log_channel=Info message="Assertion Succeeded" operation="==" key=50000 value=50000
log_channel=Info message="*****Executing Job*****" JobName=setStorageBaseUint Type=Set
log_channel=Info message="Setting Variable" result=9999999
log_channel=Info message="*****Executing Job*****" JobName=setStorageUint Type=Call
log_channel=Info message="Function call to constant function, query-contract type job will be faster than call"
log_channel=Info message="Using mempool signing"
log_channel=Info message="No return result value"
log_channel=Info message="*****Executing Job*****" JobName=queryStorageUint Type=QueryContract
log_channel=Info message="Query contract" destination=1E9CCAF198E8CF52FBA313A9F9525BC90D465221 function=getUint data=<nil>
log_channel=Info message="Return Value" value=9999999
log_channel=Info message="Job Vars" name=retUint value=9999999
log_channel=Info message="*****Executing Job*****" JobName=assertStorageUint Type=Assert
log_channel=Info message=Assertion key=9999999 relation=eq value=9999999
log_channel=Info message="Assertion Succeeded" operation="==" key=9999999 value=9999999
log_channel=Info message="*****Executing Job*****" JobName=setStorageBaseAddress Type=Set
log_channel=Info message="Setting Variable" result=1040E6521541DAB4E7EE57F21226DD17CE9F0FB7
log_channel=Info message="*****Executing Job*****" JobName=setStorageAddress Type=Call
log_channel=Info message="Failed to encode abi spec" abi="{\"ContractName\":\"SimpleStorage\",\"SourceFile\":\"storage.sol\",\"CompilerVersion\":\"0.6.3-develop.2020.2.13+commit.c6353774\",\"Abi\":[{\"inputs\":[],\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"retAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"retBool\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBool2\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"retBool\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBytes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"retBytes\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInt\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"retInt\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getString\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"retString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"retUint\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"x\",\"type\":\"address\"}],\"name\":\"setAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"x\",\"type\":\"bool\"}],\"name\":\"setBool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"x\",\"type\":\"bool\"}],\"name\":\"setBool2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"}],\"name\":\"setBytes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"x\",\"type\":\"int256\"}],\"name\":\"setInt\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"x\",\"type\":\"string\"}],\"name\":\"setString\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"setUint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]}" error="cannot map from string to EVM address"
log_channel=Info message="Failed to encode abi spec" abi="[{\"inputs\":[],\"name\":\"getAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"retAddress\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBool\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"retBool\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBool2\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"retBool\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBytes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"retBytes\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInt\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"retInt\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getString\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"retString\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getUint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"retUint\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"x\",\"type\":\"address\"}],\"name\":\"setAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"x\",\"type\":\"bool\"}],\"name\":\"setBool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"x\",\"type\":\"bool\"}],\"name\":\"setBool2\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"x\",\"type\":\"bytes32\"}],\"name\":\"setBytes\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"x\",\"type\":\"int256\"}],\"name\":\"setInt\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"x\",\"type\":\"string\"}],\"name\":\"setString\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"}],\"name\":\"setUint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" error="cannot map from string to EVM address"
log_channel=Info message="ABI Error" data="unsupported value type" bin= dest=1E9CCAF198E8CF52FBA313A9F9525BC90D465221 rawErr="cannot map from string to EVM address"
ERROR:
There has been an error in finding or in using your ABI. ABI's are "Application Binary
Interface" and they are what let us know how to talk to smart contracts.

These little json files can be read by a variety of things which need to talk to smart
contracts so they are quite necessary to be able to find and use properly.

The ABIs are saved after the deploy events. So if there was a glitch in the matrix,
we apologize in advance.

The marmot recovery checklist is...
  * ensure your chain is running and you have enough validators online
  * ensure that your contracts successfully deployed
  * if you used imports or have multiple contracts in one file check the instance
    variable in the deploy and the abi variable in the call/query-contract
  * make sure you're calling or querying the right function
  * make sure you're using the correct variables for job results
log_channel=Info message="JOBS THAT FAILED" count=1
log_channel=Info message="Playbook result" jobNo=0 file=tests/jobs_fixtures/app06-deploy_basic_contract_and_different_solc_types_packed_unpacked/deploy.yaml error="\nThere has been an error in finding or in using your ABI. ABI's are \"Application Binary\nInterface\" and they are what let us know how to talk to smart contracts.\n\nThese little json files can be read by a variety of things which need to talk to smart\ncontracts so they are quite necessary to be able to find and use properly.\n\nThe ABIs are saved after the deploy events. So if there was a glitch in the matrix,\nwe apologize in advance.\n\nThe marmot recovery checklist is...\n  * ensure your chain is running and you have enough validators online\n  * ensure that your contracts successfully deployed\n  * if you used imports or have multiple contracts in one file check the instance\n    variable in the deploy and the abi variable in the call/query-contract\n  * make sure you're calling or querying the right function\n  * make sure you're using the correct variables for job results\n" time=1.400446723s

通過日誌觀察到已經部署成功了,而且還執行了很多Job,最後執行setStorageAddress的時候報錯。

執行出錯的job是這樣定義的

- name: setStorageBaseAddress
  set:
      val: "1040E6521541DAB4E7EE57F21226DD17CE9F0FB7"

- name: setStorageAddress
  call:
      destination: $deployStorageK
      function: setAddress 
      data:
        - $setStorageBaseAddress

錯誤信息是cannot map from string to EVM address,setStorageAddress方法接受的address類型的參數 ,而這裏給出的是string。
查了下是個bug:https://github.com/hyperledger/burrow/pull/1340

組建網絡

先殺掉我們上一步實驗啓動的burrow進程killall burrow,否則端口會起衝突

生成配置

執行下面的命令後,會生成兩個配置文件burrow000.toml、burrow001.toml。如果要生成3個節點的配置,則將-f2 修改爲 -f3 ,以此類推。

./burrow spec -f2|./burrow configure -s- --pool

burrow000.toml

ValidatorAddress = "74E0EBA611656F201DC1BF1A5FA695D12AC749E6"
BurrowDir = ".burrow000"

[GenesisDoc]
  GenesisTime = 2020-04-01T02:12:40Z
  ChainName = "BurrowChain_B8849F"
  [GenesisDoc.Params]
    ProposalThreshold = 3
  [GenesisDoc.GlobalPermissions]
    [GenesisDoc.GlobalPermissions.Base]
      Perms = "send | call | createContract | createAccount | bond | name | proposal | input | batch | hasBase | hasRole"
      SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Accounts]]
    Address = "74E0EBA611656F201DC1BF1A5FA695D12AC749E6"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"EA73778BD492EDBA48D9BF162A26C942D98B7ECB60FCDBC8D2ED7079E7D89859\"}"
    Amount = 99999999999999
    Name = "Full_0"
    [GenesisDoc.Accounts.Permissions]
      [GenesisDoc.Accounts.Permissions.Base]
        Perms = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"
        SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Accounts]]
    Address = "BFC51FC41F4550162E2FF355F571132D6213769C"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"16FB8331816E6C79447BE7C2BA0EEECEF2D6FE0597773AD4C8B21563DB94D668\"}"
    Amount = 99999999999999
    Name = "Full_1"
    [GenesisDoc.Accounts.Permissions]
      [GenesisDoc.Accounts.Permissions.Base]
        Perms = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"
        SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Validators]]
    Address = "74E0EBA611656F201DC1BF1A5FA695D12AC749E6"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"EA73778BD492EDBA48D9BF162A26C942D98B7ECB60FCDBC8D2ED7079E7D89859\"}"
    Amount = 9999999999
    Name = "Full_0"

    [[GenesisDoc.Validators.UnbondTo]]
      Address = "74E0EBA611656F201DC1BF1A5FA695D12AC749E6"
      PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"EA73778BD492EDBA48D9BF162A26C942D98B7ECB60FCDBC8D2ED7079E7D89859\"}"
      Amount = 9999999999

  [[GenesisDoc.Validators]]
    Address = "BFC51FC41F4550162E2FF355F571132D6213769C"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"16FB8331816E6C79447BE7C2BA0EEECEF2D6FE0597773AD4C8B21563DB94D668\"}"
    Amount = 9999999999
    Name = "Full_1"

    [[GenesisDoc.Validators.UnbondTo]]
      Address = "BFC51FC41F4550162E2FF355F571132D6213769C"
      PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"16FB8331816E6C79447BE7C2BA0EEECEF2D6FE0597773AD4C8B21563DB94D668\"}"
      Amount = 9999999999

[Tendermint]
  Enabled = true
  Seeds = ""
  SeedMode = false
  PersistentPeers = "tcp://[email protected]:26656,tcp://[email protected]:26657"
  ListenHost = "127.0.0.1"
  ListenPort = "26656"
  ExternalAddress = ""
  AddrBookStrict = false
  Moniker = "BurrowChain_FAB3C1-CC46B1_Node_36B2954A8683E779B0B719E24327FD0B0ADCB004"
  IdentifyPeers = false
  AuthorizedPeers = ""
  CreateEmptyBlocks = "5m"

[Execution]
  TimeoutFactor = 0.33
  CallStackMaxDepth = 0
  DataStackInitialCapacity = 1024
  DataStackMaxDepth = 0

[Keys]
  GRPCServiceEnabled = true
  AllowBadFilePermissions = false
  RemoteAddress = ""
  KeysDirectory = ".keys"

[RPC]
  [RPC.Info]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "26758"
  [RPC.Profiler]
    Enabled = false
    ListenHost = "0.0.0.0"
    ListenPort = "6060"
  [RPC.GRPC]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "10997"
  [RPC.Metrics]
    Enabled = false
    ListenHost = "127.0.0.1"
    ListenPort = "9102"
    MetricsPath = "/metrics"
    BlockSampleSize = 100
  [RPC.Web3]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "26860"

[Logging]
  Trace = false
  NonBlocking = false
  [Logging.RootSink]
    [Logging.RootSink.Output]
      OutputType = "file"
      Format = "json"
      Path = "burrow000.log"

burrow001.toml

ValidatorAddress = "BFC51FC41F4550162E2FF355F571132D6213769C"
BurrowDir = ".burrow001"

[GenesisDoc]
  GenesisTime = 2020-04-01T02:12:40Z
  ChainName = "BurrowChain_B8849F"
  [GenesisDoc.Params]
    ProposalThreshold = 3
  [GenesisDoc.GlobalPermissions]
    [GenesisDoc.GlobalPermissions.Base]
      Perms = "send | call | createContract | createAccount | bond | name | proposal | input | batch | hasBase | hasRole"
      SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Accounts]]
    Address = "74E0EBA611656F201DC1BF1A5FA695D12AC749E6"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"EA73778BD492EDBA48D9BF162A26C942D98B7ECB60FCDBC8D2ED7079E7D89859\"}"
    Amount = 99999999999999
    Name = "Full_0"
    [GenesisDoc.Accounts.Permissions]
      [GenesisDoc.Accounts.Permissions.Base]
        Perms = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"
        SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Accounts]]
    Address = "BFC51FC41F4550162E2FF355F571132D6213769C"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"16FB8331816E6C79447BE7C2BA0EEECEF2D6FE0597773AD4C8B21563DB94D668\"}"
    Amount = 99999999999999
    Name = "Full_1"
    [GenesisDoc.Accounts.Permissions]
      [GenesisDoc.Accounts.Permissions.Base]
        Perms = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"
        SetBit = "root | send | call | createContract | createAccount | bond | name | proposal | input | batch | identify | hasBase | setBase | unsetBase | setGlobal | hasRole | addRole | removeRole"

  [[GenesisDoc.Validators]]
    Address = "74E0EBA611656F201DC1BF1A5FA695D12AC749E6"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"EA73778BD492EDBA48D9BF162A26C942D98B7ECB60FCDBC8D2ED7079E7D89859\"}"
    Amount = 9999999999
    Name = "Full_0"

    [[GenesisDoc.Validators.UnbondTo]]
      Address = "74E0EBA611656F201DC1BF1A5FA695D12AC749E6"
      PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"EA73778BD492EDBA48D9BF162A26C942D98B7ECB60FCDBC8D2ED7079E7D89859\"}"
      Amount = 9999999999

  [[GenesisDoc.Validators]]
    Address = "BFC51FC41F4550162E2FF355F571132D6213769C"
    PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"16FB8331816E6C79447BE7C2BA0EEECEF2D6FE0597773AD4C8B21563DB94D668\"}"
    Amount = 9999999999
    Name = "Full_1"

    [[GenesisDoc.Validators.UnbondTo]]
      Address = "BFC51FC41F4550162E2FF355F571132D6213769C"
      PublicKey = "{\"CurveType\":\"ed25519\",\"PublicKey\":\"16FB8331816E6C79447BE7C2BA0EEECEF2D6FE0597773AD4C8B21563DB94D668\"}"
      Amount = 9999999999

[Tendermint]
  Enabled = true
  Seeds = ""
  SeedMode = false
  PersistentPeers = "tcp://[email protected]:26656,tcp://[email protected]:26657"
  ListenHost = "127.0.0.1"
  ListenPort = "26657"
  ExternalAddress = ""
  AddrBookStrict = false
  Moniker = "BurrowChain_FAB3C1-CC46B1_Node_36B2954A8683E779B0B719E24327FD0B0ADCB004"
  IdentifyPeers = false
  AuthorizedPeers = ""
  CreateEmptyBlocks = "5m"

[Execution]
  TimeoutFactor = 0.33
  CallStackMaxDepth = 0
  DataStackInitialCapacity = 1024
  DataStackMaxDepth = 0

[Keys]
  GRPCServiceEnabled = true
  AllowBadFilePermissions = false
  RemoteAddress = ""
  KeysDirectory = ".keys"

[RPC]
  [RPC.Info]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "26759"
  [RPC.Profiler]
    Enabled = false
    ListenHost = "0.0.0.0"
    ListenPort = "6060"
  [RPC.GRPC]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "10998"
  [RPC.Metrics]
    Enabled = false
    ListenHost = "127.0.0.1"
    ListenPort = "9103"
    MetricsPath = "/metrics"
    BlockSampleSize = 100
  [RPC.Web3]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "26861"

[Logging]
  Trace = false
  NonBlocking = false
  [Logging.RootSink]
    [Logging.RootSink.Output]
      OutputType = "file"
      Format = "json"
      Path = "burrow001.log"

啓動第一個節點

nohup ./burrow start --config=burrow000.toml >/dev/null 2>&1 &

啓動第二個節點

nohup ./burrow start --config=burrow001.toml >/dev/null 2>&1 &

檢查是否連接成功

curl -s 127.0.0.1:26758/consensus
curl -s 127.0.0.1:26759/consensus
curl -s 127.0.0.1:26759/consensus
{
  "jsonrpc": "2.0",
  "id": "",
  "result": {
    "round_state": {
      "height": "2",
      "round": "0",
      "step": 2,
      "start_time": "2020-04-01T02:21:10.589956473Z",
      "commit_time": "2020-04-01T02:21:10.259956473Z",
      "validators": {
        "validators": [
          {
            "address": "74E0EBA611656F201DC1BF1A5FA695D12AC749E6",
            "pub_key": {
              "type": "tendermint/PubKeyEd25519",
              "value": "6nN3i9SS7bpI2b8WKibJQtmLfstg/NvI0u1weefYmFk="
            },
            "voting_power": "9999999999",
            "proposer_priority": "0"
          },
          {
            "address": "BFC51FC41F4550162E2FF355F571132D6213769C",
            "pub_key": {
              "type": "tendermint/PubKeyEd25519",
              "value": "FvuDMYFubHlEe+fCug7uzvLW/gWXdzrUyLIVY9uU1mg="
            },
            "voting_power": "9999999999",
            "proposer_priority": "0"
          }
        ],
        "proposer": {
          "address": "BFC51FC41F4550162E2FF355F571132D6213769C",
          "pub_key": {
            "type": "tendermint/PubKeyEd25519",
            "value": "FvuDMYFubHlEe+fCug7uzvLW/gWXdzrUyLIVY9uU1mg="
          },
          "voting_power": "9999999999",
          "proposer_priority": "0"
        }
      },
      "proposal": null,
      "proposal_block": null,
      "proposal_block_parts": null,
      "locked_round": "-1",
      "locked_block": null,
      "locked_block_parts": null,
      "valid_round": "-1",
      "valid_block": null,
      "valid_block_parts": null,
      "votes": [
        {
          "round": "0",
          "prevotes": [
            "nil-Vote",
            "nil-Vote"
          ],
          "prevotes_bit_array": "BA{2:__} 0/19999999998 = 0.00",
          "precommits": [
            "nil-Vote",
            "nil-Vote"
          ],
          "precommits_bit_array": "BA{2:__} 0/19999999998 = 0.00"
        },
        {
          "round": "1",
          "prevotes": [
            "nil-Vote",
            "nil-Vote"
          ],
          "prevotes_bit_array": "BA{2:__} 0/19999999998 = 0.00",
          "precommits": [
            "nil-Vote",
            "nil-Vote"
          ],
          "precommits_bit_array": "BA{2:__} 0/19999999998 = 0.00"
        }
      ],
      "commit_round": "-1",
      "last_commit": {
        "votes": [
          "Vote{0:74E0EBA61165 1/00/2(Precommit) AC20689E6673 3F18B4554714 @ 2020-04-01T02:21:10.156997478Z}",
          "Vote{1:BFC51FC41F45 1/00/2(Precommit) AC20689E6673 EA6A5F6E53E0 @ 2020-04-01T02:21:09.951555109Z}"
        ],
        "votes_bit_array": "BA{2:xx} 19999999998/19999999998 = 1.00",
        "peer_maj_23s": {}
      },
      "last_validators": {
        "validators": [
          {
            "address": "74E0EBA611656F201DC1BF1A5FA695D12AC749E6",
            "pub_key": {
              "type": "tendermint/PubKeyEd25519",
              "value": "6nN3i9SS7bpI2b8WKibJQtmLfstg/NvI0u1weefYmFk="
            },
            "voting_power": "9999999999",
            "proposer_priority": "-9999999999"
          },
          {
            "address": "BFC51FC41F4550162E2FF355F571132D6213769C",
            "pub_key": {
              "type": "tendermint/PubKeyEd25519",
              "value": "FvuDMYFubHlEe+fCug7uzvLW/gWXdzrUyLIVY9uU1mg="
            },
            "voting_power": "9999999999",
            "proposer_priority": "9999999999"
          }
        ],
        "proposer": {
          "address": "74E0EBA611656F201DC1BF1A5FA695D12AC749E6",
          "pub_key": {
            "type": "tendermint/PubKeyEd25519",
            "value": "6nN3i9SS7bpI2b8WKibJQtmLfstg/NvI0u1weefYmFk="
          },
          "voting_power": "9999999999",
          "proposer_priority": "-9999999999"
        }
      },
      "triggered_timeout_precommit": false
    },
    "peers": [
      {
        "node_address": "dcee77e2804156971bab6f9ca741f3b14c8ed32b@[email protected]:26656",
        "peer_state": {
          "round_state": {
            "height": "2",
            "round": "0",
            "step": 1,
            "start_time": "2020-04-01T02:21:10.25925951Z",
            "proposal": false,
            "proposal_block_parts_header": {
              "total": "0",
              "hash": ""
            },
            "proposal_block_parts": null,
            "proposal_pol_round": "-1",
            "proposal_pol": "__",
            "prevotes": "__",
            "precommits": "__",
            "last_commit_round": "0",
            "last_commit": "xx",
            "catchup_commit_round": "-1",
            "catchup_commit": "__"
          },
          "stats": {
            "votes": "2",
            "block_parts": "1"
          }
        }
      }
    ]
  }
}#

交易注意事項

需要指定配置文件和驗證着

burrow tx -v0 -c burrow000.toml formulate send -s $SENDER -t $RECIPIENT -a $AMOUNT  > tx.json
burrow tx -v0 -c burrow000.toml commit --file tx.json
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章