burrow, deploy

It can be used to deploy and test smart contracts.

Arguments

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

Procedure

In Deploy.go

Deploy -> RunPlaybooks()  -> workers for cocurrent job execution -> submit playbook to workers
	for i := 1; i <= args.Jobs; i++ {
		go worker(workQ, resultQ, args, logger)
	}

	for i, playbook := range playbooks {
		workQ <- playbookWork{jobNo: i, playbook: playbook}
	}

worker


func worker(playbooks <-chan playbookWork, results chan<- playbookResult, args *def.DeployArgs, logger *logging.Logger) {

	client := def.NewClient(args.Chain, args.KeysService, args.MempoolSign, time.Duration(args.Timeout)*time.Second)

	for playbook := range playbooks {
		doWork := func(work playbookWork) (logBuf bytes.Buffer, err error) {
			// block that triggers if the do.Path was NOT set
			//   via cli flag... or not
			fname := filepath.Join(args.Path, work.playbook)

			// if YAMLPath cannot be found, abort
			if _, err := os.Stat(fname); os.IsNotExist(err) {
				return logBuf, fmt.Errorf("could not find playbook file (%s)",
					fname)
			}

			if args.Jobs != 1 {
				logger = logging.NewLogger(log.NewLogfmtLogger(&logBuf))
			}

			// Load the package if it doesn't exist
			script, err := loader.LoadPlaybook(fname, args, logger)
			if err != nil {
				return logBuf, err
			}

			// Load existing bin files to decode events
			var abiError error
			client.AllSpecs, abiError = abi.LoadPath(script.BinPath)
			if err != nil {
				logger.InfoMsg("failed to load ABIs for Event parsing", "path", script.BinPath, "error", abiError)
			}

			err = jobs.ExecutePlaybook(args, script, client, logger)
			return
		}

		startTime := time.Now()
		logBuf, err := doWork(playbook)
		results <- playbookResult{
			jobNo:    playbook.jobNo,
			log:      logBuf,
			err:      err,
			duration: time.Since(startTime),
		}
	}
}

  • load the playbook script which is the ‘deploy.yaml’
    • script decomposed to multiple jobs
  • load the abi.spec for event decoding
  • execute the playbook

doJobs

Finally jobs will be done by doJobs.

doJobs is an interpretor which aactually execute the script. In util.PreProcessFields(), the variables will be substituted by the result of the executed jobs, e.g., $setValue replaced by ‘5’.

call stack:

github.com/hyperledger/burrow/deploy/jobs.doJobs at job_manager.go:136
github.com/hyperledger/burrow/deploy/jobs.ExecutePlaybook at job_manager.go:332
github.com/hyperledger/burrow/deploy.worker.func1 at run_deploy.go:63
github.com/hyperledger/burrow/deploy.worker at run_deploy.go:68
runtime.goexit at asm_amd64.s:1357
 - Async stack trace
github.com/hyperledger/burrow/deploy.RunPlaybooks at run_deploy.go:97

