OSDN Git Service

fix(cross_chain): add asset_id check in cross_chain_in request (#177)
authorHAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Wed, 19 Jun 2019 05:23:37 +0000 (13:23 +0800)
committerPaladz <yzhu101@uottawa.ca>
Wed, 19 Jun 2019 05:23:37 +0000 (13:23 +0800)
* init issuance_program

* add asset

* fix

* modify asset of crosschain input

* fix test

* add assetdef of bc

* fix

* modify code

* fix check assetID

* fix wallet uint

* fix review

* fix utxo uint test

* delete code

* remove space

* fix review

* remove checkfederation

* fix review

13 files changed:
blockchain/txbuilder/actions.go
protocol/bc/asset.go
protocol/bc/bc.pb.go
protocol/bc/bc.proto
protocol/bc/crosschain_input.go
protocol/bc/types/crosschain_input.go
protocol/bc/types/crosschain_output.go
protocol/bc/types/map.go
protocol/bc/types/txinput.go
protocol/bc/types/txinput_test.go
protocol/bc/types/vote_txoutput.go
protocol/validation/tx.go
wallet/utxo_test.go

index 99f35bc..f06c3ed 100644 (file)
@@ -5,9 +5,10 @@ import (
        stdjson "encoding/json"
        "errors"
 
        stdjson "encoding/json"
        "errors"
 
-       "github.com/vapor/config"
+       "golang.org/x/crypto/sha3"
 
        "github.com/vapor/common"
 
        "github.com/vapor/common"
+       "github.com/vapor/config"
        "github.com/vapor/consensus"
        "github.com/vapor/encoding/json"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/consensus"
        "github.com/vapor/encoding/json"
        "github.com/vapor/protocol/bc"
@@ -261,9 +262,11 @@ func DecodeCrossInAction(data []byte) (Action, error) {
 
 type crossInAction struct {
        bc.AssetAmount
 
 type crossInAction struct {
        bc.AssetAmount
-       SourceID          bc.Hash       `json:"source_id"`
-       SourcePos         uint64        `json:"source_pos"`
-       RawDefinitionByte json.HexBytes `json:"raw_definition_byte"`
+       SourceID          bc.Hash `json:"source_id"`
+       SourcePos         uint64  `json:"source_pos"`
+       VMVersion         uint64  `json:"vm_version"`
+       RawDefinitionByte []byte  `json:"raw_definition_byte"`
+       IssuanceProgram   []byte  `json:"issuance_program"`
 }
 
 func (a *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) error {
 }
 
 func (a *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) error {
@@ -277,13 +280,17 @@ func (a *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) err
        if a.Amount == 0 {
                missing = append(missing, "amount")
        }
        if a.Amount == 0 {
                missing = append(missing, "amount")
        }
+
        if len(missing) > 0 {
                return MissingFieldsError(missing...)
        }
 
        if len(missing) > 0 {
                return MissingFieldsError(missing...)
        }
 
+       if err := a.checkAssetID(); err != nil {
+               return err
+       }
+
        // arguments will be set when materializeWitnesses
        // arguments will be set when materializeWitnesses
-       fedProg := config.FederationProgrom(config.CommonConfig)
-       txin := types.NewCrossChainInput(nil, a.SourceID, *a.AssetId, a.Amount, a.SourcePos, fedProg, a.RawDefinitionByte)
+       txin := types.NewCrossChainInput(nil, a.SourceID, *a.AssetId, a.Amount, a.SourcePos, a.VMVersion, a.RawDefinitionByte, a.IssuanceProgram)
        tplIn := &SigningInstruction{}
        fed := config.CommonConfig.Federation
        tplIn.AddRawWitnessKeys(fed.Xpubs, nil, fed.Quorum)
        tplIn := &SigningInstruction{}
        fed := config.CommonConfig.Federation
        tplIn.AddRawWitnessKeys(fed.Xpubs, nil, fed.Quorum)
@@ -293,3 +300,14 @@ func (a *crossInAction) Build(ctx context.Context, builder *TemplateBuilder) err
 func (a *crossInAction) ActionType() string {
        return "cross_chain_in"
 }
 func (a *crossInAction) ActionType() string {
        return "cross_chain_in"
 }
+
+func (c *crossInAction) checkAssetID() error {
+       defHash := bc.NewHash(sha3.Sum256(c.RawDefinitionByte))
+       assetID := bc.ComputeAssetID(c.IssuanceProgram, c.VMVersion, &defHash)
+
+       if *c.AssetId == *consensus.BTMAssetID && assetID != *c.AssetAmount.AssetId {
+               return errors.New("incorrect asset_idincorrect asset_id")
+       }
+
+       return nil
+}
index 91285fa..553cd71 100644 (file)
@@ -5,6 +5,7 @@ import (
        "errors"
        "io"
 
        "errors"
        "io"
 
+       "github.com/vapor/crypto/sha3pool"
        "github.com/vapor/encoding/blockchain"
 )
 
        "github.com/vapor/encoding/blockchain"
 )
 
@@ -42,6 +43,28 @@ func (a *AssetID) ReadFrom(r io.Reader) (int64, error) { return (*Hash)(a).ReadF
 // IsZero tells whether a Asset pointer is nil or points to an all-zero hash.
 func (a *AssetID) IsZero() bool { return (*Hash)(a).IsZero() }
 
 // IsZero tells whether a Asset pointer is nil or points to an all-zero hash.
 func (a *AssetID) IsZero() bool { return (*Hash)(a).IsZero() }
 
+// ComputeAssetID calculate the asset id from AssetDefinition
+func (ad *AssetDefinition) ComputeAssetID() (assetID AssetID) {
+       h := sha3pool.Get256()
+       defer sha3pool.Put256(h)
+       writeForHash(h, *ad) // error is impossible
+       var b [32]byte
+       h.Read(b[:]) // error is impossible
+       return NewAssetID(b)
+}
+
+// ComputeAssetID implement the assetID calculate logic
+func ComputeAssetID(prog []byte, vmVersion uint64, data *Hash) AssetID {
+       def := &AssetDefinition{
+               IssuanceProgram: &Program{
+                       VmVersion: vmVersion,
+                       Code:      prog,
+               },
+               Data: data,
+       }
+       return def.ComputeAssetID()
+}
+
 // ReadFrom read the AssetAmount from the bytes
 func (a *AssetAmount) ReadFrom(r *blockchain.Reader) (err error) {
        var assetID AssetID
 // ReadFrom read the AssetAmount from the bytes
 func (a *AssetAmount) ReadFrom(r *blockchain.Reader) (err error) {
        var assetID AssetID
index fbffe83..d31e731 100644 (file)
@@ -12,6 +12,7 @@ It has these top-level messages:
        Program
        AssetID
        AssetAmount
        Program
        AssetID
        AssetAmount
+       AssetDefinition
        ValueSource
        ValueDestination
        BlockHeader
        ValueSource
        ValueDestination
        BlockHeader
@@ -178,6 +179,30 @@ func (m *AssetAmount) GetAmount() uint64 {
        return 0
 }
 
        return 0
 }
 
+type AssetDefinition struct {
+       IssuanceProgram *Program `protobuf:"bytes,1,opt,name=issuance_program,json=issuanceProgram" json:"issuance_program,omitempty"`
+       Data            *Hash    `protobuf:"bytes,2,opt,name=data" json:"data,omitempty"`
+}
+
+func (m *AssetDefinition) Reset()                    { *m = AssetDefinition{} }
+func (m *AssetDefinition) String() string            { return proto.CompactTextString(m) }
+func (*AssetDefinition) ProtoMessage()               {}
+func (*AssetDefinition) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+
+func (m *AssetDefinition) GetIssuanceProgram() *Program {
+       if m != nil {
+               return m.IssuanceProgram
+       }
+       return nil
+}
+
+func (m *AssetDefinition) GetData() *Hash {
+       if m != nil {
+               return m.Data
+       }
+       return nil
+}
+
 type ValueSource struct {
        Ref      *Hash        `protobuf:"bytes,1,opt,name=ref" json:"ref,omitempty"`
        Value    *AssetAmount `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
 type ValueSource struct {
        Ref      *Hash        `protobuf:"bytes,1,opt,name=ref" json:"ref,omitempty"`
        Value    *AssetAmount `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
@@ -187,7 +212,7 @@ type ValueSource struct {
 func (m *ValueSource) Reset()                    { *m = ValueSource{} }
 func (m *ValueSource) String() string            { return proto.CompactTextString(m) }
 func (*ValueSource) ProtoMessage()               {}
 func (m *ValueSource) Reset()                    { *m = ValueSource{} }
 func (m *ValueSource) String() string            { return proto.CompactTextString(m) }
 func (*ValueSource) ProtoMessage()               {}
-func (*ValueSource) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
+func (*ValueSource) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
 
 func (m *ValueSource) GetRef() *Hash {
        if m != nil {
 
 func (m *ValueSource) GetRef() *Hash {
        if m != nil {
@@ -219,7 +244,7 @@ type ValueDestination struct {
 func (m *ValueDestination) Reset()                    { *m = ValueDestination{} }
 func (m *ValueDestination) String() string            { return proto.CompactTextString(m) }
 func (*ValueDestination) ProtoMessage()               {}
 func (m *ValueDestination) Reset()                    { *m = ValueDestination{} }
 func (m *ValueDestination) String() string            { return proto.CompactTextString(m) }
 func (*ValueDestination) ProtoMessage()               {}
-func (*ValueDestination) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
+func (*ValueDestination) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
 
 func (m *ValueDestination) GetRef() *Hash {
        if m != nil {
 
 func (m *ValueDestination) GetRef() *Hash {
        if m != nil {
@@ -256,7 +281,7 @@ type BlockHeader struct {
 func (m *BlockHeader) Reset()                    { *m = BlockHeader{} }
 func (m *BlockHeader) String() string            { return proto.CompactTextString(m) }
 func (*BlockHeader) ProtoMessage()               {}
 func (m *BlockHeader) Reset()                    { *m = BlockHeader{} }
 func (m *BlockHeader) String() string            { return proto.CompactTextString(m) }
 func (*BlockHeader) ProtoMessage()               {}
-func (*BlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
+func (*BlockHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
 
 func (m *BlockHeader) GetVersion() uint64 {
        if m != nil {
 
 func (m *BlockHeader) GetVersion() uint64 {
        if m != nil {
@@ -324,7 +349,7 @@ type TxHeader struct {
 func (m *TxHeader) Reset()                    { *m = TxHeader{} }
 func (m *TxHeader) String() string            { return proto.CompactTextString(m) }
 func (*TxHeader) ProtoMessage()               {}
 func (m *TxHeader) Reset()                    { *m = TxHeader{} }
 func (m *TxHeader) String() string            { return proto.CompactTextString(m) }
 func (*TxHeader) ProtoMessage()               {}
-func (*TxHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
+func (*TxHeader) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
 
 func (m *TxHeader) GetVersion() uint64 {
        if m != nil {
 
 func (m *TxHeader) GetVersion() uint64 {
        if m != nil {
@@ -361,7 +386,7 @@ type TxVerifyResult struct {
 func (m *TxVerifyResult) Reset()                    { *m = TxVerifyResult{} }
 func (m *TxVerifyResult) String() string            { return proto.CompactTextString(m) }
 func (*TxVerifyResult) ProtoMessage()               {}
 func (m *TxVerifyResult) Reset()                    { *m = TxVerifyResult{} }
 func (m *TxVerifyResult) String() string            { return proto.CompactTextString(m) }
 func (*TxVerifyResult) ProtoMessage()               {}
-func (*TxVerifyResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
+func (*TxVerifyResult) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
 
 func (m *TxVerifyResult) GetStatusFail() bool {
        if m != nil {
 
 func (m *TxVerifyResult) GetStatusFail() bool {
        if m != nil {
@@ -378,7 +403,7 @@ type TransactionStatus struct {
 func (m *TransactionStatus) Reset()                    { *m = TransactionStatus{} }
 func (m *TransactionStatus) String() string            { return proto.CompactTextString(m) }
 func (*TransactionStatus) ProtoMessage()               {}
 func (m *TransactionStatus) Reset()                    { *m = TransactionStatus{} }
 func (m *TransactionStatus) String() string            { return proto.CompactTextString(m) }
 func (*TransactionStatus) ProtoMessage()               {}
-func (*TransactionStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
+func (*TransactionStatus) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
 
 func (m *TransactionStatus) GetVersion() uint64 {
        if m != nil {
 
 func (m *TransactionStatus) GetVersion() uint64 {
        if m != nil {
@@ -404,7 +429,7 @@ type Mux struct {
 func (m *Mux) Reset()                    { *m = Mux{} }
 func (m *Mux) String() string            { return proto.CompactTextString(m) }
 func (*Mux) ProtoMessage()               {}
 func (m *Mux) Reset()                    { *m = Mux{} }
 func (m *Mux) String() string            { return proto.CompactTextString(m) }
 func (*Mux) ProtoMessage()               {}
-func (*Mux) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
+func (*Mux) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
 
 func (m *Mux) GetSources() []*ValueSource {
        if m != nil {
 
 func (m *Mux) GetSources() []*ValueSource {
        if m != nil {
@@ -442,7 +467,7 @@ type Coinbase struct {
 func (m *Coinbase) Reset()                    { *m = Coinbase{} }
 func (m *Coinbase) String() string            { return proto.CompactTextString(m) }
 func (*Coinbase) ProtoMessage()               {}
 func (m *Coinbase) Reset()                    { *m = Coinbase{} }
 func (m *Coinbase) String() string            { return proto.CompactTextString(m) }
 func (*Coinbase) ProtoMessage()               {}
-func (*Coinbase) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
+func (*Coinbase) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
 
 func (m *Coinbase) GetWitnessDestination() *ValueDestination {
        if m != nil {
 
 func (m *Coinbase) GetWitnessDestination() *ValueDestination {
        if m != nil {
@@ -467,7 +492,7 @@ type IntraChainOutput struct {
 func (m *IntraChainOutput) Reset()                    { *m = IntraChainOutput{} }
 func (m *IntraChainOutput) String() string            { return proto.CompactTextString(m) }
 func (*IntraChainOutput) ProtoMessage()               {}
 func (m *IntraChainOutput) Reset()                    { *m = IntraChainOutput{} }
 func (m *IntraChainOutput) String() string            { return proto.CompactTextString(m) }
 func (*IntraChainOutput) ProtoMessage()               {}
-func (*IntraChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
+func (*IntraChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
 
 func (m *IntraChainOutput) GetSource() *ValueSource {
        if m != nil {
 
 func (m *IntraChainOutput) GetSource() *ValueSource {
        if m != nil {
@@ -499,7 +524,7 @@ type CrossChainOutput struct {
 func (m *CrossChainOutput) Reset()                    { *m = CrossChainOutput{} }
 func (m *CrossChainOutput) String() string            { return proto.CompactTextString(m) }
 func (*CrossChainOutput) ProtoMessage()               {}
 func (m *CrossChainOutput) Reset()                    { *m = CrossChainOutput{} }
 func (m *CrossChainOutput) String() string            { return proto.CompactTextString(m) }
 func (*CrossChainOutput) ProtoMessage()               {}
-func (*CrossChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
+func (*CrossChainOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
 
 func (m *CrossChainOutput) GetSource() *ValueSource {
        if m != nil {
 
 func (m *CrossChainOutput) GetSource() *ValueSource {
        if m != nil {
@@ -532,7 +557,7 @@ type VoteOutput struct {
 func (m *VoteOutput) Reset()                    { *m = VoteOutput{} }
 func (m *VoteOutput) String() string            { return proto.CompactTextString(m) }
 func (*VoteOutput) ProtoMessage()               {}
 func (m *VoteOutput) Reset()                    { *m = VoteOutput{} }
 func (m *VoteOutput) String() string            { return proto.CompactTextString(m) }
 func (*VoteOutput) ProtoMessage()               {}
-func (*VoteOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
+func (*VoteOutput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
 
 func (m *VoteOutput) GetSource() *ValueSource {
        if m != nil {
 
 func (m *VoteOutput) GetSource() *ValueSource {
        if m != nil {
@@ -572,7 +597,7 @@ type VetoInput struct {
 func (m *VetoInput) Reset()                    { *m = VetoInput{} }
 func (m *VetoInput) String() string            { return proto.CompactTextString(m) }
 func (*VetoInput) ProtoMessage()               {}
 func (m *VetoInput) Reset()                    { *m = VetoInput{} }
 func (m *VetoInput) String() string            { return proto.CompactTextString(m) }
 func (*VetoInput) ProtoMessage()               {}
-func (*VetoInput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
+func (*VetoInput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
 
 func (m *VetoInput) GetSpentOutputId() *Hash {
        if m != nil {
 
 func (m *VetoInput) GetSpentOutputId() *Hash {
        if m != nil {
@@ -610,7 +635,7 @@ type Retirement struct {
 func (m *Retirement) Reset()                    { *m = Retirement{} }
 func (m *Retirement) String() string            { return proto.CompactTextString(m) }
 func (*Retirement) ProtoMessage()               {}
 func (m *Retirement) Reset()                    { *m = Retirement{} }
 func (m *Retirement) String() string            { return proto.CompactTextString(m) }
 func (*Retirement) ProtoMessage()               {}
-func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
+func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
 
 func (m *Retirement) GetSource() *ValueSource {
        if m != nil {
 
 func (m *Retirement) GetSource() *ValueSource {
        if m != nil {
@@ -636,7 +661,7 @@ type Spend struct {
 func (m *Spend) Reset()                    { *m = Spend{} }
 func (m *Spend) String() string            { return proto.CompactTextString(m) }
 func (*Spend) ProtoMessage()               {}
 func (m *Spend) Reset()                    { *m = Spend{} }
 func (m *Spend) String() string            { return proto.CompactTextString(m) }
 func (*Spend) ProtoMessage()               {}
-func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
+func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
 
 func (m *Spend) GetSpentOutputId() *Hash {
        if m != nil {
 
 func (m *Spend) GetSpentOutputId() *Hash {
        if m != nil {
@@ -671,14 +696,15 @@ type CrossChainInput struct {
        Value              *AssetAmount      `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
        WitnessDestination *ValueDestination `protobuf:"bytes,3,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
        ControlProgram     *Program          `protobuf:"bytes,4,opt,name=control_program,json=controlProgram" json:"control_program,omitempty"`
        Value              *AssetAmount      `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
        WitnessDestination *ValueDestination `protobuf:"bytes,3,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
        ControlProgram     *Program          `protobuf:"bytes,4,opt,name=control_program,json=controlProgram" json:"control_program,omitempty"`
-       WitnessArguments   [][]byte          `protobuf:"bytes,5,rep,name=witness_arguments,json=witnessArguments,proto3" json:"witness_arguments,omitempty"`
-       Ordinal            uint64            `protobuf:"varint,6,opt,name=ordinal" json:"ordinal,omitempty"`
+       AssetDefinition    *AssetDefinition  `protobuf:"bytes,5,opt,name=asset_definition,json=assetDefinition" json:"asset_definition,omitempty"`
+       WitnessArguments   [][]byte          `protobuf:"bytes,6,rep,name=witness_arguments,json=witnessArguments,proto3" json:"witness_arguments,omitempty"`
+       Ordinal            uint64            `protobuf:"varint,7,opt,name=ordinal" json:"ordinal,omitempty"`
 }
 
 func (m *CrossChainInput) Reset()                    { *m = CrossChainInput{} }
 func (m *CrossChainInput) String() string            { return proto.CompactTextString(m) }
 func (*CrossChainInput) ProtoMessage()               {}
 }
 
 func (m *CrossChainInput) Reset()                    { *m = CrossChainInput{} }
 func (m *CrossChainInput) String() string            { return proto.CompactTextString(m) }
 func (*CrossChainInput) ProtoMessage()               {}
-func (*CrossChainInput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
+func (*CrossChainInput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
 
 func (m *CrossChainInput) GetMainchainOutputId() *Hash {
        if m != nil {
 
 func (m *CrossChainInput) GetMainchainOutputId() *Hash {
        if m != nil {
@@ -708,6 +734,13 @@ func (m *CrossChainInput) GetControlProgram() *Program {
        return nil
 }
 
        return nil
 }
 
+func (m *CrossChainInput) GetAssetDefinition() *AssetDefinition {
+       if m != nil {
+               return m.AssetDefinition
+       }
+       return nil
+}
+
 func (m *CrossChainInput) GetWitnessArguments() [][]byte {
        if m != nil {
                return m.WitnessArguments
 func (m *CrossChainInput) GetWitnessArguments() [][]byte {
        if m != nil {
                return m.WitnessArguments
@@ -727,6 +760,7 @@ func init() {
        proto.RegisterType((*Program)(nil), "bc.Program")
        proto.RegisterType((*AssetID)(nil), "bc.AssetID")
        proto.RegisterType((*AssetAmount)(nil), "bc.AssetAmount")
        proto.RegisterType((*Program)(nil), "bc.Program")
        proto.RegisterType((*AssetID)(nil), "bc.AssetID")
        proto.RegisterType((*AssetAmount)(nil), "bc.AssetAmount")
+       proto.RegisterType((*AssetDefinition)(nil), "bc.AssetDefinition")
        proto.RegisterType((*ValueSource)(nil), "bc.ValueSource")
        proto.RegisterType((*ValueDestination)(nil), "bc.ValueDestination")
        proto.RegisterType((*BlockHeader)(nil), "bc.BlockHeader")
        proto.RegisterType((*ValueSource)(nil), "bc.ValueSource")
        proto.RegisterType((*ValueDestination)(nil), "bc.ValueDestination")
        proto.RegisterType((*BlockHeader)(nil), "bc.BlockHeader")
@@ -747,62 +781,65 @@ func init() {
 func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
 func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-       // 898 bytes of a gzipped FileDescriptorProto
-       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0xdd, 0x6e, 0x23, 0x35,
-       0x14, 0x56, 0x66, 0xa6, 0x49, 0x7a, 0xd2, 0x6d, 0x1a, 0x77, 0x17, 0x46, 0x2b, 0x10, 0xd5, 0x48,
-       0x4b, 0x17, 0x21, 0x55, 0xfd, 0x59, 0x04, 0x17, 0x5c, 0x50, 0x5a, 0x96, 0xcd, 0xc5, 0x6a, 0x91,
-       0x5b, 0xe5, 0x76, 0xe4, 0xcc, 0xb8, 0x8d, 0xc5, 0x64, 0x1c, 0x6c, 0xcf, 0xd0, 0xed, 0x2b, 0x70,
-       0xcd, 0x05, 0x2f, 0xc2, 0x2b, 0x70, 0x81, 0x78, 0x26, 0x90, 0xcf, 0x78, 0xf2, 0xd3, 0xa4, 0xed,
-       0x56, 0x08, 0x01, 0x77, 0x39, 0xc7, 0xc7, 0xdf, 0xf9, 0xfc, 0xf9, 0x7c, 0x9e, 0x40, 0x7b, 0x98,
-       0xec, 0x4d, 0x94, 0x34, 0x92, 0x78, 0xc3, 0x24, 0x7a, 0x09, 0xc1, 0x2b, 0xa6, 0x47, 0x64, 0x13,
-       0xbc, 0x72, 0x3f, 0x6c, 0xec, 0x34, 0x9e, 0x37, 0xa9, 0x57, 0xee, 0x63, 0x7c, 0x10, 0x7a, 0x2e,
-       0x3e, 0xc0, 0xf8, 0x30, 0xf4, 0x5d, 0x7c, 0x88, 0xf1, 0x51, 0x18, 0xb8, 0xf8, 0x28, 0xfa, 0x12,
-       0x5a, 0xdf, 0x29, 0x79, 0xa9, 0xd8, 0x98, 0x7c, 0x08, 0x50, 0x8e, 0xe3, 0x92, 0x2b, 0x2d, 0x64,
-       0x8e, 0x90, 0x01, 0x5d, 0x2f, 0xc7, 0x83, 0x2a, 0x41, 0x08, 0x04, 0x89, 0x4c, 0x39, 0x62, 0x6f,
-       0x50, 0xfc, 0x1d, 0xf5, 0xa1, 0x75, 0xac, 0x35, 0x37, 0xfd, 0xd3, 0xbf, 0x4d, 0xe4, 0x35, 0x74,
-       0x10, 0xea, 0x78, 0x2c, 0x8b, 0xdc, 0x90, 0x8f, 0xa1, 0xcd, 0x6c, 0x18, 0x8b, 0x14, 0x41, 0x3b,
-       0x87, 0x9d, 0xbd, 0x61, 0xb2, 0xe7, 0xba, 0xd1, 0x16, 0x2e, 0xf6, 0x53, 0xf2, 0x1e, 0x34, 0x19,
-       0xee, 0xc0, 0x56, 0x01, 0x75, 0x51, 0x94, 0x41, 0x67, 0xc0, 0xb2, 0x82, 0x9f, 0xc9, 0x42, 0x25,
-       0x9c, 0x3c, 0x05, 0x5f, 0xf1, 0x0b, 0x87, 0xd4, 0xb6, 0x48, 0x56, 0x3d, 0x6a, 0x93, 0xe4, 0x19,
-       0xac, 0x95, 0xb6, 0x14, 0x11, 0x3a, 0x87, 0xdd, 0x69, 0x9f, 0x8a, 0x0a, 0xad, 0x56, 0xc9, 0x53,
-       0x68, 0x4f, 0xa4, 0x16, 0xc6, 0x8a, 0xe3, 0x63, 0xaf, 0x69, 0x1c, 0xfd, 0x00, 0x5b, 0xd8, 0xed,
-       0x94, 0x6b, 0x23, 0x72, 0x66, 0x73, 0xff, 0x74, 0xcb, 0x3f, 0x3d, 0xe8, 0x7c, 0x9d, 0xc9, 0xe4,
-       0xfb, 0x57, 0x9c, 0xa5, 0x5c, 0x91, 0x10, 0x5a, 0x8b, 0x57, 0x57, 0x87, 0x56, 0xa2, 0x11, 0x17,
-       0x97, 0xa3, 0xa9, 0x44, 0x55, 0x44, 0x5e, 0x40, 0x6f, 0xa2, 0x78, 0x29, 0x64, 0xa1, 0xe3, 0xa1,
-       0x45, 0xb2, 0x5a, 0xfb, 0x37, 0xe8, 0x76, 0xeb, 0x12, 0xec, 0xd5, 0x4f, 0xc9, 0x07, 0xb0, 0x6e,
-       0xc4, 0x98, 0x6b, 0xc3, 0xc6, 0x13, 0xbc, 0xbe, 0x80, 0xce, 0x12, 0xe4, 0x33, 0xe8, 0x19, 0xc5,
-       0x72, 0xcd, 0x12, 0x4b, 0x52, 0xc7, 0x4a, 0x4a, 0x13, 0xae, 0xdd, 0xc0, 0xdc, 0x9a, 0x2f, 0xa1,
-       0x52, 0x1a, 0xf2, 0x15, 0xbc, 0x3f, 0x97, 0x8b, 0xb5, 0x61, 0xa6, 0xd0, 0xf1, 0x88, 0xe9, 0x51,
-       0xd8, 0xbc, 0xb1, 0xf9, 0xc9, 0x5c, 0xe1, 0x19, 0xd6, 0xa1, 0x0f, 0x4e, 0x81, 0x2c, 0x23, 0x84,
-       0x2d, 0xdc, 0xfc, 0xc4, 0x6e, 0x3e, 0xbf, 0xb9, 0x8d, 0xf6, 0x96, 0x90, 0xc8, 0xa7, 0xd0, 0xfb,
-       0x51, 0x98, 0x9c, 0x6b, 0x1d, 0x33, 0x75, 0x59, 0x8c, 0x79, 0x6e, 0x74, 0xd8, 0xde, 0xf1, 0x9f,
-       0x6f, 0xd0, 0x2d, 0xb7, 0x70, 0x5c, 0xe7, 0xa3, 0x9f, 0x1b, 0xd0, 0x3e, 0xbf, 0xba, 0x57, 0xfe,
-       0x5d, 0xe8, 0x6a, 0xae, 0x04, 0xcb, 0xc4, 0x35, 0x4f, 0x63, 0x2d, 0xae, 0xb9, 0xbb, 0x87, 0xcd,
-       0x59, 0xfa, 0x4c, 0x5c, 0x73, 0xeb, 0x3f, 0x2b, 0x64, 0xac, 0x58, 0x7e, 0xc9, 0xdd, 0x7d, 0xa3,
-       0xb4, 0xd4, 0x26, 0xc8, 0x2e, 0x80, 0xe2, 0xba, 0xc8, 0xac, 0x25, 0x74, 0x18, 0xec, 0xf8, 0x0b,
-       0xb2, 0xac, 0x57, 0x6b, 0xfd, 0x54, 0x47, 0x07, 0xb0, 0x79, 0x7e, 0x35, 0xe0, 0x4a, 0x5c, 0xbc,
-       0xa5, 0x98, 0x24, 0x1f, 0x41, 0xc7, 0x49, 0x7a, 0xc1, 0x44, 0x86, 0x04, 0xdb, 0x14, 0xaa, 0xd4,
-       0x4b, 0x26, 0xb2, 0xe8, 0x02, 0x7a, 0x4b, 0xfa, 0xdc, 0x71, 0xa4, 0xcf, 0xe1, 0x51, 0x89, 0xf8,
-       0xb5, 0xce, 0x1e, 0xb2, 0x21, 0xa8, 0xf3, 0x42, 0x6b, 0xba, 0x51, 0x15, 0x56, 0x90, 0xd1, 0x1f,
-       0x0d, 0xf0, 0x5f, 0x17, 0x57, 0xe4, 0x13, 0x68, 0x69, 0x34, 0xa6, 0x0e, 0x1b, 0xb8, 0x15, 0x1d,
-       0x30, 0x67, 0x58, 0x5a, 0xaf, 0x93, 0x67, 0xd0, 0x9a, 0x54, 0x0f, 0x94, 0x33, 0x0b, 0xbe, 0x03,
-       0xee, 0xcd, 0xa2, 0xf5, 0x1a, 0xf9, 0x16, 0x1e, 0xd7, 0x37, 0x97, 0xce, 0x4c, 0xa8, 0x43, 0x1f,
-       0xe1, 0x1f, 0x4f, 0xe1, 0xe7, 0x1c, 0x4a, 0xb7, 0xdd, 0x8e, 0xb9, 0xdc, 0x2d, 0x23, 0x10, 0xdc,
-       0x32, 0x02, 0x12, 0xda, 0x27, 0x52, 0xe4, 0x43, 0xa6, 0x39, 0xf9, 0x06, 0xb6, 0x57, 0x30, 0x70,
-       0xfe, 0x5f, 0x4d, 0x80, 0x2c, 0x13, 0xb0, 0xfe, 0x62, 0x6a, 0x28, 0x8c, 0x62, 0xea, 0xad, 0x7b,
-       0x6b, 0x67, 0x89, 0xe8, 0xa7, 0x06, 0x6c, 0xf5, 0x73, 0xa3, 0xd8, 0xc9, 0x88, 0x89, 0xfc, 0x4d,
-       0x61, 0x26, 0x85, 0x21, 0xbb, 0xd0, 0xac, 0xd4, 0x72, 0xcd, 0x96, 0xc4, 0x74, 0xcb, 0xe4, 0x05,
-       0x74, 0x13, 0x99, 0x1b, 0x25, 0xb3, 0xf8, 0x0e, 0x4d, 0x37, 0x5d, 0x4d, 0xfd, 0x5d, 0x08, 0xa1,
-       0x25, 0x55, 0x2a, 0x72, 0x96, 0xb9, 0xa1, 0xac, 0x43, 0x64, 0x73, 0xa2, 0xa4, 0xd6, 0xff, 0x09,
-       0x36, 0xbf, 0x34, 0x00, 0x06, 0xd2, 0xf0, 0x7f, 0x99, 0x87, 0xfd, 0x50, 0x96, 0xd2, 0x70, 0x7c,
-       0x1c, 0x37, 0x28, 0xfe, 0x8e, 0x7e, 0x6f, 0xc0, 0xfa, 0x80, 0x1b, 0xd9, 0xcf, 0x2d, 0xb5, 0x7d,
-       0xe8, 0xea, 0x09, 0xcf, 0x4d, 0x2c, 0x91, 0xea, 0xec, 0x1b, 0x37, 0xf3, 0xf3, 0x23, 0x2c, 0xa8,
-       0x8e, 0xd2, 0x4f, 0x6f, 0x1b, 0x2e, 0xef, 0x81, 0xc3, 0xb5, 0x72, 0xb8, 0xfd, 0xd5, 0xc3, 0x3d,
-       0x7f, 0xc2, 0x60, 0x51, 0xe9, 0x37, 0x00, 0x94, 0x1b, 0xa1, 0xb8, 0x2d, 0x7c, 0x77, 0xa1, 0xe7,
-       0x00, 0xbd, 0x45, 0xc0, 0xdf, 0x1a, 0xb0, 0x76, 0x36, 0xe1, 0x79, 0xfa, 0xbf, 0x97, 0xe6, 0x57,
-       0x0f, 0xba, 0x33, 0x4b, 0x54, 0xd7, 0xfd, 0x05, 0x6c, 0x8f, 0x99, 0xc8, 0x13, 0x9b, 0xb9, 0xe3,
-       0x5c, 0xbd, 0x69, 0xd1, 0xf4, 0x6c, 0xef, 0xf8, 0x3f, 0xe1, 0x16, 0x09, 0xfc, 0x07, 0x4a, 0xb0,
-       0xc2, 0x08, 0xc1, 0xfd, 0x46, 0x58, 0x29, 0xdc, 0xda, 0xfd, 0xc2, 0x35, 0x17, 0x84, 0x1b, 0x36,
-       0xf1, 0xbf, 0xed, 0xd1, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xd2, 0x80, 0xe2, 0xa6, 0xe7, 0x0a,
-       0x00, 0x00,
+       // 960 bytes of a gzipped FileDescriptorProto
+       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x56, 0x4d, 0x6f, 0x1b, 0x37,
+       0x13, 0x86, 0x56, 0x6b, 0x49, 0x1e, 0x39, 0x96, 0x44, 0x27, 0xef, 0xbb, 0x08, 0x52, 0xd4, 0x58,
+       0x20, 0x75, 0x8a, 0x02, 0x86, 0x3f, 0xd2, 0x8f, 0x43, 0x51, 0xd4, 0xb5, 0x9b, 0x46, 0x87, 0x20,
+       0x05, 0x6d, 0xe8, 0xba, 0xa0, 0x76, 0x29, 0x89, 0xa8, 0xb4, 0x54, 0x49, 0xae, 0xea, 0xf8, 0x2f,
+       0xf4, 0xdc, 0x43, 0x7f, 0x51, 0x0f, 0x45, 0xff, 0x4e, 0xaf, 0x2d, 0x38, 0xcb, 0x95, 0x56, 0x1f,
+       0xb6, 0x13, 0x14, 0x45, 0xdb, 0xdb, 0xce, 0x70, 0xf8, 0xcc, 0x33, 0x0f, 0x67, 0xb8, 0x84, 0x46,
+       0x3f, 0x3e, 0x9c, 0x2a, 0x69, 0x24, 0xf1, 0xfa, 0x71, 0xf8, 0x02, 0xfc, 0x97, 0x4c, 0x8f, 0xc8,
+       0x2e, 0x78, 0xb3, 0xa3, 0xa0, 0xb2, 0x5f, 0x79, 0x56, 0xa3, 0xde, 0xec, 0x08, 0xed, 0xe3, 0xc0,
+       0x73, 0xf6, 0x31, 0xda, 0x27, 0x41, 0xd5, 0xd9, 0x27, 0x68, 0x9f, 0x06, 0xbe, 0xb3, 0x4f, 0xc3,
+       0xcf, 0xa1, 0xfe, 0xad, 0x92, 0x43, 0xc5, 0x26, 0xe4, 0x3d, 0x80, 0xd9, 0x24, 0x9a, 0x71, 0xa5,
+       0x85, 0x4c, 0x11, 0xd2, 0xa7, 0xdb, 0xb3, 0x49, 0x2f, 0x77, 0x10, 0x02, 0x7e, 0x2c, 0x13, 0x8e,
+       0xd8, 0x3b, 0x14, 0xbf, 0xc3, 0x2e, 0xd4, 0xcf, 0xb4, 0xe6, 0xa6, 0x7b, 0xf1, 0x97, 0x89, 0xbc,
+       0x82, 0x26, 0x42, 0x9d, 0x4d, 0x64, 0x96, 0x1a, 0xf2, 0x01, 0x34, 0x98, 0x35, 0x23, 0x91, 0x20,
+       0x68, 0xf3, 0xa4, 0x79, 0xd8, 0x8f, 0x0f, 0x5d, 0x36, 0x5a, 0xc7, 0xc5, 0x6e, 0x42, 0xfe, 0x07,
+       0x35, 0x86, 0x3b, 0x30, 0x95, 0x4f, 0x9d, 0x15, 0x0e, 0xa1, 0x85, 0xb1, 0x17, 0x7c, 0x20, 0x52,
+       0x61, 0x6c, 0x01, 0x9f, 0x40, 0x5b, 0x68, 0x9d, 0xb1, 0x34, 0xe6, 0xd1, 0x34, 0xaf, 0xb9, 0x0c,
+       0xed, 0x64, 0xa0, 0xad, 0x22, 0xa8, 0xd0, 0xe5, 0x09, 0xf8, 0x09, 0x33, 0x0c, 0x13, 0x34, 0x4f,
+       0x1a, 0x36, 0xd6, 0x4a, 0x4f, 0xd1, 0x1b, 0x8e, 0xa1, 0xd9, 0x63, 0xe3, 0x8c, 0x5f, 0xca, 0x4c,
+       0xc5, 0x9c, 0x3c, 0x86, 0xaa, 0xe2, 0x03, 0x87, 0xbb, 0x88, 0xb5, 0x4e, 0xf2, 0x14, 0xb6, 0x66,
+       0x36, 0xd4, 0x21, 0xb5, 0xe6, 0x05, 0xe5, 0x35, 0xd3, 0x7c, 0x95, 0x3c, 0x86, 0xc6, 0x54, 0x6a,
+       0xe4, 0x8c, 0x7a, 0xf9, 0x74, 0x6e, 0x87, 0xdf, 0x43, 0x1b, 0xb3, 0x5d, 0x70, 0x6d, 0x44, 0xca,
+       0xb0, 0xae, 0xbf, 0x39, 0xe5, 0x1f, 0x1e, 0x34, 0xbf, 0x1a, 0xcb, 0xf8, 0xbb, 0x97, 0x9c, 0x25,
+       0x5c, 0x91, 0x00, 0xea, 0xcb, 0x3d, 0x52, 0x98, 0xf6, 0x2c, 0x46, 0x5c, 0x0c, 0x47, 0xf3, 0xb3,
+       0xc8, 0x2d, 0xf2, 0x1c, 0x3a, 0x53, 0xc5, 0x67, 0x42, 0x66, 0x3a, 0xea, 0x5b, 0x24, 0x7b, 0xa8,
+       0xd5, 0x15, 0xba, 0xad, 0x22, 0x04, 0x73, 0x75, 0x13, 0xf2, 0x04, 0xb6, 0x8d, 0x98, 0x70, 0x6d,
+       0xd8, 0x64, 0x8a, 0x7d, 0xe2, 0xd3, 0x85, 0x83, 0x7c, 0x0c, 0x1d, 0xa3, 0x58, 0xaa, 0x59, 0x6c,
+       0x49, 0xea, 0x48, 0x49, 0x69, 0x82, 0xad, 0x15, 0xcc, 0x76, 0x39, 0x84, 0x4a, 0x69, 0xc8, 0x97,
+       0xf0, 0xff, 0x92, 0x2f, 0xd2, 0x86, 0x99, 0x4c, 0x47, 0x23, 0xa6, 0x47, 0x41, 0x6d, 0x65, 0xf3,
+       0xa3, 0x52, 0xe0, 0x25, 0xc6, 0xe1, 0xc0, 0x5d, 0x00, 0x59, 0x47, 0x08, 0xea, 0xb8, 0xf9, 0x91,
+       0xdd, 0x7c, 0xb5, 0xba, 0x8d, 0x76, 0xd6, 0x90, 0xc8, 0x47, 0xd0, 0xf9, 0x41, 0x98, 0x94, 0x6b,
+       0x1d, 0x31, 0x35, 0xcc, 0x26, 0x3c, 0x35, 0x3a, 0x68, 0xec, 0x57, 0x9f, 0xed, 0xd0, 0xb6, 0x5b,
+       0x38, 0x2b, 0xfc, 0xe1, 0x4f, 0x15, 0x68, 0x5c, 0x5d, 0xdf, 0x2b, 0xff, 0x01, 0xb4, 0x34, 0x57,
+       0x82, 0x8d, 0xc5, 0x0d, 0x4f, 0x22, 0x2d, 0x6e, 0xb8, 0x3b, 0x87, 0xdd, 0x85, 0xfb, 0x52, 0xdc,
+       0x70, 0x3b, 0xe8, 0x56, 0xc8, 0x48, 0xb1, 0x74, 0xc8, 0xdd, 0x79, 0xa3, 0xb4, 0xd4, 0x3a, 0xc8,
+       0x01, 0x80, 0xe2, 0x3a, 0x1b, 0xdb, 0xd9, 0xd3, 0x81, 0xbf, 0x5f, 0x5d, 0x92, 0x65, 0x3b, 0x5f,
+       0xeb, 0x26, 0x3a, 0x3c, 0x86, 0xdd, 0xab, 0xeb, 0x1e, 0x57, 0x62, 0xf0, 0x86, 0xa2, 0x93, 0xbc,
+       0x0f, 0x4d, 0x27, 0xe9, 0x80, 0x89, 0x31, 0x12, 0x6c, 0x50, 0xc8, 0x5d, 0x2f, 0x98, 0x18, 0x87,
+       0x03, 0xe8, 0xac, 0xe9, 0x73, 0x47, 0x49, 0x9f, 0xc2, 0x83, 0x19, 0xe2, 0x17, 0x3a, 0x7b, 0xc8,
+       0x86, 0xa0, 0xce, 0x4b, 0xa9, 0xe9, 0x4e, 0x1e, 0x98, 0x43, 0x86, 0xbf, 0x55, 0xa0, 0xfa, 0x2a,
+       0xbb, 0x26, 0x1f, 0x42, 0x5d, 0xe3, 0x60, 0xea, 0xa0, 0x82, 0x5b, 0x71, 0x02, 0x4a, 0x03, 0x4b,
+       0x8b, 0x75, 0xf2, 0x14, 0xea, 0xc5, 0xad, 0xe0, 0xad, 0xdf, 0x0a, 0xc5, 0x1a, 0xf9, 0x06, 0x1e,
+       0x16, 0x27, 0x97, 0x2c, 0x86, 0x50, 0x07, 0x55, 0x84, 0x7f, 0x38, 0x87, 0x2f, 0x4d, 0x28, 0xdd,
+       0x73, 0x3b, 0x4a, 0xbe, 0x5b, 0x5a, 0xc0, 0xbf, 0xa5, 0x05, 0x24, 0x34, 0xce, 0xa5, 0x48, 0xfb,
+       0x4c, 0x73, 0xf2, 0x35, 0xec, 0x6d, 0x60, 0xe0, 0xe6, 0x7f, 0x33, 0x01, 0xb2, 0x4e, 0xc0, 0xce,
+       0x17, 0x53, 0x7d, 0x61, 0x14, 0x53, 0x6f, 0xdc, 0xa5, 0xbe, 0x70, 0x84, 0x3f, 0x56, 0xa0, 0xdd,
+       0x4d, 0x8d, 0x62, 0xe7, 0x23, 0x26, 0xd2, 0xd7, 0x99, 0x99, 0x66, 0x86, 0x1c, 0x40, 0x2d, 0x57,
+       0xcb, 0x25, 0x5b, 0x13, 0xd3, 0x2d, 0x93, 0xe7, 0xd0, 0x8a, 0x65, 0x6a, 0x94, 0x1c, 0x47, 0x77,
+       0x68, 0xba, 0xeb, 0x62, 0x8a, 0x8b, 0x36, 0x80, 0xba, 0x54, 0x89, 0x48, 0xd9, 0xd8, 0x35, 0x65,
+       0x61, 0x22, 0x9b, 0x73, 0x25, 0xb5, 0xfe, 0x57, 0xb0, 0xf9, 0xb9, 0x02, 0xd0, 0x93, 0x86, 0xff,
+       0xc3, 0x3c, 0xec, 0x1f, 0x79, 0x26, 0x0d, 0xc7, 0xcb, 0x71, 0x87, 0xe2, 0x77, 0xf8, 0x6b, 0x05,
+       0xb6, 0x7b, 0xdc, 0xc8, 0x6e, 0x6a, 0xa9, 0x1d, 0x41, 0x4b, 0x4f, 0x79, 0x6a, 0x22, 0x89, 0x54,
+       0x17, 0x3f, 0xd3, 0xc5, 0x3c, 0x3f, 0xc0, 0x80, 0xbc, 0x94, 0x6e, 0x72, 0x5b, 0x73, 0x79, 0xef,
+       0xd8, 0x5c, 0x1b, 0x9b, 0xbb, 0xba, 0xb9, 0xb9, 0xcb, 0x15, 0xfa, 0xcb, 0x4a, 0xbf, 0x06, 0xa0,
+       0xdc, 0x08, 0xc5, 0x6d, 0xe0, 0xdb, 0x0b, 0x5d, 0x02, 0xf4, 0x96, 0x01, 0x7f, 0xa9, 0xc0, 0xd6,
+       0xe5, 0x94, 0xa7, 0xc9, 0x7f, 0x5e, 0x9a, 0xdf, 0x3d, 0x68, 0x2d, 0x46, 0x22, 0x3f, 0xee, 0xcf,
+       0x60, 0x6f, 0xc2, 0x44, 0x1a, 0x5b, 0xcf, 0x1d, 0x75, 0x75, 0xe6, 0x41, 0xf3, 0xda, 0xde, 0xf2,
+       0x9d, 0x70, 0x8b, 0x04, 0xd5, 0x77, 0x94, 0x60, 0xc3, 0x20, 0xf8, 0xf7, 0x0f, 0xc2, 0x17, 0xd0,
+       0xce, 0x9f, 0x84, 0xc9, 0xfc, 0x4d, 0xe7, 0xfe, 0xf8, 0x7b, 0x73, 0xba, 0x8b, 0xe7, 0x1e, 0x6d,
+       0xb1, 0x95, 0xf7, 0xdf, 0x46, 0xe1, 0x6b, 0xf7, 0x0b, 0x5f, 0x5f, 0x12, 0xbe, 0x5f, 0xc3, 0x47,
+       0xf8, 0xe9, 0x9f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x2b, 0x1b, 0x9e, 0x47, 0x90, 0x0b, 0x00, 0x00,
 }
 }
index 827100b..d3085c0 100644 (file)
@@ -31,6 +31,11 @@ message AssetAmount {
   uint64  amount   = 2;
 }
 
   uint64  amount   = 2;
 }
 
+message AssetDefinition {
+  Program issuance_program = 1;
+  Hash    data             = 2;
+}
+
 message ValueSource {
   Hash        ref      = 1;
   AssetAmount value    = 2;
 message ValueSource {
   Hash        ref      = 1;
   AssetAmount value    = 2;
@@ -121,10 +126,11 @@ message Spend {
 }
 
 message CrossChainInput {
 }
 
 message CrossChainInput {
-  Hash             mainchain_output_id = 1;
-  AssetAmount      value               = 2;
-  ValueDestination witness_destination = 3;
-  Program          control_program     = 4;
-  repeated bytes   witness_arguments   = 5;
-  uint64           ordinal             = 6;
-}
\ No newline at end of file
+  Hash             mainchain_output_id       = 1;
+  AssetAmount      value                     = 2;
+  ValueDestination witness_destination       = 3;
+  Program          control_program           = 4;
+  AssetDefinition  asset_definition          = 5;
+  repeated bytes   witness_arguments         = 6;
+  uint64           ordinal                   = 7;
+}
index 63515f2..123ce25 100644 (file)
@@ -9,6 +9,8 @@ func (CrossChainInput) typ() string { return "crosschaininput1" }
 
 func (cci *CrossChainInput) writeForHash(w io.Writer) {
        mustWriteForHash(w, cci.MainchainOutputId)
 
 func (cci *CrossChainInput) writeForHash(w io.Writer) {
        mustWriteForHash(w, cci.MainchainOutputId)
+       mustWriteForHash(w, cci.Value)
+       mustWriteForHash(w, cci.AssetDefinition)
 }
 
 // SetDestination will link the CrossChainInput to the output
 }
 
 // SetDestination will link the CrossChainInput to the output
@@ -21,11 +23,12 @@ func (cci *CrossChainInput) SetDestination(id *Hash, val *AssetAmount, pos uint6
 }
 
 // NewCrossChainInput creates a new CrossChainInput.
 }
 
 // NewCrossChainInput creates a new CrossChainInput.
-func NewCrossChainInput(mainchainOutputID *Hash, value *AssetAmount, prog *Program, ordinal uint64) *CrossChainInput {
+func NewCrossChainInput(mainchainOutputID *Hash, value *AssetAmount, prog *Program, ordinal uint64, assetDef *AssetDefinition) *CrossChainInput {
        return &CrossChainInput{
                MainchainOutputId: mainchainOutputID,
                Value:             value,
                Ordinal:           ordinal,
                ControlProgram:    prog,
        return &CrossChainInput{
                MainchainOutputId: mainchainOutputID,
                Value:             value,
                Ordinal:           ordinal,
                ControlProgram:    prog,
+               AssetDefinition:   assetDef,
        }
 }
        }
 }
index a08cfd6..e29673d 100644 (file)
@@ -6,16 +6,19 @@ import (
 
 // CrossChainInput satisfies the TypedInput interface and represents a cross-chain transaction.
 type CrossChainInput struct {
 
 // CrossChainInput satisfies the TypedInput interface and represents a cross-chain transaction.
 type CrossChainInput struct {
-       AssetDefinition       []byte
        SpendCommitmentSuffix []byte   // The unconsumed suffix of the spend commitment
        Arguments             [][]byte // Witness
        SpendCommitment
        SpendCommitmentSuffix []byte   // The unconsumed suffix of the spend commitment
        Arguments             [][]byte // Witness
        SpendCommitment
+
+       VMVersion       uint64
+       AssetDefinition []byte
+       IssuanceProgram []byte
 }
 
 // NewCrossChainInput create a new CrossChainInput struct.
 // The source is created/issued by trusted federation and hence there is no need
 // to refer to it.
 }
 
 // NewCrossChainInput create a new CrossChainInput struct.
 // The source is created/issued by trusted federation and hence there is no need
 // to refer to it.
-func NewCrossChainInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, amount, sourcePos uint64, controlProgram, assetDefinition []byte) *TxInput {
+func NewCrossChainInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, amount, sourcePos, vmVersion uint64, assetDefinition, issuanceProgram []byte) *TxInput {
        sc := SpendCommitment{
                AssetAmount: bc.AssetAmount{
                        AssetId: &assetID,
        sc := SpendCommitment{
                AssetAmount: bc.AssetAmount{
                        AssetId: &assetID,
@@ -24,14 +27,15 @@ func NewCrossChainInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID
                SourceID:       sourceID,
                SourcePosition: sourcePos,
                VMVersion:      1,
                SourceID:       sourceID,
                SourcePosition: sourcePos,
                VMVersion:      1,
-               ControlProgram: controlProgram,
        }
        return &TxInput{
                AssetVersion: 1,
                TypedInput: &CrossChainInput{
        }
        return &TxInput{
                AssetVersion: 1,
                TypedInput: &CrossChainInput{
-                       AssetDefinition: assetDefinition,
                        SpendCommitment: sc,
                        Arguments:       arguments,
                        SpendCommitment: sc,
                        Arguments:       arguments,
+                       VMVersion:       vmVersion,
+                       AssetDefinition: assetDefinition,
+                       IssuanceProgram: issuanceProgram,
                },
        }
 }
                },
        }
 }
index fc3ac58..afc9201 100644 (file)
@@ -11,7 +11,7 @@ type CrossChainOutput struct {
        CommitmentSuffix []byte
 }
 
        CommitmentSuffix []byte
 }
 
-// CrossChainOutput create a new output struct
+// NewCrossChainOutput create a new output struct
 func NewCrossChainOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *TxOutput {
        return &TxOutput{
                AssetVersion: 1,
 func NewCrossChainOutput(assetID bc.AssetID, amount uint64, controlProgram []byte) *TxOutput {
        return &TxOutput{
                AssetVersion: 1,
index 170b9f0..0fe229d 100644 (file)
@@ -2,6 +2,7 @@ package types
 
 import (
        log "github.com/sirupsen/logrus"
 
 import (
        log "github.com/sirupsen/logrus"
+       "golang.org/x/crypto/sha3"
 
        "github.com/vapor/consensus"
        "github.com/vapor/protocol/bc"
 
        "github.com/vapor/consensus"
        "github.com/vapor/protocol/bc"
@@ -140,16 +141,26 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
                        vetoInputs = append(vetoInputs, vetoInput)
 
                case *CrossChainInput:
                        vetoInputs = append(vetoInputs, vetoInput)
 
                case *CrossChainInput:
-                       // TODO: fed peg script
                        prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
                        src := &bc.ValueSource{
                                Ref:      &inp.SourceID,
                                Value:    &inp.AssetAmount,
                                Position: inp.SourcePosition,
                        }
                        prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
                        src := &bc.ValueSource{
                                Ref:      &inp.SourceID,
                                Value:    &inp.AssetAmount,
                                Position: inp.SourcePosition,
                        }
+
                        prevout := bc.NewIntraChainOutput(src, prog, 0) // ordinal doesn't matter
                        outputID := bc.EntryID(prevout)
                        prevout := bc.NewIntraChainOutput(src, prog, 0) // ordinal doesn't matter
                        outputID := bc.EntryID(prevout)
-                       crossIn := bc.NewCrossChainInput(&outputID, &inp.AssetAmount, prog, uint64(i))
+
+                       assetDefHash := bc.NewHash(sha3.Sum256(inp.AssetDefinition))
+                       assetDef := &bc.AssetDefinition{
+                               Data: &assetDefHash,
+                               IssuanceProgram: &bc.Program{
+                                       VmVersion: inp.VMVersion,
+                                       Code:      inp.IssuanceProgram,
+                               },
+                       }
+
+                       crossIn := bc.NewCrossChainInput(&outputID, &inp.AssetAmount, prog, uint64(i), assetDef)
                        crossIn.WitnessArguments = inp.Arguments
                        crossInID := addEntry(crossIn)
                        muxSources[i] = &bc.ValueSource{
                        crossIn.WitnessArguments = inp.Arguments
                        crossInID := addEntry(crossIn)
                        muxSources[i] = &bc.ValueSource{
index 47831cc..4918841 100644 (file)
@@ -210,6 +210,18 @@ func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
                                return err
                        }
 
                                return err
                        }
 
+                       if inp.VMVersion, err = blockchain.ReadVarint63(r); err != nil {
+                               return err
+                       }
+
+                       if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
+                               return err
+                       }
+
+                       if inp.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
+                               return err
+                       }
+
                case *VetoInput:
                        if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
                                return err
                case *VetoInput:
                        if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
                                return err
@@ -225,13 +237,6 @@ func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
                return err
        }
 
                return err
        }
 
-       switch inp := t.TypedInput.(type) {
-       case *CrossChainInput:
-               if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
-                       return err
-               }
-       }
-
        return nil
 }
 
        return nil
 }
 
@@ -248,13 +253,6 @@ func (t *TxInput) writeTo(w io.Writer) error {
                return errors.Wrap(err, "writing input witness")
        }
 
                return errors.Wrap(err, "writing input witness")
        }
 
-       switch inp := t.TypedInput.(type) {
-       case *CrossChainInput:
-               if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
-                       return errors.Wrap(err, "writing AssetDefinition")
-               }
-       }
-
        return nil
 }
 
        return nil
 }
 
@@ -304,7 +302,20 @@ func (t *TxInput) writeInputWitness(w io.Writer) error {
                return err
 
        case *CrossChainInput:
                return err
 
        case *CrossChainInput:
-               _, err := blockchain.WriteVarstrList(w, inp.Arguments)
+               if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
+                       return err
+               }
+
+               if _, err := blockchain.WriteVarint63(w, inp.VMVersion); err != nil {
+                       return err
+               }
+
+               if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
+                       return err
+               }
+
+               _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram)
+
                return err
        case *VetoInput:
                if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
                return err
        case *VetoInput:
                if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
index 884d672..419b3cd 100644 (file)
@@ -71,28 +71,31 @@ func TestSerializationCrossIn(t *testing.T) {
                []byte("arguments1"),
                []byte("arguments2"),
        }
                []byte("arguments1"),
                []byte("arguments2"),
        }
-       crossIn := NewCrossChainInput(arguments, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), testutil.MustDecodeAsset("fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a"), 254354, 3, []byte("crossInProgram"), []byte("whatever"))
+
+       crossIn := NewCrossChainInput(arguments, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), testutil.MustDecodeAsset("fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a"), 254354, 3, 1, []byte("whatever"), []byte("IssuanceProgram"))
 
        wantHex := strings.Join([]string{
                "01", // asset version
 
        wantHex := strings.Join([]string{
                "01", // asset version
-               "56", // input commitment length
+               "48", // input commitment length
                "00", // cross-chain input type flag
                "00", // cross-chain input type flag
-               "54", // cross-chain input commitment length
+               "46", // cross-chain input commitment length
                "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // source id
                "fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a", // assetID
                "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // source id
                "fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a", // assetID
-               "92c30f",                       // amount
-               "03",                           // source position
-               "01",                           // vm version
-               "0e",                           // spend program length
-               "63726f7373496e50726f6772616d", // spend program
-               "17",                           // witness length
-               "02",                           // argument array length
-               "0a",                           // first argument length
-               "617267756d656e747331",         // first argument data
-               "0a",                           // second argument length
-               "617267756d656e747332",         // second argument data
-               "08",                           // asset definition length
-               "7768617465766572",             // asset definition data
+               "92c30f",                         // amount
+               "03",                             // source position
+               "01",                             // vm version
+               "00",                             // spend program length
+               "31",                             // witness length
+               "02",                             // argument array length
+               "0a",                             // first argument length
+               "617267756d656e747331",           // first argument data
+               "0a",                             // second argument length
+               "617267756d656e747332",           // second argument data
+               "01",                             // VmVersion
+               "08",                             // asset definition length
+               "7768617465766572",               // asset definition data
+               "0f",                             // IssuanceProgram length
+               "49737375616e636550726f6772616d", // IssuanceProgram
        }, "")
 
        // Test convert struct to hex
        }, "")
 
        // Test convert struct to hex
index a34107a..f0ebe94 100644 (file)
@@ -4,7 +4,7 @@ import (
        "github.com/vapor/protocol/bc"
 )
 
        "github.com/vapor/protocol/bc"
 )
 
-// VoteOutput satisfies the TypedOutput interface and represents a vote transaction.
+// VoteTxOutput satisfies the TypedOutput interface and represents a vote transaction.
 type VoteTxOutput struct {
        OutputCommitment
        // Unconsumed suffixes of the commitment and witness extensible strings.
 type VoteTxOutput struct {
        OutputCommitment
        // Unconsumed suffixes of the commitment and witness extensible strings.
index ce5feac..0768d88 100644 (file)
@@ -1,7 +1,6 @@
 package validation
 
 import (
 package validation
 
 import (
-       "bytes"
        "fmt"
        "math"
 
        "fmt"
        "math"
 
@@ -249,7 +248,17 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                }
 
        case *bc.CrossChainInput:
                }
 
        case *bc.CrossChainInput:
-               _, err := vm.Verify(NewTxVMContext(vs, e, e.ControlProgram, e.WitnessArguments), consensus.DefaultGasCredit)
+               // check assetID
+               assetID := e.AssetDefinition.ComputeAssetID()
+               if *e.Value.AssetId != *consensus.BTMAssetID && *e.Value.AssetId != assetID {
+                       return errors.New("incorrect asset_id while check CrossChainInput")
+               }
+               code := config.FederationProgrom(config.CommonConfig)
+               prog := &bc.Program{
+                       VmVersion: e.ControlProgram.VmVersion,
+                       Code:      code,
+               }
+               _, err := vm.Verify(NewTxVMContext(vs, e, prog, e.WitnessArguments), consensus.DefaultGasCredit)
                if err != nil {
                        return errors.Wrap(err, "checking cross-chain input control program")
                }
                if err != nil {
                        return errors.Wrap(err, "checking cross-chain input control program")
                }
@@ -515,21 +524,6 @@ func checkValidDest(vs *validationState, vd *bc.ValueDestination) error {
        return nil
 }
 
        return nil
 }
 
-func checkFedaration(tx *bc.Tx) error {
-       for _, id := range tx.InputIDs {
-               switch inp := tx.Entries[id].(type) {
-               case *bc.CrossChainInput:
-                       fedProg := config.FederationProgrom(config.CommonConfig)
-                       if !bytes.Equal(inp.ControlProgram.Code, fedProg) {
-                               return errors.New("The federal controlProgram is incorrect")
-                       }
-               default:
-                       continue
-               }
-       }
-       return nil
-}
-
 func checkStandardTx(tx *bc.Tx, blockHeight uint64) error {
        for _, id := range tx.InputIDs {
                if blockHeight >= ruleAA && id.IsZero() {
 func checkStandardTx(tx *bc.Tx, blockHeight uint64) error {
        for _, id := range tx.InputIDs {
                if blockHeight >= ruleAA && id.IsZero() {
@@ -537,10 +531,6 @@ func checkStandardTx(tx *bc.Tx, blockHeight uint64) error {
                }
        }
 
                }
        }
 
-       if err := checkFedaration(tx); err != nil {
-               return err
-       }
-
        for _, id := range tx.GasInputIDs {
                spend, err := tx.Spend(id)
                if err != nil {
        for _, id := range tx.GasInputIDs {
                spend, err := tx.Spend(id)
                if err != nil {
index 61d8e3b..86450ba 100644 (file)
@@ -671,8 +671,8 @@ func TestTxOutToUtxos(t *testing.T) {
                {
                        tx: types.NewTx(types.TxData{
                                Inputs: []*types.TxInput{
                {
                        tx: types.NewTx(types.TxData{
                                Inputs: []*types.TxInput{
-                                       types.NewCrossChainInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, []byte{0x51}, []byte("asset1")),
-                                       types.NewCrossChainInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, []byte{0x51}, []byte("assetbtm"))},
+                                       types.NewCrossChainInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 5, 1, 1, []byte("asset1"), []byte("IssuanceProgram")),
+                                       types.NewCrossChainInput([][]byte{}, bc.Hash{V0: 2}, *consensus.BTMAssetID, 7, 1, 1, []byte("assetbtm"), []byte("IssuanceProgram"))},
                                Outputs: []*types.TxOutput{
                                        types.NewIntraChainOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
                                        types.NewIntraChainOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
                                Outputs: []*types.TxOutput{
                                        types.NewIntraChainOutput(bc.AssetID{V0: 1}, 2, []byte{0x51}),
                                        types.NewIntraChainOutput(bc.AssetID{V0: 1}, 3, []byte{0x52}),
@@ -684,35 +684,35 @@ func TestTxOutToUtxos(t *testing.T) {
                        blockHeight: 0,
                        wantUtxos: []*account.UTXO{
                                &account.UTXO{
                        blockHeight: 0,
                        wantUtxos: []*account.UTXO{
                                &account.UTXO{
-                                       OutputID:       bc.Hash{V0: 396952592194652166, V1: 9806684391645699244, V2: 484243382648745315, V3: 16988093808435014689},
+                                       OutputID:       bc.Hash{V0: 5429526025956869574, V1: 12188959875155232503, V2: 14722092106507294798, V3: 27876074648890075},
                                        AssetID:        bc.AssetID{V0: 1},
                                        Amount:         2,
                                        ControlProgram: []byte{0x51},
                                        AssetID:        bc.AssetID{V0: 1},
                                        Amount:         2,
                                        ControlProgram: []byte{0x51},
-                                       SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
+                                       SourceID:       bc.Hash{V0: 10187915247323429348, V1: 4770401581694266753, V2: 4182269187154655368, V3: 9030883832705174512},
                                        SourcePos:      0,
                                },
                                &account.UTXO{
                                        SourcePos:      0,
                                },
                                &account.UTXO{
-                                       OutputID:       bc.Hash{V0: 10880631720641638863, V1: 7783872056988487492, V2: 10925792818362846534, V3: 16483659407709834456},
+                                       OutputID:       bc.Hash{V0: 18100481287404207387, V1: 3365694797435565990, V2: 8136211093499423216, V3: 12028531817690438568},
                                        AssetID:        bc.AssetID{V0: 1},
                                        Amount:         3,
                                        ControlProgram: []byte{0x52},
                                        AssetID:        bc.AssetID{V0: 1},
                                        Amount:         3,
                                        ControlProgram: []byte{0x52},
-                                       SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
+                                       SourceID:       bc.Hash{V0: 10187915247323429348, V1: 4770401581694266753, V2: 4182269187154655368, V3: 9030883832705174512},
                                        SourcePos:      1,
                                },
                                &account.UTXO{
                                        SourcePos:      1,
                                },
                                &account.UTXO{
-                                       OutputID:       bc.Hash{V0: 6688768820716928311, V1: 7640171490156205612, V2: 6082620342644961312, V3: 6194446985740174532},
+                                       OutputID:       bc.Hash{V0: 15745816911932387102, V1: 5035893487696724781, V2: 10084725527786878517, V3: 11270352747873435606},
                                        AssetID:        *consensus.BTMAssetID,
                                        Amount:         2,
                                        ControlProgram: []byte{0x53},
                                        AssetID:        *consensus.BTMAssetID,
                                        Amount:         2,
                                        ControlProgram: []byte{0x53},
-                                       SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
+                                       SourceID:       bc.Hash{V0: 10187915247323429348, V1: 4770401581694266753, V2: 4182269187154655368, V3: 9030883832705174512},
                                        SourcePos:      2,
                                },
                                &account.UTXO{
                                        SourcePos:      2,
                                },
                                &account.UTXO{
-                                       OutputID:       bc.Hash{V0: 13540722642395030514, V1: 15412939347183859286, V2: 9545016219428105666, V3: 11940603522975438116},
+                                       OutputID:       bc.Hash{V0: 10165799535720725897, V1: 9618876671942765420, V2: 17982649347111502590, V3: 15837286550437859084},
                                        AssetID:        *consensus.BTMAssetID,
                                        Amount:         5,
                                        ControlProgram: []byte{0x54},
                                        AssetID:        *consensus.BTMAssetID,
                                        Amount:         5,
                                        ControlProgram: []byte{0x54},
-                                       SourceID:       bc.Hash{V0: 15256474482236132139, V1: 14615963227748152009, V2: 1392768713126269609, V3: 3435801067785833027},
+                                       SourceID:       bc.Hash{V0: 10187915247323429348, V1: 4770401581694266753, V2: 4182269187154655368, V3: 9030883832705174512},
                                        SourcePos:      3,
                                },
                        },
                                        SourcePos:      3,
                                },
                        },