burrow abi overview

This blob is focus on the generate, encode and storage of abi. If you want to know more about abi, you can refer solidity abi spec

abi

burrow contract invoke process
The chart above show the rule of abi in a process of contract invoke.

show

json
type specJSON struct {
	Name            string
	Type            string
	Inputs          []argumentJSON
	Outputs         []argumentJSON
	Constant        bool
	Payable         bool
	StateMutability string
	Anonymous       bool
}

// function input/output argument
type argumentJSON struct {
	Name       string
	Type       string
	Components []argumentJSON
	Indexed    bool
}

example

part abi of storage.sol

[{
	"constant": true,
	"inputs": [],
	"name": "getAddress",
	"outputs": [{
		"internalType": "address",
		"name": "retAddress",
		"type": "address"
	}],
	"payable": false,
	"stateMutability": "view",
	"type": "function"
}, {
	"constant": false,
	"inputs": [{
		"internalType": "address",
		"name": "x",
		"type": "address"
	}],
	"name": "setAddress",
	"outputs": [],
	"payable": false,
	"stateMutability": "nonpayable",
	"type": "function"
}]
go structure
// Spec is the ABI for contract decoded.
type Spec struct {
	Constructor  *FunctionSpec
	Fallback     *FunctionSpec
	Functions    map[string]*FunctionSpec
	EventsByName map[string]*EventSpec
	EventsByID   map[EventID]*EventSpec
}

// function spec
type FunctionSpec struct {
	Name       string
	FunctionID FunctionID
	Constant   bool
	Inputs     []Argument
	Outputs    []Argument
}

// event spec
type EventSpec struct {
	ID        EventID
	Inputs    []Argument
	Name      string
	Anonymous bool
}

generate

Abi is auto generated after compile, Of course, you can also write your abi file by hand.

The code below show respones of compiler, Abi is located in resp.Objects[].Contract.Abi and Contract.MetadataMap[].Metadata.Abi, which the latter is stored in blockchain.

type Response struct {
	Objects []ResponseItem `json:"objects"`
	Warning string         `json:"warning"`
	Version string         `json:"version"`
	Error   string         `json:"error"`
}

// Compile response object
type ResponseItem struct {
	Filename   string           `json:"filename"`
	Objectname string           `json:"objectname"`
	Contract   SolidityContract `json:"binary"`
}

// SolidityContract is defined for each contract defined in the solidity source code
type SolidityContract struct {
	Abi json.RawMessage
	Evm struct {
		Bytecode         ContractCode
		DeployedBytecode ContractCode
	}
	EWasm struct {
		Wasm string
	}
	Devdoc   json.RawMessage
	Userdoc  json.RawMessage
	Metadata string
	// This is not present in the solidity output, but we add it ourselves
	// This is map from DeployedBytecode to Metadata. A Solidity contract can create any number
	// of contracts, which have distinct metadata. This is a map for the deployed code to metdata,
	// including the first contract itself.
	MetadataMap []MetadataMap `json:",omitempty"`
}

type Metadata struct {
	ContractName    string
	SourceFile      string
	CompilerVersion string
	Abi             json.RawMessage
}

type MetadataMap struct {
	DeployedBytecode ContractCode
	Metadata         Metadata
}

encode

To construct a tx, we should encode invocation args.
First of all, we should know data type which encode from and to.
From type is implemented via reflect; To type is retrieved from contract abi.

setStorageAddress call stack

github.com/hyperledger/burrow/execution/evm/abi.EVMAddress.pack at primitives.go:536
<autogenerated>:2
github.com/hyperledger/burrow/execution/evm/abi.pack.func1 at packing.go:185
github.com/hyperledger/burrow/execution/evm/abi.pack at packing.go:240
github.com/hyperledger/burrow/execution/evm/abi.Pack at packing.go:16
github.com/hyperledger/burrow/execution/evm/abi.(*Spec).Pack at spec.go:157
github.com/hyperledger/burrow/execution/evm/abi.EncodeFunctionCall at abi.go:97
github.com/hyperledger/burrow/deploy/jobs.FormulateCallJob at jobs_contracts.go:456
github.com/hyperledger/burrow/deploy/jobs.doJobs at job_manager.go:241
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
EVMType

Each data type is packed respectively, their pack func is defined in EVMType.pack.
Now there is 7 kinds of types.

type EVMType interface {
	GetSignature() string
	getGoType() interface{}
	pack(v interface{}) ([]byte, error)
	unpack(data []byte, offset int, v interface{}) (int, error)
	Dynamic() bool
	ImplicitCast(o EVMType) bool
}

implement

EVMInt
EVMUint
EVMBool
EVMString
EVMBytes
EVMFixed
EVMAddress

delivery

Metadata of contract is delivery to calltx.ContractMeta and then send tx to full node.

