Commit a4b37c31 authored by 袁兴强's avatar 袁兴强

wasm contract can be updated by the creator

parent a980fd5d
......@@ -23,6 +23,7 @@ func Cmd() *cobra.Command {
cmd.AddCommand(
cmdCheckContract(),
cmdCreateContract(),
cmdUpdateContract(),
cmdCallContract(),
)
......@@ -53,6 +54,19 @@ func cmdCreateContract() *cobra.Command {
return cmd
}
func cmdUpdateContract() *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Short: "update an existing contract on chain33",
Run: updateContract,
}
cmd.Flags().StringP("name", "n", "", "contract name")
cmd.Flags().StringP("path", "p", "", "path of the wasm file, such as ./test.wasm")
_ = cmd.MarkFlagRequired("name")
_ = cmd.MarkFlagRequired("path")
return cmd
}
func cmdCallContract() *cobra.Command {
cmd := &cobra.Command{
Use: "call",
......@@ -110,6 +124,31 @@ func createContract(cmd *cobra.Command, args []string) {
ctx.RunWithoutMarshal()
}
func updateContract(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
name, _ := cmd.Flags().GetString("name")
path, _ := cmd.Flags().GetString("path")
// Read WebAssembly *.wasm file.
code, err := ioutil.ReadFile(path)
if err != nil {
fmt.Fprintln(os.Stderr, err)
return
}
payload := wasmtypes.WasmUpdate{
Name: name,
Code: code,
}
params := rpctypes.CreateTxIn{
Execer: wasmtypes.WasmX,
ActionName: "Update",
Payload: types.MustPBToJSON(&payload),
}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
func callContract(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
name, _ := cmd.Flags().GetString("name")
......
......@@ -55,9 +55,16 @@ wabt/bin/wasm2wat dice.wasm
### 发布合约
```bash
# 若合约已存在则会创建失败,可以换一个合约名发布
./chain33-cli send wasm create -n 指定合约名 -p wasm合约路径 -k 用户私钥
```
### 更新合约
```bash
# 更新合约要求合约已存在,且只有合约创建者有更新权限
./chain33-cli send wasm update -n 指定合约名 -p wasm合约路径 -k 用户私钥
```
### 调用合约
```bash
#其中参数为用逗号分隔的数字列表,字符串参数为逗号分隔的字符串列表
......
......@@ -10,6 +10,11 @@ func contractKey(name string) []byte {
return append([]byte("mavl-"+types2.WasmX+"-code-"), []byte(name)...)
}
// "mavl-wasm-creator-{name}"
func contractCreatorKey(name string) []byte {
return append([]byte("mavl-"+types2.WasmX+"-creator-"), []byte(name)...)
}
// "mavl-wasm-{contract}-"
func calcStatePrefix(contract string) []byte {
var prefix []byte
......
......@@ -48,7 +48,7 @@ func (w *Wasm) Exec_Create(payload *types2.WasmCreate, tx *types.Transaction, in
return nil, types2.ErrInvalidWasm
}
kvc := dapp.NewKVCreator(w.GetStateDB(), nil, nil)
kvc := dapp.NewKVCreator(w.GetStateDB(), types.CalcStatePrefix(tx.Execer), nil)
_, err := kvc.GetNoPrefix(contractKey(name))
if err == nil {
return nil, types2.ErrContractExist
......@@ -57,6 +57,7 @@ func (w *Wasm) Exec_Create(payload *types2.WasmCreate, tx *types.Transaction, in
return nil, err
}
kvc.AddNoPrefix(contractKey(name), code)
kvc.AddNoPrefix(contractCreatorKey(name), []byte(tx.From()))
receiptLog := &types.ReceiptLog{
Ty: types2.TyLogWasmCreate,
......@@ -73,6 +74,53 @@ func (w *Wasm) Exec_Create(payload *types2.WasmCreate, tx *types.Transaction, in
}, nil
}
func (w *Wasm) Exec_Update(payload *types2.WasmUpdate, tx *types.Transaction, index int) (*types.Receipt, error) {
if payload == nil {
return nil, types.ErrInvalidParam
}
if !w.checkTxExec(string(tx.Execer), types2.WasmX) {
return nil, types.ErrExecNameNotMatch
}
name := payload.Name
kvc := dapp.NewKVCreator(w.GetStateDB(), types.CalcStatePrefix(tx.Execer), nil)
creator, err := kvc.GetNoPrefix(contractCreatorKey(name))
if err != nil {
return nil, types2.ErrContractNotExist
}
_, err = kvc.GetNoPrefix(contractKey(name))
if err != nil {
return nil, types2.ErrContractNotExist
}
if tx.From() != string(creator) {
return nil, types2.ErrInvalidCreator
}
code := payload.Code
if len(code) > types2.MaxCodeSize {
return nil, types2.ErrCodeOversize
}
if err := validation.ValidateWasm(code); err != nil {
return nil, types2.ErrInvalidWasm
}
kvc.AddNoPrefix(contractKey(name), code)
receiptLog := &types.ReceiptLog{
Ty: types2.TyLogWasmUpdate,
Log: types.Encode(&types2.UpdateContractLog{
Name: name,
Code: hex.EncodeToString(code),
}),
}
return &types.Receipt{
Ty: types.ExecOk,
KV: kvc.KVList(),
Logs: []*types.ReceiptLog{receiptLog},
}, nil
}
func (w *Wasm) Exec_Call(payload *types2.WasmCall, tx *types.Transaction, index int) (*types.Receipt, error) {
if payload == nil {
return nil, types.ErrInvalidParam
......
......@@ -9,6 +9,10 @@ func (w *Wasm) ExecDelLocal_Create(payload *types2.WasmCreate, tx *types.Transac
return &types.LocalDBSet{}, nil
}
func (w *Wasm) ExecDelLocal_Update(payload *types2.WasmUpdate, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return &types.LocalDBSet{}, nil
}
func (w *Wasm) ExecDelLocal_Call(payload *types2.WasmCall, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
localExecer := w.userExecName(payload.Contract, true)
kvs, err := w.DelRollbackKV(tx, []byte(localExecer))
......
......@@ -9,6 +9,10 @@ func (w *Wasm) ExecLocal_Create(payload *types2.WasmCreate, tx *types.Transactio
return &types.LocalDBSet{}, nil
}
func (w *Wasm) ExecLocal_Update(payload *types2.WasmUpdate, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return &types.LocalDBSet{}, nil
}
func (w *Wasm) ExecLocal_Call(payload *types2.WasmCall, tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
if receipt.Ty != types.ExecOk {
return &types.LocalDBSet{}, nil
......
......@@ -5,9 +5,10 @@ package types;
message wasmAction {
oneof value {
wasmCreate create = 1;
wasmCall call = 2;
wasmUpdate update = 2;
wasmCall call = 3;
}
int32 ty = 3;
int32 ty = 4;
}
message wasmCreate {
......@@ -15,6 +16,11 @@ message wasmCreate {
bytes code = 2;
}
message wasmUpdate {
string name = 1;
bytes code = 2;
}
message wasmCall {
string contract = 1;
string method = 2;
......@@ -35,6 +41,11 @@ message createContractLog {
string code = 2;
}
message updateContractLog {
string name = 1;
string code = 2;
}
message callContractLog {
string contract = 1;
string method = 2;
......
......@@ -3,7 +3,9 @@ package types
import "errors"
var (
ErrContractExist = errors.New("contract exist")
ErrContractExist = errors.New("contract already exist")
ErrContractNotExist = errors.New("contract not exist")
ErrInvalidCreator = errors.New("invalid contract creator")
ErrInvalidWasm = errors.New("invalid wasm code")
ErrCodeOversize = errors.New("code oversize")
ErrInvalidMethod = errors.New("invalid method")
......
......@@ -19,12 +19,14 @@ const (
// action for executor
const (
WasmActionCreate = iota + 1
WasmActionUpdate
WasmActionCall
)
// log ty for executor
const (
TyLogWasmCreate = iota + 100
TyLogWasmUpdate
TyLogWasmCall
TyLogCustom
TyLogLocalData
......@@ -64,6 +66,7 @@ func (t *WasmType) GetPayload() types.Message {
func (t *WasmType) GetTypeMap() map[string]int32 {
return map[string]int32{
"Create": WasmActionCreate,
"Update": WasmActionUpdate,
"Call": WasmActionCall,
}
}
......@@ -71,6 +74,7 @@ func (t *WasmType) GetTypeMap() map[string]int32 {
func (t *WasmType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{
TyLogWasmCreate: {Ty: reflect.TypeOf(CreateContractLog{}), Name: "LogWasmCreate"},
TyLogWasmUpdate: {Ty: reflect.TypeOf(UpdateContractLog{}), Name: "LogWasmUpdate"},
TyLogWasmCall: {Ty: reflect.TypeOf(CallContractLog{}), Name: "LogWasmCall"},
TyLogCustom: {Ty: reflect.TypeOf(CustomLog{}), Name: "LogWasmCustom"},
TyLogLocalData: {Ty: reflect.TypeOf(LocalDataLog{}), Name: "LogWasmLocalData"},
......
......@@ -5,9 +5,8 @@ package types
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
......@@ -24,9 +23,10 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type WasmAction struct {
// Types that are valid to be assigned to Value:
// *WasmAction_Create
// *WasmAction_Update
// *WasmAction_Call
Value isWasmAction_Value `protobuf_oneof:"value"`
Ty int32 `protobuf:"varint,3,opt,name=ty,proto3" json:"ty,omitempty"`
Ty int32 `protobuf:"varint,4,opt,name=ty,proto3" json:"ty,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
......@@ -65,12 +65,18 @@ type WasmAction_Create struct {
Create *WasmCreate `protobuf:"bytes,1,opt,name=create,proto3,oneof"`
}
type WasmAction_Update struct {
Update *WasmUpdate `protobuf:"bytes,2,opt,name=update,proto3,oneof"`
}
type WasmAction_Call struct {
Call *WasmCall `protobuf:"bytes,2,opt,name=call,proto3,oneof"`
Call *WasmCall `protobuf:"bytes,3,opt,name=call,proto3,oneof"`
}
func (*WasmAction_Create) isWasmAction_Value() {}
func (*WasmAction_Update) isWasmAction_Value() {}
func (*WasmAction_Call) isWasmAction_Value() {}
func (m *WasmAction) GetValue() isWasmAction_Value {
......@@ -87,6 +93,13 @@ func (m *WasmAction) GetCreate() *WasmCreate {
return nil
}
func (m *WasmAction) GetUpdate() *WasmUpdate {
if x, ok := m.GetValue().(*WasmAction_Update); ok {
return x.Update
}
return nil
}
func (m *WasmAction) GetCall() *WasmCall {
if x, ok := m.GetValue().(*WasmAction_Call); ok {
return x.Call
......@@ -105,6 +118,7 @@ func (m *WasmAction) GetTy() int32 {
func (*WasmAction) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*WasmAction_Create)(nil),
(*WasmAction_Update)(nil),
(*WasmAction_Call)(nil),
}
}
......@@ -156,6 +170,53 @@ func (m *WasmCreate) GetCode() []byte {
return nil
}
type WasmUpdate struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Code []byte `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *WasmUpdate) Reset() { *m = WasmUpdate{} }
func (m *WasmUpdate) String() string { return proto.CompactTextString(m) }
func (*WasmUpdate) ProtoMessage() {}
func (*WasmUpdate) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{2}
}
func (m *WasmUpdate) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_WasmUpdate.Unmarshal(m, b)
}
func (m *WasmUpdate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_WasmUpdate.Marshal(b, m, deterministic)
}
func (m *WasmUpdate) XXX_Merge(src proto.Message) {
xxx_messageInfo_WasmUpdate.Merge(m, src)
}
func (m *WasmUpdate) XXX_Size() int {
return xxx_messageInfo_WasmUpdate.Size(m)
}
func (m *WasmUpdate) XXX_DiscardUnknown() {
xxx_messageInfo_WasmUpdate.DiscardUnknown(m)
}
var xxx_messageInfo_WasmUpdate proto.InternalMessageInfo
func (m *WasmUpdate) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *WasmUpdate) GetCode() []byte {
if m != nil {
return m.Code
}
return nil
}
type WasmCall struct {
Contract string `protobuf:"bytes,1,opt,name=contract,proto3" json:"contract,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
......@@ -170,7 +231,7 @@ func (m *WasmCall) Reset() { *m = WasmCall{} }
func (m *WasmCall) String() string { return proto.CompactTextString(m) }
func (*WasmCall) ProtoMessage() {}
func (*WasmCall) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{2}
return fileDescriptor_7d78909ad64e3bbb, []int{3}
}
func (m *WasmCall) XXX_Unmarshal(b []byte) error {
......@@ -230,7 +291,7 @@ func (m *QueryCheckContract) Reset() { *m = QueryCheckContract{} }
func (m *QueryCheckContract) String() string { return proto.CompactTextString(m) }
func (*QueryCheckContract) ProtoMessage() {}
func (*QueryCheckContract) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{3}
return fileDescriptor_7d78909ad64e3bbb, []int{4}
}
func (m *QueryCheckContract) XXX_Unmarshal(b []byte) error {
......@@ -269,7 +330,7 @@ func (m *CustomLog) Reset() { *m = CustomLog{} }
func (m *CustomLog) String() string { return proto.CompactTextString(m) }
func (*CustomLog) ProtoMessage() {}
func (*CustomLog) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{4}
return fileDescriptor_7d78909ad64e3bbb, []int{5}
}
func (m *CustomLog) XXX_Unmarshal(b []byte) error {
......@@ -309,7 +370,7 @@ func (m *CreateContractLog) Reset() { *m = CreateContractLog{} }
func (m *CreateContractLog) String() string { return proto.CompactTextString(m) }
func (*CreateContractLog) ProtoMessage() {}
func (*CreateContractLog) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{5}
return fileDescriptor_7d78909ad64e3bbb, []int{6}
}
func (m *CreateContractLog) XXX_Unmarshal(b []byte) error {
......@@ -344,6 +405,53 @@ func (m *CreateContractLog) GetCode() string {
return ""
}
type UpdateContractLog struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *UpdateContractLog) Reset() { *m = UpdateContractLog{} }
func (m *UpdateContractLog) String() string { return proto.CompactTextString(m) }
func (*UpdateContractLog) ProtoMessage() {}
func (*UpdateContractLog) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{7}
}
func (m *UpdateContractLog) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_UpdateContractLog.Unmarshal(m, b)
}
func (m *UpdateContractLog) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_UpdateContractLog.Marshal(b, m, deterministic)
}
func (m *UpdateContractLog) XXX_Merge(src proto.Message) {
xxx_messageInfo_UpdateContractLog.Merge(m, src)
}
func (m *UpdateContractLog) XXX_Size() int {
return xxx_messageInfo_UpdateContractLog.Size(m)
}
func (m *UpdateContractLog) XXX_DiscardUnknown() {
xxx_messageInfo_UpdateContractLog.DiscardUnknown(m)
}
var xxx_messageInfo_UpdateContractLog proto.InternalMessageInfo
func (m *UpdateContractLog) GetName() string {
if m != nil {
return m.Name
}
return ""
}
func (m *UpdateContractLog) GetCode() string {
if m != nil {
return m.Code
}
return ""
}
type CallContractLog struct {
Contract string `protobuf:"bytes,1,opt,name=contract,proto3" json:"contract,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
......@@ -357,7 +465,7 @@ func (m *CallContractLog) Reset() { *m = CallContractLog{} }
func (m *CallContractLog) String() string { return proto.CompactTextString(m) }
func (*CallContractLog) ProtoMessage() {}
func (*CallContractLog) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{6}
return fileDescriptor_7d78909ad64e3bbb, []int{8}
}
func (m *CallContractLog) XXX_Unmarshal(b []byte) error {
......@@ -411,7 +519,7 @@ func (m *LocalDataLog) Reset() { *m = LocalDataLog{} }
func (m *LocalDataLog) String() string { return proto.CompactTextString(m) }
func (*LocalDataLog) ProtoMessage() {}
func (*LocalDataLog) Descriptor() ([]byte, []int) {
return fileDescriptor_7d78909ad64e3bbb, []int{7}
return fileDescriptor_7d78909ad64e3bbb, []int{9}
}
func (m *LocalDataLog) XXX_Unmarshal(b []byte) error {
......@@ -449,40 +557,42 @@ func (m *LocalDataLog) GetValue() []byte {
func init() {
proto.RegisterType((*WasmAction)(nil), "types.wasmAction")
proto.RegisterType((*WasmCreate)(nil), "types.wasmCreate")
proto.RegisterType((*WasmUpdate)(nil), "types.wasmUpdate")
proto.RegisterType((*WasmCall)(nil), "types.wasmCall")
proto.RegisterType((*QueryCheckContract)(nil), "types.queryCheckContract")
proto.RegisterType((*CustomLog)(nil), "types.customLog")
proto.RegisterType((*CreateContractLog)(nil), "types.createContractLog")
proto.RegisterType((*UpdateContractLog)(nil), "types.updateContractLog")
proto.RegisterType((*CallContractLog)(nil), "types.callContractLog")
proto.RegisterType((*LocalDataLog)(nil), "types.localDataLog")
}
func init() {
proto.RegisterFile("wasm.proto", fileDescriptor_7d78909ad64e3bbb)
}
func init() { proto.RegisterFile("wasm.proto", fileDescriptor_7d78909ad64e3bbb) }
var fileDescriptor_7d78909ad64e3bbb = []byte{
// 337 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x52, 0x31, 0x4f, 0xf3, 0x30,
0x10, 0x6d, 0xea, 0x36, 0x5f, 0x73, 0x5f, 0x45, 0x5b, 0x0b, 0x55, 0x11, 0x03, 0x44, 0x96, 0x90,
0x22, 0x21, 0x75, 0x00, 0xc4, 0xc2, 0x04, 0x65, 0xe8, 0xc0, 0xe4, 0x9d, 0xc1, 0xb8, 0x86, 0x56,
0x75, 0xe2, 0xe0, 0x5c, 0x8a, 0xf2, 0xef, 0x91, 0x1d, 0x17, 0x75, 0x40, 0x0c, 0x6c, 0xef, 0x9d,
0xdf, 0xbd, 0x97, 0xbb, 0x0b, 0xc0, 0xa7, 0xa8, 0x8b, 0x45, 0x65, 0x0d, 0x1a, 0x3a, 0xc4, 0xb6,
0x52, 0x35, 0x6b, 0xbb, 0xe2, 0x83, 0xc4, 0xad, 0x29, 0xe9, 0x15, 0xc4, 0xd2, 0x2a, 0x81, 0x2a,
0x8d, 0xb2, 0x28, 0xff, 0x7f, 0x3d, 0x5b, 0x78, 0xd5, 0xc2, 0x49, 0x96, 0xfe, 0x61, 0xd5, 0xe3,
0x41, 0x42, 0x2f, 0x61, 0x20, 0x85, 0xd6, 0x69, 0xdf, 0x4b, 0x27, 0xc7, 0x52, 0xa1, 0xf5, 0xaa,
0xc7, 0xfd, 0x33, 0x3d, 0x81, 0x3e, 0xb6, 0x29, 0xc9, 0xa2, 0x7c, 0xc8, 0xfb, 0xd8, 0x3e, 0xfe,
0x83, 0xe1, 0x5e, 0xe8, 0x46, 0xb1, 0xdb, 0x2e, 0xba, 0xf3, 0xa5, 0x14, 0x06, 0xa5, 0x28, 0xba,
0xe0, 0x84, 0x7b, 0xec, 0x6a, 0xd2, 0xac, 0x95, 0x4f, 0x18, 0x73, 0x8f, 0x59, 0x05, 0xa3, 0x43,
0x04, 0x3d, 0x83, 0x91, 0x34, 0x25, 0x5a, 0x21, 0x31, 0xf4, 0x7d, 0x73, 0x3a, 0x87, 0xb8, 0x50,
0xb8, 0x31, 0x6b, 0xdf, 0x9d, 0xf0, 0xc0, 0xe8, 0x39, 0x40, 0x25, 0xac, 0x28, 0x14, 0x2a, 0x5b,
0xa7, 0x24, 0x23, 0x39, 0xe1, 0x47, 0x15, 0x3a, 0x05, 0xa2, 0xca, 0x7d, 0x3a, 0xc8, 0x48, 0x9e,
0x70, 0x07, 0x59, 0x0e, 0xf4, 0xa3, 0x51, 0xb6, 0x5d, 0x6e, 0x94, 0xdc, 0x2d, 0x0f, 0xfe, 0x3f,
0x7c, 0x2f, 0xbb, 0x80, 0x44, 0x36, 0x35, 0x9a, 0xe2, 0xd9, 0xbc, 0x3b, 0xc1, 0xb6, 0x7c, 0x33,
0x69, 0xe4, 0x9d, 0x3c, 0x66, 0xf7, 0x30, 0xeb, 0x96, 0x77, 0xb0, 0x09, 0xc2, 0x5f, 0x27, 0x4f,
0xc2, 0xe4, 0x2f, 0x30, 0x71, 0x0b, 0x3d, 0x6e, 0xfd, 0xcb, 0x02, 0xe6, 0x10, 0x5b, 0x55, 0x37,
0x1a, 0xc3, 0x4d, 0x02, 0x63, 0x77, 0x30, 0xd6, 0x46, 0x0a, 0xfd, 0x24, 0x50, 0x38, 0xef, 0x29,
0x90, 0x9d, 0x6a, 0xbd, 0xed, 0x98, 0x3b, 0x48, 0x4f, 0xc3, 0xe5, 0xc2, 0x3d, 0x3a, 0xf2, 0x1a,
0xfb, 0xff, 0xe9, 0xe6, 0x2b, 0x00, 0x00, 0xff, 0xff, 0x62, 0xf8, 0x3a, 0xae, 0x5d, 0x02, 0x00,
0x00,
// 370 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0x4d, 0x4b, 0xfb, 0x40,
0x10, 0xc6, 0x9b, 0xe6, 0xe5, 0xdf, 0xcc, 0xbf, 0xd8, 0x76, 0x91, 0x12, 0x3c, 0x68, 0x08, 0x08,
0x01, 0xa1, 0x07, 0x15, 0x2f, 0x3d, 0x69, 0x3d, 0xf4, 0xe0, 0x69, 0xc1, 0xa3, 0x87, 0x75, 0xbb,
0xda, 0xd2, 0x4d, 0x36, 0x6e, 0x36, 0x95, 0x7c, 0x21, 0x3f, 0xa7, 0xec, 0x4b, 0xa4, 0xa0, 0x88,
0xf4, 0x36, 0xb3, 0xf3, 0x7b, 0x1e, 0x9e, 0x64, 0x06, 0xe0, 0x9d, 0xd4, 0xc5, 0xac, 0x92, 0x42,
0x09, 0x14, 0xaa, 0xb6, 0x62, 0x75, 0xf6, 0xe1, 0xd9, 0xd7, 0x5b, 0xaa, 0x36, 0xa2, 0x44, 0x17,
0x10, 0x51, 0xc9, 0x88, 0x62, 0x89, 0x97, 0x7a, 0xf9, 0xff, 0xcb, 0xc9, 0xcc, 0x60, 0x33, 0x8d,
0x2c, 0xcc, 0x60, 0xd9, 0xc3, 0x0e, 0xd1, 0x70, 0x53, 0xad, 0x34, 0xdc, 0xff, 0x06, 0x3f, 0x9a,
0x81, 0x86, 0x2d, 0x82, 0xce, 0x21, 0xa0, 0x84, 0xf3, 0xc4, 0x37, 0xe8, 0x68, 0xdf, 0x97, 0x70,
0xbe, 0xec, 0x61, 0x33, 0x46, 0x47, 0xd0, 0x57, 0x6d, 0x12, 0xa4, 0x5e, 0x1e, 0xe2, 0xbe, 0x6a,
0xef, 0xfe, 0x41, 0xb8, 0x23, 0xbc, 0x61, 0xd9, 0xb5, 0xcd, 0x69, 0x43, 0x20, 0x04, 0x41, 0x49,
0x0a, 0x9b, 0x32, 0xc6, 0xa6, 0xd6, 0x6f, 0x54, 0xac, 0x6c, 0x98, 0x21, 0x36, 0x75, 0xa7, 0xb2,
0x69, 0xfe, 0xac, 0xaa, 0x60, 0xd0, 0x05, 0x43, 0x27, 0x30, 0xa0, 0xa2, 0x54, 0x92, 0x50, 0xe5,
0x74, 0x5f, 0x3d, 0x9a, 0x42, 0x54, 0x30, 0xb5, 0x16, 0x2b, 0xa3, 0x8e, 0xb1, 0xeb, 0xd0, 0x29,
0x40, 0x45, 0x24, 0x29, 0x98, 0x62, 0xb2, 0x4e, 0xfc, 0xd4, 0xcf, 0x7d, 0xbc, 0xf7, 0x82, 0xc6,
0xe0, 0xb3, 0x72, 0x97, 0x04, 0xa9, 0x9f, 0xc7, 0x58, 0x97, 0x59, 0x0e, 0xe8, 0xad, 0x61, 0xb2,
0x5d, 0xac, 0x19, 0xdd, 0x2e, 0x3a, 0xff, 0x1f, 0xf2, 0x66, 0x67, 0x10, 0xd3, 0xa6, 0x56, 0xa2,
0x78, 0x10, 0xaf, 0x1a, 0xd8, 0x94, 0x2f, 0x22, 0xf1, 0x8c, 0x93, 0xa9, 0xb3, 0x39, 0x4c, 0xec,
0x7e, 0x3a, 0x1b, 0x07, 0xfe, 0xfa, 0xe5, 0xb1, 0xfb, 0xf2, 0x39, 0x4c, 0xec, 0xbe, 0x0e, 0x11,
0x3f, 0xc1, 0x48, 0xef, 0x70, 0x5f, 0x7a, 0xc8, 0xdf, 0x9b, 0x42, 0x24, 0x59, 0xdd, 0x70, 0x65,
0x6e, 0x25, 0xc4, 0xae, 0xcb, 0x6e, 0x60, 0xc8, 0x05, 0x25, 0xfc, 0x9e, 0x28, 0xa2, 0xbd, 0xc7,
0xe0, 0x6f, 0x59, 0x6b, 0x6c, 0x87, 0x58, 0x97, 0xe8, 0xd8, 0x1d, 0x8b, 0x5b, 0xa6, 0x6d, 0x9e,
0x23, 0x73, 0xf0, 0x57, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x95, 0x09, 0x33, 0xfe, 0x02,
0x00, 0x00,
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment