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
21 // TxInput is the top level struct of tx input.
25 CommitmentSuffix []byte
30 // TypedInput return the txinput type.
31 TypedInput interface {
36 var errBadAssetID = errors.New("asset ID does not match other issuance parameters")
38 // AssetAmount return the asset id and amount of the txinput.
39 func (t *TxInput) AssetAmount() bc.AssetAmount {
40 switch inp := t.TypedInput.(type) {
42 assetID := inp.AssetID()
43 return bc.AssetAmount{
48 return inp.AssetAmount
50 return inp.AssetAmount
52 return bc.AssetAmount{}
55 // AssetID return the assetID of the txinput
56 func (t *TxInput) AssetID() bc.AssetID {
57 switch inp := t.TypedInput.(type) {
69 // Amount return the asset amount of the txinput
70 func (t *TxInput) Amount() uint64 {
71 switch inp := t.TypedInput.(type) {
82 // ControlProgram return the control program of the spend input
83 func (t *TxInput) ControlProgram() []byte {
84 if si, ok := t.TypedInput.(*SpendInput); ok {
85 return si.ControlProgram
90 // IssuanceProgram return the control program of the issuance input
91 func (t *TxInput) IssuanceProgram() []byte {
92 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
93 return ii.IssuanceProgram
98 // AssetDefinition return the asset definition of the issuance input
99 func (t *TxInput) AssetDefinition() []byte {
100 if ii, ok := t.TypedInput.(*IssuanceInput); ok {
101 return ii.AssetDefinition
106 // Arguments get the args for the input
107 func (t *TxInput) Arguments() [][]byte {
108 switch inp := t.TypedInput.(type) {
119 // SetArguments set the args for the input
120 func (t *TxInput) SetArguments(args [][]byte) {
121 switch inp := t.TypedInput.(type) {
131 // SpentOutputID calculate the hash of spended output
132 func (t *TxInput) SpentOutputID() (o bc.Hash, err error) {
133 if si, ok := t.TypedInput.(*SpendInput); ok {
134 o, err = ComputeOutputID(&si.SpendCommitment)
139 func (t *TxInput) readFrom(r *blockchain.Reader) (err error) {
140 if t.AssetVersion, err = blockchain.ReadVarint63(r); err != nil {
144 if t.Peginwitness, err = blockchain.ReadVarstrList(r); err != nil {
147 var assetID bc.AssetID
148 t.CommitmentSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
149 if t.AssetVersion != 1 {
153 if _, err = io.ReadFull(r, icType[:]); err != nil {
154 return errors.Wrap(err, "reading input commitment type")
157 case IssuanceInputType:
158 ii := new(IssuanceInput)
161 if ii.Nonce, err = blockchain.ReadVarstr31(r); err != nil {
164 if _, err = assetID.ReadFrom(r); err != nil {
167 if ii.Amount, err = blockchain.ReadVarint63(r); err != nil {
172 si := new(SpendInput)
174 if si.SpendCommitmentSuffix, err = si.SpendCommitment.readFrom(r, 1); err != nil {
177 case ClainPeginInputType:
178 ci := new(ClaimInput)
180 if ci.SpendCommitmentSuffix, err = ci.SpendCommitment.readFrom(r, 1); err != nil {
183 case CoinbaseInputType:
184 ci := new(CoinbaseInput)
186 if ci.Arbitrary, err = blockchain.ReadVarstr31(r); err != nil {
190 return fmt.Errorf("unsupported input type %d", icType[0])
198 t.WitnessSuffix, err = blockchain.ReadExtensibleString(r, func(r *blockchain.Reader) error {
199 if t.AssetVersion != 1 {
203 switch inp := t.TypedInput.(type) {
205 if inp.AssetDefinition, err = blockchain.ReadVarstr31(r); err != nil {
208 if inp.VMVersion, err = blockchain.ReadVarint63(r); err != nil {
211 if inp.IssuanceProgram, err = blockchain.ReadVarstr31(r); err != nil {
214 if inp.AssetID() != assetID {
217 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
222 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
226 if inp.Arguments, err = blockchain.ReadVarstrList(r); err != nil {
236 func (t *TxInput) writeTo(w io.Writer) error {
237 if _, err := blockchain.WriteVarint63(w, t.AssetVersion); err != nil {
238 return errors.Wrap(err, "writing asset version")
241 if _, err := blockchain.WriteVarstrList(w, t.Peginwitness); err != nil {
242 return errors.Wrap(err, "writing pegin witness")
244 if _, err := blockchain.WriteExtensibleString(w, t.CommitmentSuffix, t.writeInputCommitment); err != nil {
245 return errors.Wrap(err, "writing input commitment")
248 _, err := blockchain.WriteExtensibleString(w, t.WitnessSuffix, t.writeInputWitness)
249 return errors.Wrap(err, "writing input witness")
252 func (t *TxInput) writeInputCommitment(w io.Writer) (err error) {
253 if t.AssetVersion != 1 {
257 switch inp := t.TypedInput.(type) {
259 if _, err = w.Write([]byte{IssuanceInputType}); err != nil {
262 if _, err = blockchain.WriteVarstr31(w, inp.Nonce); err != nil {
265 assetID := t.AssetID()
266 if _, err = assetID.WriteTo(w); err != nil {
269 _, err = blockchain.WriteVarint63(w, inp.Amount)
273 if _, err = w.Write([]byte{SpendInputType}); err != nil {
276 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
278 if _, err = w.Write([]byte{ClainPeginInputType}); err != nil {
281 return inp.SpendCommitment.writeExtensibleString(w, inp.SpendCommitmentSuffix, t.AssetVersion)
283 if _, err = w.Write([]byte{CoinbaseInputType}); err != nil {
286 if _, err = blockchain.WriteVarstr31(w, inp.Arbitrary); err != nil {
287 return errors.Wrap(err, "writing coinbase arbitrary")
293 func (t *TxInput) writeInputWitness(w io.Writer) error {
294 if t.AssetVersion != 1 {
297 switch inp := t.TypedInput.(type) {
299 if _, err := blockchain.WriteVarstr31(w, inp.AssetDefinition); err != nil {
302 if _, err := blockchain.WriteVarint63(w, inp.VMVersion); err != nil {
305 if _, err := blockchain.WriteVarstr31(w, inp.IssuanceProgram); err != nil {
308 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
312 _, err := blockchain.WriteVarstrList(w, inp.Arguments)
315 _, err := blockchain.WriteVarstrList(w, inp.Arguments)