7 "github.com/vapor/encoding/blockchain"
8 "github.com/vapor/errors"
9 "github.com/vapor/protocol/bc"
10 "github.com/vapor/protocol/bc/types"
13 // serflag variables for input types.
15 IssuanceInputType uint8 = iota
21 // TxInput is the top level struct of tx input.
25 CommitmentSuffix []byte
29 // TypedInput return the txinput type.
30 TypedInput interface {
35 var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
37 // AssetAmount return the asset id and amount of the txinput.
38 func (t *TxInput) AssetAmount() bc.AssetAmount {
39 switch inp := t.TypedInput.(type) {
40 case *types.IssuanceInput:
41 assetID := inp.AssetID()
42 return bc.AssetAmount{
47 return inp.AssetAmount
49 return bc.AssetAmount{}
52 // AssetID return the assetID of the txinput
53 func (t *TxInput) AssetID() bc.AssetID {
54 switch inp := t.TypedInput.(type) {
55 case *types.IssuanceInput:
64 // Amount return the asset amount of the txinput
65 func (t *TxInput) Amount() uint64 {
66 switch inp := t.TypedInput.(type) {
67 case *types.IssuanceInput:
75 // ControlProgram return the control program of the spend input
76 func (t *TxInput) ControlProgram() []byte {
77 if si, ok := t.TypedInput.(*SpendInput); ok {
78 return si.ControlProgram
83 // IssuanceProgram return the control program of the issuance input
84 func (t *TxInput) IssuanceProgram() []byte {
85 if ii, ok := t.TypedInput.(*types.IssuanceInput); ok {
86 return ii.IssuanceProgram
91 // Arguments get the args for the input
92 func (t *TxInput) Arguments() [][]byte {
93 switch inp := t.TypedInput.(type) {
94 case *types.IssuanceInput:
102 // SetArguments set the args for the input
103 func (t *TxInput) SetArguments(args [][]byte) {
104 switch inp := t.TypedInput.(type) {
105 case *types.IssuanceInput:
112 // SpentOutputID calculate the hash of spended output
113 func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
114 if si, ok := t.TypedInput.(*SpendInput); ok {
115 o, err = ComputeOutputID(&si.SpendCommitment)
120 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
121 if t.AssetVersion, err = blockchain.ReadVarint63(r); err != nil {
125 var assetID bc.AssetID
126 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
127 if t.AssetVersion != 1 {
131 if _, err = io.ReadFull(r, icType[:]); err != nil {
132 return errors.Wrap(err, "reading input commitment type")
135 case IssuanceInputType:
136 ii := new(types.IssuanceInput)
139 if ii.Nonce, err = blockchain.ReadVarstr31(r); err != nil {
142 if _, err = assetID.ReadFrom(r); err != nil {
145 if ii.Amount, err = blockchain.ReadVarint63(r); err != nil {
150 si := new(SpendInput)
152 if si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1); err != nil {
156 case CoinbaseInputType:
157 ci := new(CoinbaseInput)
159 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
164 return fmt.Errorf("unsupported input type %d", icType[0])
172 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
173 if t.AssetVersion != 1 {
177 switch inp := t.TypedInput.(type) {
178 case *types.IssuanceInput:
179 if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
182 if inp.VMVersion, err = blockchain.ReadVarint63(r); err != nil {
185 if inp.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
188 if inp.AssetID() != assetID {
191 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
196 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
206 func (t *TxInput) writeTo(w io.Writer) error {
207 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
208 return errors.Wrap(err, "writing asset version")
211 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
212 return errors.Wrap(err, "writing input commitment")
215 _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness)
216 return errors.Wrap(err, "writing input witness")
219 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
220 if t.AssetVersion != 1 {
224 switch inp := t.TypedInput.(type) {
225 case *types.IssuanceInput:
226 if _, err = w.Write([]byte{IssuanceInputType}); err != nil {
229 if _, err = blockchain.WriteVarstr31(w, inp.Nonce); err != nil {
232 assetID := t.AssetID()
233 if _, err = assetID.WriteTo(w); err != nil {
236 _, err = blockchain.WriteVarint63(w, inp.Amount)
240 if _, err = w.Write([]byte{SpendInputType}); err != nil {
243 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
246 if _, err = w.Write([]byte{CoinbaseInputType}); err != nil {
249 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
250 return errors.Wrap(err, "writing coinbase arbitrary")
256 func (t *TxInput) writeInputWitness(w io.Writer) error {
257 if t.AssetVersion != 1 {
260 switch inp := t.TypedInput.(type) {
261 case *types.IssuanceInput:
262 if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
265 if _, err := blockchain.WriteVarint63(w, inp.VMVersion); err != nil {
268 if _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram); err != nil {
271 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
275 _, err := blockchain.WriteVarstrList(w, inp.Arguments)