7 "github.com/vapor/encoding/blockchain"
8 "github.com/vapor/errors"
9 "github.com/vapor/protocol/bc"
12 // serflag variables for input types.
14 IssuanceInputType uint8 = iota
20 // TxInput is the top level struct of tx input.
24 CommitmentSuffix []byte
28 // TypedInput return the txinput type.
29 TypedInput interface {
34 var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
36 // AssetAmount return the asset id and amount of the txinput.
37 func (t *TxInput) AssetAmount() bc.AssetAmount {
38 switch inp := t.TypedInput.(type) {
40 return inp.AssetAmount
42 return bc.AssetAmount{}
45 // AssetID return the assetID of the txinput
46 func (t *TxInput) AssetID() bc.AssetID {
47 switch inp := t.TypedInput.(type) {
55 // Amount return the asset amount of the txinput
56 func (t *TxInput) Amount() uint64 {
57 switch inp := t.TypedInput.(type) {
64 // ControlProgram return the control program of the spend input
65 func (t *TxInput) ControlProgram() []byte {
66 if si, ok := t.TypedInput.(*SpendInput); ok {
67 return si.ControlProgram
72 // Arguments get the args for the input
73 func (t *TxInput) Arguments() [][]byte {
74 switch inp := t.TypedInput.(type) {
81 // SetArguments set the args for the input
82 func (t *TxInput) SetArguments(args [][]byte) {
83 switch inp := t.TypedInput.(type) {
89 // SpentOutputID calculate the hash of spended output
90 func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
91 if si, ok := t.TypedInput.(*SpendInput); ok {
92 o, err = ComputeOutputID(&si.SpendCommitment)
97 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
98 if t.AssetVersion, err = blockchain.ReadVarint63(r); err != nil {
102 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
103 if t.AssetVersion != 1 {
107 if _, err = io.ReadFull(r, icType[:]); err != nil {
108 return errors.Wrap(err, "reading input commitment type")
112 si := new(SpendInput)
114 if si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1); err != nil {
118 case CoinbaseInputType:
119 ci := new(CoinbaseInput)
121 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
126 return fmt.Errorf("unsupported input type %d", icType[0])
134 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
135 if t.AssetVersion != 1 {
139 switch inp := t.TypedInput.(type) {
141 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
151 func (t *TxInput) writeTo(w io.Writer) error {
152 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
153 return errors.Wrap(err, "writing asset version")
156 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
157 return errors.Wrap(err, "writing input commitment")
160 _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness)
161 return errors.Wrap(err, "writing input witness")
164 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
165 if t.AssetVersion != 1 {
169 switch inp := t.TypedInput.(type) {
171 if _, err = w.Write([]byte{SpendInputType}); err != nil {
174 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
177 if _, err = w.Write([]byte{CoinbaseInputType}); err != nil {
180 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
181 return errors.Wrap(err, "writing coinbase arbitrary")
187 func (t *TxInput) writeInputWitness(w io.Writer) error {
188 if t.AssetVersion != 1 {
192 switch inp := t.TypedInput.(type) {
194 _, err := blockchain.WriteVarstrList(w, inp.Arguments)