func doJobs(playbook *def.Playbook, args *def.DeployArgs, client *def.Client, logger *logging.Logger) error {
	for _, job := range playbook.Jobs {
		payload, err := job.Payload()
		if err != nil {
			return fmt.Errorf("could not get Job payload: %v", payload)
		}

		err = util.PreProcessFields(payload, args, playbook, client, logger)
		if err != nil {
			return err
		}
		// Revalidate with possible replacements
		err = payload.Validate()
		if err != nil {
			return fmt.Errorf("error validating job %s after pre-processing variables: %v", job.Name, err)
		}

		switch payload.(type) {
		case *def.Proposal:
			announce(job.Name, "Proposal", logger)
			job.Result, err = ProposalJob(job.Proposal, args, playbook, client, logger)

		// Meta Job
		case *def.Meta:
			announce(job.Name, "Meta", logger)
			metaPlaybook := job.Meta.Playbook
			if metaPlaybook.Account == "" {
				metaPlaybook.Account = playbook.Account
			}
			err = doJobs(metaPlaybook, args, client, logger)

		// Governance
		case *def.UpdateAccount:
			announce(job.Name, "UpdateAccount", logger)
			var tx *pbpayload.GovTx
			tx, job.Variables, err = FormulateUpdateAccountJob(job.UpdateAccount, playbook.Account, client, logger)
			if err != nil {
				return err
			}
			err = UpdateAccountJob(job.UpdateAccount, playbook.Account, tx, client, logger)

		// Util jobs
		case *def.Account:
			announce(job.Name, "Account", logger)
			job.Result, err = SetAccountJob(job.Account, args, playbook, logger)
		case *def.Set:
			announce(job.Name, "Set", logger)
			job.Result, err = SetValJob(job.Set, args, logger)

		// Transaction jobs
		case *def.Send:
			announce(job.Name, "Send", logger)
			tx, err := FormulateSendJob(job.Send, playbook.Account, client, logger)
			if err != nil {
				return err
			}
			job.Result, err = SendJob(job.Send, tx, playbook.Account, client, logger)
			if err != nil {
				return err
			}
		case *def.Bond:
			announce(job.Name, "Bond", logger)
			tx, err := FormulateBondJob(job.Bond, playbook.Account, client, logger)
			if err != nil {
				return err
			}
			job.Result, err = BondJob(job.Bond, tx, playbook.Account, client, logger)
			if err != nil {
				return err
			}
		case *def.Unbond:
			announce(job.Name, "Unbond", logger)
			tx, err := FormulateUnbondJob(job.Unbond, playbook.Account, client, logger)
			if err != nil {
				return err
			}
			job.Result, err = UnbondJob(job.Unbond, tx, playbook.Account, client, logger)
			if err != nil {
				return err
			}
		case *def.RegisterName:
			announce(job.Name, "RegisterName", logger)
			txs, err := FormulateRegisterNameJob(job.RegisterName, args, playbook, client, logger)
			if err != nil {
				return err
			}
			job.Result, err = RegisterNameJob(job.RegisterName, args, playbook, txs, client, logger)
			if err != nil {
				return err
			}
		case *def.Permission:
			announce(job.Name, "Permission", logger)
			tx, err := FormulatePermissionJob(job.Permission, playbook.Account, client, logger)
			if err != nil {
				return err
			}
			job.Result, err = PermissionJob(job.Permission, playbook.Account, tx, client, logger)
			if err != nil {
				return err
			}
		case *def.Identify:
			announce(job.Name, "Identify", logger)
			tx, err := FormulateIdentifyJob(job.Identify, playbook.Account, client, logger)
			if err != nil {
				return err
			}
			job.Result, err = IdentifyJob(job.Identify, tx, playbook.Account, client, logger)
			if err != nil {
				return err
			}

		// Contracts jobs
		case *def.Deploy:
			announce(job.Name, "Deploy", logger)
			txs, contracts, ferr := FormulateDeployJob(job.Deploy, args, playbook, client, job.Intermediate, logger)
			if ferr != nil {
				return ferr
			}
			job.Result, err = DeployJob(job.Deploy, args, playbook, client, txs, contracts, logger)

		case *def.Call:
			announce(job.Name, "Call", logger)
			CallTx, ferr := FormulateCallJob(job.Call, args, playbook, client, logger)
			if ferr != nil {
				return ferr
			}
			job.Result, job.Variables, err = CallJob(job.Call, CallTx, args, playbook, client, logger)
		case *def.Build:
			announce(job.Name, "Build", logger)
			var resp *compilers.Response
			resp, err = getCompilerWork(job.Intermediate)
			if err != nil {
				return err
			}
			job.Result, err = BuildJob(job.Build, playbook, resp, logger)

		// State jobs
		case *def.RestoreState:
			announce(job.Name, "RestoreState", logger)
			job.Result, err = RestoreStateJob(job.RestoreState)
		case *def.DumpState:
			announce(job.Name, "DumpState", logger)
			job.Result, err = DumpStateJob(job.DumpState)

		// Test jobs
		case *def.QueryAccount:
			announce(job.Name, "QueryAccount", logger)
			job.Result, err = QueryAccountJob(job.QueryAccount, client, logger)
		case *def.QueryContract:
			announce(job.Name, "QueryContract", logger)
			job.Result, job.Variables, err = QueryContractJob(job.QueryContract, args, playbook, client, logger)
		case *def.QueryName:
			announce(job.Name, "QueryName", logger)
			job.Result, err = QueryNameJob(job.QueryName, client, logger)
		case *def.QueryVals:
			announce(job.Name, "QueryVals", logger)
			job.Result, err = QueryValsJob(job.QueryVals, client, logger)
		case *def.Assert:
			announce(job.Name, "Assert", logger)
			job.Result, err = AssertJob(job.Assert, logger)

		default:
			logger.InfoMsg("Error")
			return fmt.Errorf("the Job specified in deploy.yaml and parsed as '%v' is not recognised as a valid job",
				job)
		}

		if len(job.Variables) != 0 {
			for _, theJob := range job.Variables {
				logger.InfoMsg("Job Vars", "name", theJob.Name, "value", theJob.Value)
			}
		}

		if err != nil {
			return err
		}
	}

	return nil
}

