OSDN Git Service

add cancel vote (#172)
authorwz <mars@bytom.io>
Thu, 13 Jun 2019 08:50:23 +0000 (16:50 +0800)
committerPaladz <yzhu101@uottawa.ca>
Thu, 13 Jun 2019 08:50:23 +0000 (16:50 +0800)
* add cancel vote

* fix review

* modify name

* fix review

* fix test

* fix test

20 files changed:
account/builder.go
blockchain/txfeed/txfeed.go
protocol/bc/bc.pb.go
protocol/bc/bc.proto
protocol/bc/tx.go
protocol/bc/types/map.go
protocol/bc/types/transaction.go
protocol/bc/types/txinput.go
protocol/bc/types/txinput_test.go
protocol/bc/types/txoutput.go
protocol/bc/types/txoutput_test.go
protocol/bc/types/veto_input.go [moved from protocol/bc/types/unvote.go with 61% similarity]
protocol/bc/veto_input.go [new file with mode: 0644]
protocol/bc/vote_output.go
protocol/state/vote_result.go
protocol/validation/tx.go
protocol/validation/vmcontext.go
wallet/annotated.go
wallet/utxo.go
wallet/utxo_test.go

index af0c0a1..fe96d74 100644 (file)
@@ -313,7 +313,7 @@ func UtxoToInputs(signer *signers.Signer, u *UTXO) (*types.TxInput, *txbuilder.S
        if u.Vote == nil {
                txInput = types.NewSpendInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram)
        } else {
-               txInput = types.NewUnvoteInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram, u.Vote)
+               txInput = types.NewVetoInput(nil, u.SourceID, u.AssetID, u.Amount, u.SourcePos, u.ControlProgram, u.Vote)
        }
        sigInst := &txbuilder.SigningInstruction{}
        if signer == nil {
index 01691eb..6397990 100644 (file)
@@ -358,6 +358,11 @@ func buildAnnotatedInput(tx *types.Tx, i uint32) *query.AnnotatedInput {
                in.Type = "cross_chain_in"
                in.ControlProgram = orig.ControlProgram()
                in.SpentOutputID = e.MainchainOutputId
+
+       case *bc.VetoInput:
+               in.Type = "veto"
+               in.ControlProgram = orig.ControlProgram()
+               in.SpentOutputID = e.SpentOutputId
        }
 
        return in
@@ -378,7 +383,16 @@ func buildAnnotatedOutput(tx *types.Tx, idx int) *query.AnnotatedOutput {
        if vmutil.IsUnspendable(out.ControlProgram) {
                out.Type = "retire"
        } else {
-               out.Type = "control"
+               e := tx.Entries[*outid]
+               switch e.(type) {
+               case *bc.CrossChainOutput:
+                       out.Type = "crosschain_output"
+               case *bc.IntraChainOutput:
+                       out.Type = "control"
+               case *bc.VoteOutput:
+                       out.Type = "vote_control"
+               }
        }
+
        return out
 }
index 6b0a50a..fbffe83 100644 (file)
@@ -23,6 +23,7 @@ It has these top-level messages:
        IntraChainOutput
        CrossChainOutput
        VoteOutput
+       VetoInput
        Retirement
        Spend
        CrossChainInput
@@ -561,6 +562,46 @@ func (m *VoteOutput) GetVote() []byte {
        return nil
 }
 
+type VetoInput struct {
+       SpentOutputId      *Hash             `protobuf:"bytes,1,opt,name=spent_output_id,json=spentOutputId" json:"spent_output_id,omitempty"`
+       WitnessDestination *ValueDestination `protobuf:"bytes,2,opt,name=witness_destination,json=witnessDestination" json:"witness_destination,omitempty"`
+       WitnessArguments   [][]byte          `protobuf:"bytes,3,rep,name=witness_arguments,json=witnessArguments,proto3" json:"witness_arguments,omitempty"`
+       Ordinal            uint64            `protobuf:"varint,4,opt,name=ordinal" json:"ordinal,omitempty"`
+}
+
+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 (m *VetoInput) GetSpentOutputId() *Hash {
+       if m != nil {
+               return m.SpentOutputId
+       }
+       return nil
+}
+
+func (m *VetoInput) GetWitnessDestination() *ValueDestination {
+       if m != nil {
+               return m.WitnessDestination
+       }
+       return nil
+}
+
+func (m *VetoInput) GetWitnessArguments() [][]byte {
+       if m != nil {
+               return m.WitnessArguments
+       }
+       return nil
+}
+
+func (m *VetoInput) GetOrdinal() uint64 {
+       if m != nil {
+               return m.Ordinal
+       }
+       return 0
+}
+
 type Retirement struct {
        Source  *ValueSource `protobuf:"bytes,1,opt,name=source" json:"source,omitempty"`
        Ordinal uint64       `protobuf:"varint,2,opt,name=ordinal" json:"ordinal,omitempty"`
@@ -569,7 +610,7 @@ type Retirement struct {
 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{15} }
+func (*Retirement) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
 
 func (m *Retirement) GetSource() *ValueSource {
        if m != nil {
@@ -595,7 +636,7 @@ type Spend struct {
 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{16} }
+func (*Spend) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
 
 func (m *Spend) GetSpentOutputId() *Hash {
        if m != nil {
@@ -637,7 +678,7 @@ type CrossChainInput struct {
 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{17} }
+func (*CrossChainInput) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
 
 func (m *CrossChainInput) GetMainchainOutputId() *Hash {
        if m != nil {
@@ -697,6 +738,7 @@ func init() {
        proto.RegisterType((*IntraChainOutput)(nil), "bc.IntraChainOutput")
        proto.RegisterType((*CrossChainOutput)(nil), "bc.CrossChainOutput")
        proto.RegisterType((*VoteOutput)(nil), "bc.VoteOutput")
+       proto.RegisterType((*VetoInput)(nil), "bc.VetoInput")
        proto.RegisterType((*Retirement)(nil), "bc.Retirement")
        proto.RegisterType((*Spend)(nil), "bc.Spend")
        proto.RegisterType((*CrossChainInput)(nil), "bc.CrossChainInput")
@@ -705,61 +747,62 @@ func init() {
 func init() { proto.RegisterFile("bc.proto", fileDescriptor0) }
 
 var fileDescriptor0 = []byte{
-       // 886 bytes of a gzipped FileDescriptorProto
-       0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0x4f, 0x6f, 0xe3, 0x44,
-       0x14, 0x57, 0x6c, 0x37, 0x49, 0x5f, 0xba, 0x4d, 0x33, 0xdd, 0x05, 0x6b, 0x05, 0xa2, 0xb2, 0xb4,
-       0x74, 0x11, 0x52, 0xd5, 0x3f, 0x8b, 0xe0, 0xc0, 0x81, 0xd2, 0xb2, 0x6c, 0x0e, 0xab, 0x45, 0xd3,
-       0xaa, 0x57, 0x6b, 0x62, 0x4f, 0x9b, 0x11, 0x8e, 0x27, 0xcc, 0x8c, 0x4d, 0xb7, 0x5f, 0x81, 0x33,
-       0x07, 0xbe, 0x08, 0x5f, 0x81, 0x13, 0x9f, 0x09, 0x34, 0xcf, 0xe3, 0xc4, 0x69, 0xd2, 0x76, 0x57,
-       0x08, 0xc1, 0xcd, 0xef, 0xdf, 0xef, 0xbd, 0xf7, 0x9b, 0xf7, 0x66, 0x0c, 0xdd, 0x51, 0xb2, 0x37,
-       0x55, 0xd2, 0x48, 0xe2, 0x8d, 0x92, 0xe8, 0x25, 0x04, 0xaf, 0x98, 0x1e, 0x93, 0x4d, 0xf0, 0xca,
-       0xfd, 0xb0, 0xb5, 0xd3, 0x7a, 0xde, 0xa6, 0x5e, 0xb9, 0x8f, 0xf2, 0x41, 0xe8, 0x39, 0xf9, 0x00,
-       0xe5, 0xc3, 0xd0, 0x77, 0xf2, 0x21, 0xca, 0x47, 0x61, 0xe0, 0xe4, 0xa3, 0xe8, 0x6b, 0xe8, 0xfc,
-       0xa0, 0xe4, 0x95, 0x62, 0x13, 0xf2, 0x31, 0x40, 0x39, 0x89, 0x4b, 0xae, 0xb4, 0x90, 0x39, 0x42,
-       0x06, 0x74, 0xbd, 0x9c, 0x5c, 0x54, 0x0a, 0x42, 0x20, 0x48, 0x64, 0xca, 0x11, 0x7b, 0x83, 0xe2,
-       0x77, 0x34, 0x84, 0xce, 0xb1, 0xd6, 0xdc, 0x0c, 0x4f, 0xff, 0x71, 0x21, 0xaf, 0xa1, 0x87, 0x50,
-       0xc7, 0x13, 0x59, 0xe4, 0x86, 0x7c, 0x0a, 0x5d, 0x66, 0xc5, 0x58, 0xa4, 0x08, 0xda, 0x3b, 0xec,
-       0xed, 0x8d, 0x92, 0x3d, 0x97, 0x8d, 0x76, 0xd0, 0x38, 0x4c, 0xc9, 0x07, 0xd0, 0x66, 0x18, 0x81,
-       0xa9, 0x02, 0xea, 0xa4, 0x28, 0x83, 0xde, 0x05, 0xcb, 0x0a, 0x7e, 0x26, 0x0b, 0x95, 0x70, 0xf2,
-       0x14, 0x7c, 0xc5, 0x2f, 0x1d, 0x52, 0xd7, 0x22, 0x59, 0xf6, 0xa8, 0x55, 0x92, 0x67, 0xb0, 0x56,
-       0x5a, 0x57, 0x44, 0xe8, 0x1d, 0xf6, 0x67, 0x79, 0xaa, 0x52, 0x68, 0x65, 0x25, 0x4f, 0xa1, 0x3b,
-       0x95, 0x5a, 0x18, 0x4b, 0x8e, 0x8f, 0xb9, 0x66, 0x72, 0xf4, 0x13, 0x6c, 0x61, 0xb6, 0x53, 0xae,
-       0x8d, 0xc8, 0x99, 0xd5, 0xfd, 0xdb, 0x29, 0xff, 0xf2, 0xa0, 0xf7, 0x6d, 0x26, 0x93, 0x1f, 0x5f,
-       0x71, 0x96, 0x72, 0x45, 0x42, 0xe8, 0x2c, 0x1e, 0x5d, 0x2d, 0x5a, 0x8a, 0xc6, 0x5c, 0x5c, 0x8d,
-       0x67, 0x14, 0x55, 0x12, 0x79, 0x01, 0x83, 0xa9, 0xe2, 0xa5, 0x90, 0x85, 0x8e, 0x47, 0x16, 0xc9,
-       0x72, 0xed, 0xdf, 0x2a, 0xb7, 0x5f, 0xbb, 0x60, 0xae, 0x61, 0x4a, 0x3e, 0x82, 0x75, 0x23, 0x26,
-       0x5c, 0x1b, 0x36, 0x99, 0xe2, 0xf1, 0x05, 0x74, 0xae, 0x20, 0x5f, 0xc0, 0xc0, 0x28, 0x96, 0x6b,
-       0x96, 0xd8, 0x22, 0x75, 0xac, 0xa4, 0x34, 0xe1, 0xda, 0x2d, 0xcc, 0xad, 0xa6, 0x0b, 0x95, 0xd2,
-       0x90, 0x6f, 0xe0, 0xc3, 0x86, 0x2e, 0xd6, 0x86, 0x99, 0x42, 0xc7, 0x63, 0xa6, 0xc7, 0x61, 0xfb,
-       0x56, 0xf0, 0x93, 0x86, 0xe3, 0x19, 0xfa, 0xe1, 0x1e, 0x9c, 0x02, 0x59, 0x46, 0x08, 0x3b, 0x18,
-       0xfc, 0xc4, 0x06, 0x9f, 0xdf, 0x0e, 0xa3, 0x83, 0x25, 0x24, 0xf2, 0x39, 0x0c, 0x7e, 0x16, 0x26,
-       0xe7, 0x5a, 0xc7, 0x4c, 0x5d, 0x15, 0x13, 0x9e, 0x1b, 0x1d, 0x76, 0x77, 0xfc, 0xe7, 0x1b, 0x74,
-       0xcb, 0x19, 0x8e, 0x6b, 0x7d, 0xf4, 0x6b, 0x0b, 0xba, 0xe7, 0xd7, 0x0f, 0xd2, 0xbf, 0x0b, 0x7d,
-       0xcd, 0x95, 0x60, 0x99, 0xb8, 0xe1, 0x69, 0xac, 0xc5, 0x0d, 0x77, 0xe7, 0xb0, 0x39, 0x57, 0x9f,
-       0x89, 0x1b, 0x6e, 0xf7, 0xcf, 0x12, 0x19, 0x2b, 0x96, 0x5f, 0x71, 0x77, 0xde, 0x48, 0x2d, 0xb5,
-       0x0a, 0xb2, 0x0b, 0xa0, 0xb8, 0x2e, 0x32, 0xbb, 0x12, 0x3a, 0x0c, 0x76, 0xfc, 0x05, 0x5a, 0xd6,
-       0x2b, 0xdb, 0x30, 0xd5, 0xd1, 0x01, 0x6c, 0x9e, 0x5f, 0x5f, 0x70, 0x25, 0x2e, 0xdf, 0x52, 0x54,
-       0x92, 0x4f, 0xa0, 0xe7, 0x28, 0xbd, 0x64, 0x22, 0xc3, 0x02, 0xbb, 0x14, 0x2a, 0xd5, 0x4b, 0x26,
-       0xb2, 0xe8, 0x12, 0x06, 0x4b, 0xfc, 0xdc, 0xd3, 0xd2, 0x97, 0xf0, 0xa8, 0x44, 0xfc, 0x9a, 0x67,
-       0x0f, 0xab, 0x21, 0xc8, 0xf3, 0x42, 0x6a, 0xba, 0x51, 0x39, 0x56, 0x90, 0xd1, 0x9f, 0x2d, 0xf0,
-       0x5f, 0x17, 0xd7, 0xe4, 0x33, 0xe8, 0x68, 0x5c, 0x4c, 0x1d, 0xb6, 0x30, 0x14, 0x37, 0xa0, 0xb1,
-       0xb0, 0xb4, 0xb6, 0x93, 0x67, 0xd0, 0x99, 0x56, 0x17, 0x94, 0x5b, 0x16, 0xbc, 0x07, 0xdc, 0x9d,
-       0x45, 0x6b, 0x1b, 0xf9, 0x1e, 0x1e, 0xd7, 0x27, 0x97, 0xce, 0x97, 0x50, 0x87, 0x3e, 0xc2, 0x3f,
-       0x9e, 0xc1, 0x37, 0x36, 0x94, 0x6e, 0xbb, 0x88, 0x86, 0xee, 0x8e, 0x11, 0x08, 0xee, 0x18, 0x01,
-       0x09, 0xdd, 0x13, 0x29, 0xf2, 0x11, 0xd3, 0x9c, 0x7c, 0x07, 0xdb, 0x2b, 0x2a, 0x70, 0xfb, 0xbf,
-       0xba, 0x00, 0xb2, 0x5c, 0x80, 0xdd, 0x2f, 0xa6, 0x46, 0xc2, 0x28, 0xa6, 0xde, 0xba, 0xbb, 0x76,
-       0xae, 0x88, 0x7e, 0x69, 0xc1, 0xd6, 0x30, 0x37, 0x8a, 0x9d, 0x8c, 0x99, 0xc8, 0xdf, 0x14, 0x66,
-       0x5a, 0x18, 0xb2, 0x0b, 0xed, 0x8a, 0x2d, 0x97, 0x6c, 0x89, 0x4c, 0x67, 0x26, 0x2f, 0xa0, 0x9f,
-       0xc8, 0xdc, 0x28, 0x99, 0xc5, 0xf7, 0x70, 0xba, 0xe9, 0x7c, 0xea, 0x77, 0x21, 0x84, 0x8e, 0x54,
-       0xa9, 0xc8, 0x59, 0xe6, 0x86, 0xb2, 0x16, 0xb1, 0x9a, 0x13, 0x25, 0xb5, 0xfe, 0x5f, 0x54, 0xf3,
-       0x5b, 0x0b, 0xe0, 0x42, 0x1a, 0xfe, 0x1f, 0xd7, 0x61, 0x1f, 0xca, 0x52, 0x1a, 0x8e, 0x97, 0xe3,
-       0x06, 0xc5, 0xef, 0xe8, 0x0d, 0x00, 0xe5, 0x46, 0x28, 0x6e, 0xe7, 0xe6, 0xdd, 0x4b, 0x6b, 0x24,
-       0xf1, 0x16, 0x9b, 0xfd, 0xa3, 0x05, 0x6b, 0x67, 0x53, 0x9e, 0xa7, 0x64, 0x1f, 0xfa, 0x7a, 0xca,
-       0x73, 0x13, 0x4b, 0xec, 0x7b, 0xfe, 0x60, 0xce, 0x2f, 0x87, 0x47, 0xe8, 0x50, 0xf1, 0x32, 0x4c,
-       0xef, 0x9a, 0x54, 0xef, 0x3d, 0x27, 0x75, 0xe5, 0xa6, 0xf8, 0xab, 0x37, 0xa5, 0xd9, 0x49, 0xb0,
-       0xd8, 0xc9, 0xef, 0x1e, 0xf4, 0xe7, 0x43, 0x34, 0xcc, 0xed, 0xd9, 0x7d, 0x05, 0xdb, 0x13, 0x26,
-       0xf2, 0xc4, 0x6a, 0xee, 0xe9, 0x6b, 0x30, 0x73, 0x9a, 0xf5, 0xf6, 0x8e, 0x2f, 0xeb, 0x1d, 0x14,
-       0xf8, 0xef, 0x49, 0xc1, 0x8a, 0xd1, 0x09, 0x1e, 0x1e, 0x9d, 0x95, 0xc4, 0xad, 0x3d, 0x4c, 0x5c,
-       0x7b, 0x81, 0xb8, 0x51, 0x1b, 0xff, 0x06, 0x8f, 0xfe, 0x0e, 0x00, 0x00, 0xff, 0xff, 0xd8, 0x41,
-       0xe2, 0x4f, 0x19, 0x0a, 0x00, 0x00,
+       // 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,
 }
index fd25c9e..827100b 100644 (file)
@@ -101,6 +101,13 @@ message VoteOutput {
   bytes       vote            = 4;
 }
 
+message VetoInput {
+  Hash             spent_output_id     = 1;
+  ValueDestination witness_destination = 2;
+  repeated bytes   witness_arguments   = 3;
+  uint64           ordinal             = 4;
+}
+
 message Retirement {
   ValueSource source   = 1;
   uint64      ordinal  = 2;
index fd76ddd..0702e4c 100644 (file)
@@ -82,6 +82,19 @@ func (tx *Tx) Spend(id Hash) (*Spend, error) {
        return sp, nil
 }
 
+// VetoInput try to get the veto entry by given hash
+func (tx *Tx) VetoInput(id Hash) (*VetoInput, error) {
+       e, ok := tx.Entries[id]
+       if !ok || e == nil {
+               return nil, errors.Wrapf(ErrMissingEntry, "id %x", id.Bytes())
+       }
+       sp, ok := e.(*VetoInput)
+       if !ok {
+               return nil, errors.Wrapf(ErrEntryType, "entry %x has unexpected type %T", id.Bytes(), e)
+       }
+       return sp, nil
+}
+
 // VoteOutput try to get the vote output entry by given hash
 func (tx *Tx) VoteOutput(id Hash) (*VoteOutput, error) {
        e, ok := tx.Entries[id]
index 1568119..170b9f0 100644 (file)
@@ -39,6 +39,13 @@ func MapTx(oldTx *TxData) *bc.Tx {
                                tx.GasInputIDs = append(tx.GasInputIDs, id)
                        }
 
+               case *bc.VetoInput:
+                       ord = e.Ordinal
+                       spentOutputIDs[*e.SpentOutputId] = true
+                       if *e.WitnessDestination.Value.AssetId == *consensus.BTMAssetID {
+                               tx.GasInputIDs = append(tx.GasInputIDs, id)
+                       }
+
                case *bc.Coinbase:
                        ord = 0
                        tx.GasInputIDs = append(tx.GasInputIDs, id)
@@ -71,9 +78,10 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
        }
 
        var (
-               spends   []*bc.Spend
-               crossIns []*bc.CrossChainInput
-               coinbase *bc.Coinbase
+               spends     []*bc.Spend
+               vetoInputs []*bc.VetoInput
+               crossIns   []*bc.CrossChainInput
+               coinbase   *bc.Coinbase
        )
 
        muxSources := make([]*bc.ValueSource, len(tx.Inputs))
@@ -111,7 +119,7 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
                                Value: &value,
                        }
 
-               case *UnvoteInput:
+               case *VetoInput:
                        prog := &bc.Program{VmVersion: inp.VMVersion, Code: inp.ControlProgram}
                        src := &bc.ValueSource{
                                Ref:      &inp.SourceID,
@@ -120,16 +128,16 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
                        }
                        prevout := bc.NewVoteOutput(src, prog, 0, inp.Vote) // ordinal doesn't matter for prevouts, only for result outputs
                        prevoutID := addEntry(prevout)
-                       // create entry for spend
-                       spend := bc.NewSpend(&prevoutID, uint64(i))
-                       spend.WitnessArguments = inp.Arguments
-                       spendID := addEntry(spend)
+                       // create entry for VetoInput
+                       vetoInput := bc.NewVetoInput(&prevoutID, uint64(i))
+                       vetoInput.WitnessArguments = inp.Arguments
+                       vetoVoteID := addEntry(vetoInput)
                        // setup mux
                        muxSources[i] = &bc.ValueSource{
-                               Ref:   &spendID,
+                               Ref:   &vetoVoteID,
                                Value: &inp.AssetAmount,
                        }
-                       spends = append(spends, spend)
+                       vetoInputs = append(vetoInputs, vetoInput)
 
                case *CrossChainInput:
                        // TODO: fed peg script
@@ -157,13 +165,13 @@ func mapTx(tx *TxData) (headerID bc.Hash, hdr *bc.TxHeader, entryMap map[bc.Hash
 
        // connect the inputs to the mux
        for _, spend := range spends {
-               switch spentOutput := entryMap[*spend.SpentOutputId].(type) {
-               case *bc.IntraChainOutput:
-                       spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
+               spentOutput := entryMap[*spend.SpentOutputId].(*bc.IntraChainOutput)
+               spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
+       }
 
-               case *bc.VoteOutput:
-                       spend.SetDestination(&muxID, spentOutput.Source.Value, spend.Ordinal)
-               }
+       for _, vetoInput := range vetoInputs {
+               voteOutput := entryMap[*vetoInput.SpentOutputId].(*bc.VoteOutput)
+               vetoInput.SetDestination(&muxID, voteOutput.Source.Value, vetoInput.Ordinal)
        }
 
        for _, crossIn := range crossIns {
index 08e6f6c..52f50a9 100644 (file)
@@ -53,6 +53,8 @@ func (tx *Tx) SetInputArguments(n uint32, args [][]byte) {
                e.WitnessArguments = args
        case *bc.CrossChainInput:
                e.WitnessArguments = args
+       case *bc.VetoInput:
+               e.WitnessArguments = args
        }
 }
 
index 7b9ba0e..47831cc 100644 (file)
@@ -14,7 +14,7 @@ const (
        CrossChainInputType uint8 = iota
        SpendInputType
        CoinbaseInputType
-       UnvoteInputType
+       VetoInputType
 )
 
 type (
@@ -43,7 +43,7 @@ func (t *TxInput) AssetAmount() bc.AssetAmount {
        case *CrossChainInput:
                return inp.AssetAmount
 
-       case *UnvoteInput:
+       case *VetoInput:
                return inp.AssetAmount
        }
 
@@ -59,7 +59,7 @@ func (t *TxInput) AssetID() bc.AssetID {
        case *CrossChainInput:
                return *inp.AssetAmount.AssetId
 
-       case *UnvoteInput:
+       case *VetoInput:
                return *inp.AssetId
 
        }
@@ -75,7 +75,7 @@ func (t *TxInput) Amount() uint64 {
        case *CrossChainInput:
                return inp.AssetAmount.Amount
 
-       case *UnvoteInput:
+       case *VetoInput:
                return inp.Amount
 
        }
@@ -91,7 +91,7 @@ func (t *TxInput) ControlProgram() []byte {
        case *CrossChainInput:
                return inp.ControlProgram
 
-       case *UnvoteInput:
+       case *VetoInput:
                return inp.ControlProgram
 
        }
@@ -108,7 +108,7 @@ func (t *TxInput) Arguments() [][]byte {
        case *CrossChainInput:
                return inp.Arguments
 
-       case *UnvoteInput:
+       case *VetoInput:
                return inp.Arguments
        }
        return nil
@@ -123,7 +123,7 @@ func (t *TxInput) SetArguments(args [][]byte) {
        case *CrossChainInput:
                inp.Arguments = args
 
-       case *UnvoteInput:
+       case *VetoInput:
                inp.Arguments = args
        }
 }
@@ -134,8 +134,8 @@ func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
        case *SpendInput:
                o, err = ComputeOutputID(&inp.SpendCommitment, SpendInputType, nil)
 
-       case *UnvoteInput:
-               o, err = ComputeOutputID(&inp.SpendCommitment, UnvoteInputType, inp.Vote)
+       case *VetoInput:
+               o, err = ComputeOutputID(&inp.SpendCommitment, VetoInputType, inp.Vote)
        }
 
        return o, err
@@ -177,8 +177,8 @@ func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
                                return err
                        }
 
-               case UnvoteInputType:
-                       ui := new(UnvoteInput)
+               case VetoInputType:
+                       ui := new(VetoInput)
                        t.TypedInput = ui
                        if ui.UnvoteCommitmentSuffix, err = ui.SpendCommitment.readFrom(r, 1); err != nil {
 
@@ -210,7 +210,7 @@ func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
                                return err
                        }
 
-               case *UnvoteInput:
+               case *VetoInput:
                        if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
                                return err
                        }
@@ -284,8 +284,8 @@ func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
                        return errors.Wrap(err, "writing coinbase arbitrary")
                }
 
-       case *UnvoteInput:
-               if _, err = w.Write([]byte{UnvoteInputType}); err != nil {
+       case *VetoInput:
+               if _, err = w.Write([]byte{VetoInputType}); err != nil {
                        return err
                }
                return inp.SpendCommitment.writeExtensibleString(w, inp.UnvoteCommitmentSuffix, t.AssetVersion)
@@ -306,7 +306,7 @@ func (t *TxInput) writeInputWitness(w io.Writer) error {
        case *CrossChainInput:
                _, err := blockchain.WriteVarstrList(w, inp.Arguments)
                return err
-       case *UnvoteInput:
+       case *VetoInput:
                if _, err := blockchain.WriteVarstrList(w, inp.Arguments); err != nil {
                        return err
                }
index 6ff94a9..884d672 100644 (file)
@@ -26,17 +26,17 @@ func TestSerializationSpend(t *testing.T) {
                "52", // spend commitment length
                "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // source id
                "fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a", // assetID
-               "92c30f", // amount
-               "03",     // source position
-               "01",     // vm version
-               "0c",     // spend program length
+               "92c30f",                   // amount
+               "03",                       // source position
+               "01",                       // vm version
+               "0c",                       // spend program length
                "7370656e6450726f6772616d", // 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
+               "17",                       // witness length
+               "02",                       // argument array length
+               "0a",                       // first argument length
+               "617267756d656e747331",     // first argument data
+               "0a",                       // second argument length
+               "617267756d656e747332",     // second argument data
        }, "")
 
        // Test convert struct to hex
@@ -80,19 +80,19 @@ func TestSerializationCrossIn(t *testing.T) {
                "54", // cross-chain input commitment length
                "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // source id
                "fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a", // assetID
-               "92c30f", // amount
-               "03",     // source position
-               "01",     // vm version
-               "0e",     // spend program length
+               "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
+               "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
        }, "")
 
        // Test convert struct to hex
@@ -128,7 +128,7 @@ func TestSerializationUnvote(t *testing.T) {
                []byte("arguments2"),
        }
 
-       unvote := NewUnvoteInput(arguments, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), testutil.MustDecodeAsset("fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a"), 254354, 3, []byte("spendProgram"), []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269"))
+       vetoInput := NewVetoInput(arguments, testutil.MustDecodeHash("fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409"), testutil.MustDecodeAsset("fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a"), 254354, 3, []byte("spendProgram"), []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269"))
 
        wantHex := strings.Join([]string{
                "01", // asset version
@@ -137,24 +137,24 @@ func TestSerializationUnvote(t *testing.T) {
                "52", // unvote commitment length
                "fad5195a0c8e3b590b86a3c0a95e7529565888508aecca96e9aeda633002f409", // source id
                "fe9791d71b67ee62515e08723c061b5ccb952a80d804417c8aeedf7f633c524a", // assetID
-               "92c30f", // amount
-               "03",     // source position
-               "01",     // vm version
-               "0c",     // unvote program length
+               "92c30f",                   // amount
+               "03",                       // source position
+               "01",                       // vm version
+               "0c",                       // unvote program length
                "7370656e6450726f6772616d", // unvote program
-               "9901", // witness length
-               "02",   // argument array length
-               "0a",   // first argument length
-               "617267756d656e747331", // first argument data
-               "0a", // second argument length
-               "617267756d656e747332", // second argument data
-               "8001",                 //xpub length
+               "9901",                     // witness length
+               "02",                       // argument array length
+               "0a",                       // first argument length
+               "617267756d656e747331",     // first argument data
+               "0a",                       // second argument length
+               "617267756d656e747332",     // second argument data
+               "8001",                     //xpub length
                "6166353934303036613430383337643966303238646161626236643538396466306239313338646165666164353638336535323333633236343632373932313732393461386435333265363038363362636631393636323561333566623863656566666133633039363130656239326463666236353561393437663133323639", //voter xpub
        }, "")
 
        // Test convert struct to hex
        var buffer bytes.Buffer
-       if err := unvote.writeTo(&buffer); err != nil {
+       if err := vetoInput.writeTo(&buffer); err != nil {
                t.Fatal(err)
        }
 
@@ -164,18 +164,18 @@ func TestSerializationUnvote(t *testing.T) {
        }
 
        // Test convert hex to struct
-       var gotUnvote TxInput
+       var gotVeto TxInput
        decodeHex, err := hex.DecodeString(wantHex)
        if err != nil {
                t.Fatal(err)
        }
 
-       if err := gotUnvote.readFrom(blockchain.NewReader(decodeHex)); err != nil {
+       if err := gotVeto.readFrom(blockchain.NewReader(decodeHex)); err != nil {
                t.Fatal(err)
        }
 
-       if !testutil.DeepEqual(*unvote, gotUnvote) {
-               t.Errorf("expected marshaled/unmarshaled txinput to be:\n%sgot:\n%s", spew.Sdump(*unvote), spew.Sdump(gotUnvote))
+       if !testutil.DeepEqual(*vetoInput, gotVeto) {
+               t.Errorf("expected marshaled/unmarshaled txinput to be:\n%sgot:\n%s", spew.Sdump(*vetoInput), spew.Sdump(gotVeto))
        }
 }
 
index aca9920..15f07e1 100644 (file)
@@ -221,7 +221,7 @@ func ComputeOutputID(sc *SpendCommitment, inputType uint8, vote []byte) (h bc.Ha
        switch inputType {
        case SpendInputType:
                o = bc.NewIntraChainOutput(src, &bc.Program{VmVersion: sc.VMVersion, Code: sc.ControlProgram}, 0)
-       case UnvoteInputType:
+       case VetoInputType:
                o = bc.NewVoteOutput(src, &bc.Program{VmVersion: sc.VMVersion, Code: sc.ControlProgram}, 0, vote)
        default:
                return h, fmt.Errorf("Input type error:[%v]", inputType)
index 9dc854a..0ae1f62 100644 (file)
@@ -185,9 +185,9 @@ func TestComputeOutputID(t *testing.T) {
                                VMVersion:      1,
                                ControlProgram: testutil.MustDecodeHexString("00145c47f3a0dd3e1e9956fe5b0f897072ed33f9efb9"),
                        },
-                       inputType:    UnvoteInputType,
+                       inputType:    VetoInputType,
                        vote:         []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269"),
-                       wantOutputID: "c95701822db14f5c647158762e4d4b9bff270bfd3040f0ca32cb87c18e377429",
+                       wantOutputID: "a4de5a81babc7949d6b38d1cd4bcbc83da340387e747b5f521af3e427c6b0132",
                },
                {
                        sc: &SpendCommitment{
@@ -197,9 +197,9 @@ func TestComputeOutputID(t *testing.T) {
                                VMVersion:      1,
                                ControlProgram: testutil.MustDecodeHexString("00145c47f3a0dd3e1e9956fe5b0f897072ed33f9efb9"),
                        },
-                       inputType:    UnvoteInputType,
+                       inputType:    VetoInputType,
                        vote:         []byte(""),
-                       wantOutputID: "8f17b871f3fd07bfe778e92c272e26d4bb19258c90af08310ef32feb526eaf9c",
+                       wantOutputID: "e42a48ef401b993c5e523b6a7b5456ad4b297c7aeda163405f265d8d00af983e",
                },
        }
 
similarity index 61%
rename from protocol/bc/types/unvote.go
rename to protocol/bc/types/veto_input.go
index 810a8f3..59517bd 100644 (file)
@@ -4,16 +4,16 @@ import (
        "github.com/vapor/protocol/bc"
 )
 
-// UnvoteInput satisfies the TypedInput interface and represents a unvote transaction.
-type UnvoteInput struct {
+// VetoInput satisfies the TypedInput interface and represents a unvote transaction.
+type VetoInput struct {
        UnvoteCommitmentSuffix []byte   // The unconsumed suffix of the output commitment
        Arguments              [][]byte // Witness
        Vote                   []byte   // voter xpub
        SpendCommitment
 }
 
-// NewUnvoteInput create a new UnvoteInput struct.
-func NewUnvoteInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, amount, sourcePos uint64, controlProgram []byte, vote []byte) *TxInput {
+// NewVetoInput create a new VetoInput struct.
+func NewVetoInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, amount, sourcePos uint64, controlProgram []byte, vote []byte) *TxInput {
        sc := SpendCommitment{
                AssetAmount: bc.AssetAmount{
                        AssetId: &assetID,
@@ -26,7 +26,7 @@ func NewUnvoteInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, am
        }
        return &TxInput{
                AssetVersion: 1,
-               TypedInput: &UnvoteInput{
+               TypedInput: &VetoInput{
                        SpendCommitment: sc,
                        Arguments:       arguments,
                        Vote:            vote,
@@ -35,4 +35,4 @@ func NewUnvoteInput(arguments [][]byte, sourceID bc.Hash, assetID bc.AssetID, am
 }
 
 // InputType is the interface function for return the input type.
-func (ui *UnvoteInput) InputType() uint8 { return SpendInputType }
+func (ui *VetoInput) InputType() uint8 { return VetoInputType }
diff --git a/protocol/bc/veto_input.go b/protocol/bc/veto_input.go
new file mode 100644 (file)
index 0000000..71975c5
--- /dev/null
@@ -0,0 +1,25 @@
+package bc
+
+import "io"
+
+func (VetoInput) typ() string { return "vetoInput1" }
+func (s *VetoInput) writeForHash(w io.Writer) {
+       mustWriteForHash(w, s.SpentOutputId)
+}
+
+// SetDestination will link the spend to the output
+func (s *VetoInput) SetDestination(id *Hash, val *AssetAmount, pos uint64) {
+       s.WitnessDestination = &ValueDestination{
+               Ref:      id,
+               Value:    val,
+               Position: pos,
+       }
+}
+
+// NewVetoInput creates a new VetoInput.
+func NewVetoInput(spentOutputID *Hash, ordinal uint64) *VetoInput {
+       return &VetoInput{
+               SpentOutputId: spentOutputID,
+               Ordinal:       ordinal,
+       }
+}
index 9e574db..2029ff0 100644 (file)
@@ -2,7 +2,7 @@ package bc
 
 import "io"
 
-func (VoteOutput) typ() string { return "crosschainoutput1" }
+func (VoteOutput) typ() string { return "voteoutput1" }
 func (o *VoteOutput) writeForHash(w io.Writer) {
        mustWriteForHash(w, o.Source)
        mustWriteForHash(w, o.ControlProgram)
index 3ab1243..96ae36f 100644 (file)
@@ -58,7 +58,7 @@ func (v *VoteResult) ApplyBlock(block *types.Block) error {
 
        for _, tx := range block.Transactions {
                for _, input := range tx.Inputs {
-                       unVoteInput, ok := input.TypedInput.(*types.UnvoteInput)
+                       unVoteInput, ok := input.TypedInput.(*types.VetoInput)
                        if !ok {
                                continue
                        }
@@ -136,7 +136,7 @@ func (v *VoteResult) DetachBlock(block *types.Block) error {
        for i := len(block.Transactions) - 1; i >= 0; i-- {
                tx := block.Transactions[i]
                for _, input := range tx.Inputs {
-                       unVoteInput, ok := input.TypedInput.(*types.UnvoteInput)
+                       unVoteInput, ok := input.TypedInput.(*types.VetoInput)
                        if !ok {
                                continue
                        }
index 64fbde9..ce5feac 100644 (file)
@@ -265,30 +265,13 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                if e.SpentOutputId == nil {
                        return errors.Wrap(ErrMissingField, "spend without spent output ID")
                }
-               var (
-                       controlProgram *bc.Program
-                       value          *bc.AssetAmount
-               )
-               entryOutput, err := vs.tx.Entry(*e.SpentOutputId)
+
+               spentOutput, err := vs.tx.IntraChainOutput(*e.SpentOutputId)
                if err != nil {
                        return errors.Wrap(err, "getting spend prevout")
                }
 
-               switch output := entryOutput.(type) {
-               case *bc.IntraChainOutput:
-                       controlProgram = output.ControlProgram
-                       value = output.Source.Value
-               case *bc.VoteOutput:
-                       if len(output.Vote) != 64 {
-                               return ErrVotePubKey
-                       }
-                       controlProgram = output.ControlProgram
-                       value = output.Source.Value
-               default:
-                       return errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", e.SpentOutputId.Bytes(), entryOutput)
-               }
-
-               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, controlProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
+               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, spentOutput.ControlProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
                if err != nil {
                        return errors.Wrap(err, "checking control program")
                }
@@ -296,7 +279,7 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        return err
                }
 
-               eq, err := value.Equal(e.WitnessDestination.Value)
+               eq, err := spentOutput.Source.Value.Equal(e.WitnessDestination.Value)
                if err != nil {
                        return err
                }
@@ -304,8 +287,8 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        return errors.WithDetailf(
                                ErrMismatchedValue,
                                "previous output is for %d unit(s) of %x, spend wants %d unit(s) of %x",
-                               value.Amount,
-                               value.AssetId.Bytes(),
+                               spentOutput.Source.Value.Amount,
+                               spentOutput.Source.Value.AssetId.Bytes(),
                                e.WitnessDestination.Value.Amount,
                                e.WitnessDestination.Value.AssetId.Bytes(),
                        )
@@ -316,6 +299,47 @@ func checkValid(vs *validationState, e bc.Entry) (err error) {
                        return errors.Wrap(err, "checking spend destination")
                }
 
+       case *bc.VetoInput:
+               if e.SpentOutputId == nil {
+                       return errors.Wrap(ErrMissingField, "vetoInput without vetoInput output ID")
+               }
+
+               voteOutput, err := vs.tx.VoteOutput(*e.SpentOutputId)
+               if err != nil {
+                       return errors.Wrap(err, "getting vetoInput prevout")
+               }
+               if len(voteOutput.Vote) != 64 {
+                       return ErrVotePubKey
+               }
+
+               gasLeft, err := vm.Verify(NewTxVMContext(vs, e, voteOutput.ControlProgram, e.WitnessArguments), vs.gasStatus.GasLeft)
+               if err != nil {
+                       return errors.Wrap(err, "checking control program")
+               }
+               if err = vs.gasStatus.updateUsage(gasLeft); err != nil {
+                       return err
+               }
+
+               eq, err := voteOutput.Source.Value.Equal(e.WitnessDestination.Value)
+               if err != nil {
+                       return err
+               }
+               if !eq {
+                       return errors.WithDetailf(
+                               ErrMismatchedValue,
+                               "previous output is for %d unit(s) of %x, vetoInput wants %d unit(s) of %x",
+                               voteOutput.Source.Value.Amount,
+                               voteOutput.Source.Value.AssetId.Bytes(),
+                               e.WitnessDestination.Value.Amount,
+                               e.WitnessDestination.Value.AssetId.Bytes(),
+                       )
+               }
+               vs2 := *vs
+               vs2.destPos = 0
+               if err = checkValidDest(&vs2, e.WitnessDestination); err != nil {
+                       return errors.Wrap(err, "checking vetoInput destination")
+               }
+
        case *bc.Coinbase:
                if vs.block == nil || len(vs.block.Transactions) == 0 || vs.block.Transactions[0] != vs.tx {
                        return ErrWrongCoinbaseTransaction
@@ -367,6 +391,12 @@ func checkValidSrc(vstate *validationState, vs *bc.ValueSource) error {
 
        var dest *bc.ValueDestination
        switch ref := e.(type) {
+       case *bc.VetoInput:
+               if vs.Position != 0 {
+                       return errors.Wrapf(ErrPosition, "invalid position %d for veto-input source", vs.Position)
+               }
+               dest = ref.WitnessDestination
+
        case *bc.Coinbase:
                if vs.Position != 0 {
                        return errors.Wrapf(ErrPosition, "invalid position %d for coinbase source", vs.Position)
index 10b77d8..9815b2e 100644 (file)
@@ -32,23 +32,23 @@ func NewTxVMContext(vs *validationState, entry bc.Entry, prog *bc.Program, args
                destPos = &e.WitnessDestination.Position
 
        case *bc.Spend:
-               switch spentOutput := tx.Entries[*e.SpentOutputId].(type) {
-               case *bc.IntraChainOutput:
-                       a1 := spentOutput.Source.Value.AssetId.Bytes()
-                       assetID = &a1
-                       amount = &spentOutput.Source.Value.Amount
-                       destPos = &e.WitnessDestination.Position
-                       s := e.SpentOutputId.Bytes()
-                       spentOutputID = &s
+               spentOutput := tx.Entries[*e.SpentOutputId].(*bc.IntraChainOutput)
+               a1 := spentOutput.Source.Value.AssetId.Bytes()
+               assetID = &a1
+               amount = &spentOutput.Source.Value.Amount
+               destPos = &e.WitnessDestination.Position
+               s := e.SpentOutputId.Bytes()
+               spentOutputID = &s
+
+       case *bc.VetoInput:
+               voteOutput := tx.Entries[*e.SpentOutputId].(*bc.VoteOutput)
+               a1 := voteOutput.Source.Value.AssetId.Bytes()
+               assetID = &a1
+               amount = &voteOutput.Source.Value.Amount
+               destPos = &e.WitnessDestination.Position
+               s := e.SpentOutputId.Bytes()
+               spentOutputID = &s
 
-               case *bc.VoteOutput:
-                       a1 := spentOutput.Source.Value.AssetId.Bytes()
-                       assetID = &a1
-                       amount = &spentOutput.Source.Value.Amount
-                       destPos = &e.WitnessDestination.Position
-                       s := e.SpentOutputId.Bytes()
-                       spentOutputID = &s
-               }
        }
 
        var txSigHash *[]byte
@@ -173,6 +173,19 @@ func (ec *entryContext) checkOutput(index uint64, amount uint64, assetID []byte,
                        return false, errors.Wrapf(vm.ErrBadValue, "index %d >= 1", index)
                }
                return checkEntry(d)
+
+       case *bc.VetoInput:
+               d, ok := ec.entries[*e.WitnessDestination.Ref]
+               if !ok {
+                       return false, errors.Wrapf(bc.ErrMissingEntry, "entry for vetoInput destination %x not found", e.WitnessDestination.Ref.Bytes())
+               }
+               if m, ok := d.(*bc.Mux); ok {
+                       return checkMux(m)
+               }
+               if index != 0 {
+                       return false, errors.Wrapf(vm.ErrBadValue, "index %d >= 1", index)
+               }
+               return checkEntry(d)
        }
 
        return false, vm.ErrContext
index 4bcc507..6604876 100644 (file)
@@ -174,6 +174,16 @@ func (w *Wallet) BuildAnnotatedInput(tx *types.Tx, i uint32) *query.AnnotatedInp
        in.InputID = id
        e := tx.Entries[id]
        switch e := e.(type) {
+       case *bc.VetoInput:
+               in.Type = "veto"
+               in.ControlProgram = orig.ControlProgram()
+               in.Address = w.getAddressFromControlProgram(in.ControlProgram, false)
+               in.SpentOutputID = e.SpentOutputId
+               arguments := orig.Arguments()
+               for _, arg := range arguments {
+                       in.WitnessArguments = append(in.WitnessArguments, arg)
+               }
+
        case *bc.CrossChainInput:
                in.Type = "cross_chain_in"
                in.ControlProgram = orig.ControlProgram()
index e1373f5..491d98c 100644 (file)
@@ -174,38 +174,41 @@ func batchSaveUtxos(utxos []*account.UTXO, batch dbm.Batch) error {
 func txInToUtxos(tx *types.Tx, statusFail bool) []*account.UTXO {
        utxos := []*account.UTXO{}
        for _, inpID := range tx.Tx.InputIDs {
-               sp, err := tx.Spend(inpID)
-               if err != nil {
-                       continue
-               }
 
-               entryOutput, err := tx.Entry(*sp.SpentOutputId)
+               e, err := tx.Entry(inpID)
                if err != nil {
-                       log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get entryOutput")
                        continue
                }
-
                utxo := &account.UTXO{}
-               switch resOut := entryOutput.(type) {
-               case *bc.IntraChainOutput:
+               switch inp := e.(type) {
+               case *bc.Spend:
+                       resOut, err := tx.IntraChainOutput(*inp.SpentOutputId)
+                       if err != nil {
+                               log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get resOut for spedn")
+                               continue
+                       }
                        if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID {
                                continue
                        }
                        utxo = &account.UTXO{
-                               OutputID:       *sp.SpentOutputId,
+                               OutputID:       *inp.SpentOutputId,
                                AssetID:        *resOut.Source.Value.AssetId,
                                Amount:         resOut.Source.Value.Amount,
                                ControlProgram: resOut.ControlProgram.Code,
                                SourceID:       *resOut.Source.Ref,
                                SourcePos:      resOut.Source.Position,
                        }
-
-               case *bc.VoteOutput:
+               case *bc.VetoInput:
+                       resOut, err := tx.VoteOutput(*inp.SpentOutputId)
+                       if err != nil {
+                               log.WithFields(log.Fields{"module": logModule, "err": err}).Error("txInToUtxos fail on get resOut for vetoInput")
+                               continue
+                       }
                        if statusFail && *resOut.Source.Value.AssetId != *consensus.BTMAssetID {
                                continue
                        }
                        utxo = &account.UTXO{
-                               OutputID:       *sp.SpentOutputId,
+                               OutputID:       *inp.SpentOutputId,
                                AssetID:        *resOut.Source.Value.AssetId,
                                Amount:         resOut.Source.Value.Amount,
                                ControlProgram: resOut.ControlProgram.Code,
@@ -213,12 +216,10 @@ func txInToUtxos(tx *types.Tx, statusFail bool) []*account.UTXO {
                                SourcePos:      resOut.Source.Position,
                                Vote:           resOut.Vote,
                        }
-
                default:
-                       log.WithFields(log.Fields{"module": logModule}).Error("txInToUtxos fail on get resOut")
+                       log.WithFields(log.Fields{"module": logModule, "err": errors.Wrapf(bc.ErrEntryType, "entry %x has unexpected type %T", inpID.Bytes(), e)}).Error("txInToUtxos fail on get resOut")
                        continue
                }
-
                utxos = append(utxos, utxo)
        }
        return utxos
index c5aad35..4f76dd5 100644 (file)
@@ -484,7 +484,7 @@ func TestTxInToUtxos(t *testing.T) {
                {
                        tx: types.NewTx(types.TxData{
                                Inputs: []*types.TxInput{
-                                       types.NewUnvoteInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}, []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269")),
+                                       types.NewVetoInput([][]byte{}, bc.Hash{V0: 1}, bc.AssetID{V0: 1}, 1, 1, []byte{0x51}, []byte("af594006a40837d9f028daabb6d589df0b9138daefad5683e5233c2646279217294a8d532e60863bcf196625a35fb8ceeffa3c09610eb92dcfb655a947f13269")),
                                },
                                Outputs: []*types.TxOutput{
                                        types.NewIntraChainOutput(bc.AssetID{V0: 1}, 1, []byte{0x51}),
@@ -493,7 +493,7 @@ func TestTxInToUtxos(t *testing.T) {
                        statusFail: false,
                        wantUtxos: []*account.UTXO{
                                &account.UTXO{
-                                       OutputID:       bc.NewHash([32]byte{0x95, 0x23, 0x06, 0xa5, 0x2f, 0xc4, 0xe2, 0x36, 0x03, 0x0f, 0xe3, 0xe6, 0xb8, 0x0b, 0xcc, 0x3c, 0x1e, 0x17, 0x3e, 0x25, 0x95, 0xd0, 0xbf, 0x08, 0x11, 0x73, 0x06, 0xd4, 0x64, 0x9c, 0xfb, 0x3b}),
+                                       OutputID:       bc.NewHash([32]byte{0x7c, 0x75, 0x7f, 0x03, 0x67, 0x9b, 0xc2, 0x8f, 0x8f, 0xbd, 0x04, 0x25, 0x72, 0x42, 0x4b, 0x0b, 0x2a, 0xa4, 0x0e, 0x10, 0x0a, 0x6e, 0x99, 0x0e, 0x6d, 0x58, 0x92, 0x1d, 0xdd, 0xbe, 0xeb, 0x1a}),
                                        AssetID:        bc.AssetID{V0: 1},
                                        Amount:         1,
                                        ControlProgram: []byte{0x51},