// A instruction to run smart contract code in the EVM
type CallTx struct {
	// The caller's input
	Input *TxInput `protobuf:"bytes,1,opt,name=Input,proto3" json:"Input,omitempty"`
	// The contract address to call or nil if we are creating a contract
	Address *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,2,opt,name=Address,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:"Address,omitempty"`
	// The upper bound on the amount of gas (and therefore EVM execution steps) this CallTx may generate
	GasLimit uint64 `protobuf:"varint,3,opt,name=GasLimit,proto3" json:"GasLimit,omitempty"`
	// Fee to offer validators for processing transaction
	Fee uint64 `protobuf:"varint,4,opt,name=Fee,proto3" json:"Fee,omitempty"`
	// EVM bytecode
	Data github_com_hyperledger_burrow_binary.HexBytes `protobuf:"bytes,5,opt,name=Data,proto3,customtype=github.com/hyperledger/burrow/binary.HexBytes" json:"Data"`
	// WASM bytecode
	WASM github_com_hyperledger_burrow_binary.HexBytes `protobuf:"bytes,6,opt,name=WASM,proto3,customtype=github.com/hyperledger/burrow/binary.HexBytes" json:"tags,omitempty"`
	// Set of contracts this code will deploy
	ContractMeta []*ContractMeta `protobuf:"bytes,7,rep,name=ContractMeta,proto3" json:"ContractMeta,omitempty"`
	// The upper bound on the price per unit of gas
	GasPrice             uint64   `protobuf:"varint,8,opt,name=GasPrice,proto3" json:"GasPrice,omitempty"`
}

type ContractMeta struct {
	CodeHash             github_com_hyperledger_burrow_binary.HexBytes `protobuf:"bytes,1,opt,name=CodeHash,proto3,customtype=github.com/hyperledger/burrow/binary.HexBytes" json:"CodeHash"`
	Meta                 string                                        `protobuf:"bytes,2,opt,name=Meta,proto3" json:"Meta,omitempty"`
}

backen store

If the metadata is already memoised, it was stored in account.ContractMeta.Metadata. Otherwise, it was stored in leveldb.

type Account struct {
	Address   github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,1,opt,name=Address,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:"Address"`
	PublicKey crypto.PublicKey                             `protobuf:"bytes,2,opt,name=PublicKey,proto3" json:"PublicKey"`
	// Sequence counts the number of transactions that have been accepted from this account
	Sequence uint64 `protobuf:"varint,3,opt,name=Sequence,proto3" json:"Sequence,omitempty"`
	// The account's current native token balance
	Balance uint64 `protobuf:"varint,4,opt,name=Balance,proto3" json:"Balance,omitempty"`
	// We expect exactly one of EVMCode, WASMCode, and NativeName to be non-empty
	// EVM bytecode
	EVMCode     Bytecode                      `protobuf:"bytes,5,opt,name=EVMCode,proto3,customtype=Bytecode" json:"EVMCode"`
	Permissions permission.AccountPermissions `protobuf:"bytes,6,opt,name=Permissions,proto3" json:"Permissions"`
	// WASM bytecode
	WASMCode Bytecode `protobuf:"bytes,7,opt,name=WASMCode,proto3,customtype=Bytecode" json:",omitempty"`
	// Fully qualified (`<contract name>.<function name>`) name of native contract this for which this account object
	// is a sentinel value. Which is to say this account object is a pointer to compiled code and does not contain
	// the contract logic in its entirety
	NativeName string `protobuf:"bytes,11,opt,name=NativeName,proto3" json:",omitempty"`
	// The sha3 hash of the code associated with the account
	CodeHash github_com_hyperledger_burrow_binary.HexBytes `protobuf:"bytes,8,opt,name=CodeHash,proto3,customtype=github.com/hyperledger/burrow/binary.HexBytes" json:"-"`
	// Pointer to the Metadata associated with this account
	ContractMeta []*ContractMeta `protobuf:"bytes,9,rep,name=ContractMeta,proto3" json:"ContractMeta,omitempty"`
	// The metadata is stored in the deployed account. When the deployed account creates new account
	// (from Solidity/EVM), they point to the original deployed account where the metadata is stored.
	// This original account is called the forebear.
	Forebear             *github_com_hyperledger_burrow_crypto.Address `protobuf:"bytes,10,opt,name=Forebear,proto3,customtype=github.com/hyperledger/burrow/crypto.Address" json:"Forebear,omitempty"`
	XXX_NoUnkeyedLiteral struct{}                                      `json:"-"`
	XXX_unrecognized     []byte                                        `json:"-"`
	XXX_sizecache        int32                                         `json:"-"`
}

type ContractMeta struct {
	CodeHash     github_com_hyperledger_burrow_binary.HexBytes `protobuf:"bytes,1,opt,name=CodeHash,proto3,customtype=github.com/hyperledger/burrow/binary.HexBytes" json:"CodeHash"`
	MetadataHash github_com_hyperledger_burrow_binary.HexBytes `protobuf:"bytes,2,opt,name=MetadataHash,proto3,customtype=github.com/hyperledger/burrow/binary.HexBytes" json:"MetadataHash"`
	// In the dump format we would like the ABI rather than its hash
	Metadata             string   `protobuf:"bytes,3,opt,name=Metadata,proto3" json:"Metadata,omitempty"`
}

In my debug, metadata is always stored in leveldb.
rpc server call stack

github.com/tendermint/tm-db.(*GoLevelDB).Get at go_level_db.go:44
github.com/hyperledger/burrow/storage.(*PrefixDB).Get at prefix_db.go:23
github.com/hyperledger/burrow/execution/state.(*ReadState).GetMetadata at abi.go:8
github.com/hyperledger/burrow/rpc/rpcquery.(*queryServer).GetMetadata at query_server.go:121
github.com/hyperledger/burrow/rpc/rpcquery._Query_GetMetadata_Handler.func1 at rpcquery.pb.go:1419
github.com/hyperledger/burrow/rpc.unaryInterceptor.func1 at grpc.go:29
github.com/hyperledger/burrow/rpc/rpcquery._Query_GetMetadata_Handler at rpcquery.pb.go:1421
google.golang.org/grpc.(*Server).processUnaryRPC at server.go:1024
google.golang.org/grpc.(*Server).handleStream at server.go:1313
google.golang.org/grpc.(*Server).serveStreams.func1.1 at server.go:722
runtime.goexit at asm_amd64.s:1357
 - Async stack trace
google.golang.org/grpc.(*Server).serveStreams.func1 at server.go:720
  • 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、付费专栏及课程。

余额充值