Jobs with underlying RPC:

JobInterface.MethodRPC
ProposalqueryClient.GetProposal/rpcquery.Query/GetProposal
UpdateAccounttransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
SendtransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
BondtransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
UnbondtransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
RegisterNametransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
PermissiontransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
IdentifytransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
DeploytransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
CalltransactClient.BroadcastTxSync/rpctransact.Transact/BroadcastTxSync
QueryAccountqueryClient.GetAccount/rpcquery.Query/GetAccount
QueryContracttransactClient.CallTxSim/rpctransact.Transact/CallTxSim
QueryNamequeryClient.GetName/rpcquery.Query/GetName
QueryVals/rpcquery.Query/GetValidatorSetqueryClient.GetValidatorSet

Call vs. QueryContract

The call and query contract job is for executing contract code by way of running one of the functions. The call job will create a transaction and will have to wait until the next block to retrieve the result; the query-contract job is for accessing read-only functions which do not require write access.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1444. Elephpotamus Time limit: 0.5 second Memory limit: 64 MB Harry Potter is taking an examination in Care for Magical Creatures. His task is to feed a dwarf elephpotamus. Harry remembers that elephpotamuses are very straightforward and imperturbable. In fact, they are so straightforward that always move along a straight line and they are so imperturbable that only move when attracted by something really tasty. In addition, if an elephpotamus stumbles into a chain of its own footprints, it falls into a stupor and refuses to go anywhere. According to Hagrid, elephpotamuses usually get back home moving along their footprints. This is why they never cross them, otherwise they may get lost. When an elephpotamus sees its footprints, it tries to remember in detail all its movements since leaving home (this is also the reason why they move along straight lines only, this way it is easier to memorize). Basing on this information, the animal calculates in which direction its burrow is situated, then turns and goes straight to it. It takes some (rather large) time for an elephpotamus to perform these calculations. And what some ignoramuses recognize as a stupor is in fact a demonstration of outstanding calculating abilities of this wonderful, though a bit slow-witted creature. Elephpotamuses' favorite dainty is elephant pumpkins, and some of such pumpkins grow on the lawn where Harry is to take his exam. At the start of the exam, Hagrid will drag the elephpotamus to one of the pumpkins. Having fed the animal with a pumpkin, Harry can direct it to any of the remaining pumpkins. In order to pass the exam, Harry must lead the elephpotamus so that it eats as many pumpkins as possible before it comes across its footprints. Input The first input line contains the number of pumpkins on the lawn N (3 ≤ N ≤ 30000). The pumpkins are numbered from 1 to N, the number one being assigned to the pumpkin to which the animal is brought at the start of the trial. In the next N lines, the coordinates of the pumpkins are given in the order corresponding to their numbers. All the coordinates are integers in the range from −1000 to 1000. It is guaranteed that there are no two pumpkins at the same location and there is no straight line passing through all the pumpkins. Output In the first line write the maximal number K of pumpkins that can be fed to the elephpotamus. In the next K lines, output the order in which the animal will eat them, giving one number in a line. The first number in this sequence must always be 1.写一段Java完成此目的
最新发布
06-03

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值