9 "github.com/bytom/crypto/sha3pool"
10 "github.com/bytom/encoding/blockchain"
11 "github.com/bytom/errors"
12 "github.com/bytom/protocol/bc"
15 // CurrentTransactionVersion is the current latest
16 // supported transaction version.
17 const CurrentTransactionVersion = 1
19 // Tx holds a transaction along with its hash.
25 func (tx *Tx) UnmarshalText(p []byte) error {
26 if err := tx.TxData.UnmarshalText(p); err != nil {
30 tx.Tx = MapTx(&tx.TxData)
34 // SetInputArguments sets the Arguments field in input n.
35 func (tx *Tx) SetInputArguments(n uint32, args [][]byte) {
36 tx.Inputs[n].SetArguments(args)
37 id := tx.Tx.InputIDs[n]
39 switch e := e.(type) {
41 e.WitnessArguments = args
43 e.WitnessArguments = args
47 func (tx *Tx) IssuanceHash(n int) bc.Hash {
48 return tx.Tx.InputIDs[n]
51 func (tx *Tx) OutputID(outputIndex int) *bc.Hash {
52 return tx.ResultIds[outputIndex]
55 // NewTx returns a new Tx containing data and its hash.
56 // If you have already computed the hash, use struct literal
57 // notation to make a Tx object directly.
58 func NewTx(data TxData) *Tx {
65 // These flags are part of the wire protocol;
66 // they must not change.
68 SerWitness uint8 = 1 << iota
72 // Bit mask for accepted serialization flags.
73 // All other flag bits must be 0.
74 SerTxHash = 0x0 // this is used only for computing transaction hash - prevout and refdata are replaced with their hashes
76 serRequired = 0x7 // we support only this combination of flags
79 // TxData encodes a transaction in the blockchain.
80 // Most users will want to use Tx instead;
81 // it includes the hash.
90 // The unconsumed suffix of the common fields extensible string
91 CommonFieldsSuffix []byte
93 // The unconsumed suffix of the common witness extensible string
94 CommonWitnessSuffix []byte
99 // HasIssuance returns true if this transaction has an issuance input.
100 func (tx *TxData) HasIssuance() bool {
101 for _, in := range tx.Inputs {
109 func (tx *TxData) UnmarshalText(p []byte) error {
110 b := make([]byte, hex.DecodedLen(len(p)))
111 if _, err := hex.Decode(b, p); err != nil {
115 r := blockchain.NewReader(b)
116 if err := tx.readFrom(r); err != nil {
119 if trailing := r.Len(); trailing > 0 {
120 return fmt.Errorf("trailing garbage (%d bytes)", trailing)
125 func (tx *TxData) readFrom(r *blockchain.Reader) (err error) {
126 tx.SerializedSize = uint64(r.Len())
128 if _, err = io.ReadFull(r, serflags[:]); err != nil {
129 return errors.Wrap(err, "reading serialization flags")
131 if serflags[0] != serRequired {
132 return fmt.Errorf("unsupported serflags %#x", serflags[0])
135 tx.Version, err = blockchain.ReadVarint63(r)
137 return errors.Wrap(err, "reading transaction version")
140 if tx.TimeRange, err = blockchain.ReadVarint63(r); err != nil {
144 tx.CommonWitnessSuffix, err = blockchain.ReadExtensibleString(r, tx.readCommonWitness)
146 return errors.Wrap(err, "reading transaction common witness")
149 n, err := blockchain.ReadVarint31(r)
151 return errors.Wrap(err, "reading number of transaction inputs")
155 if err = ti.readFrom(r); err != nil {
156 return errors.Wrapf(err, "reading input %d", len(tx.Inputs))
158 tx.Inputs = append(tx.Inputs, ti)
161 n, err = blockchain.ReadVarint31(r)
163 return errors.Wrap(err, "reading number of transaction outputs")
167 if err = to.readFrom(r, tx.Version); err != nil {
168 return errors.Wrapf(err, "reading output %d", len(tx.Outputs))
170 tx.Outputs = append(tx.Outputs, to)
173 tx.ReferenceData, err = blockchain.ReadVarstr31(r)
174 return errors.Wrap(err, "reading transaction reference data")
177 // does not read the enclosing extensible string
178 func (tx *TxData) readCommonWitness(r *blockchain.Reader) error {
182 func (tx *TxData) MarshalText() ([]byte, error) {
184 tx.WriteTo(&buf) // error is impossible
185 b := make([]byte, hex.EncodedLen(buf.Len()))
186 hex.Encode(b, buf.Bytes())
190 // WriteTo writes tx to w.
191 func (tx *TxData) WriteTo(w io.Writer) (int64, error) {
192 ew := errors.NewWriter(w)
193 if err := tx.writeTo(ew, serRequired); err != nil {
194 return ew.Written(), ew.Err()
196 return ew.Written(), ew.Err()
199 func (tx *TxData) writeTo(w io.Writer, serflags byte) error {
200 if _, err := w.Write([]byte{serflags}); err != nil {
201 return errors.Wrap(err, "writing serialization flags")
204 if _, err := blockchain.WriteVarint63(w, tx.Version); err != nil {
205 return errors.Wrap(err, "writing transaction version")
208 if _, err := blockchain.WriteVarint63(w, tx.TimeRange); err != nil {
209 return errors.Wrap(err, "writing transaction maxtime")
212 if _, err := blockchain.WriteExtensibleString(w, tx.CommonWitnessSuffix, tx.writeCommonWitness); err != nil {
213 return errors.Wrap(err, "writing common witness")
216 if _, err := blockchain.WriteVarint31(w, uint64(len(tx.Inputs))); err != nil {
217 return errors.Wrap(err, "writing tx input count")
219 for i, ti := range tx.Inputs {
220 if err := ti.writeTo(w, serflags); err != nil {
221 return errors.Wrapf(err, "writing tx input %d", i)
225 if _, err := blockchain.WriteVarint31(w, uint64(len(tx.Outputs))); err != nil {
226 return errors.Wrap(err, "writing tx output count")
228 for i, to := range tx.Outputs {
229 if err := to.writeTo(w, serflags); err != nil {
230 return errors.Wrapf(err, "writing tx output %d", i)
234 return writeRefData(w, tx.ReferenceData, serflags)
237 // does not write the enclosing extensible string
238 func (tx *TxData) writeCommonWitness(w io.Writer) error {
239 // Future protocol versions may add fields here.
243 func writeRefData(w io.Writer, data []byte, serflags byte) error {
244 if serflags&SerMetadata != 0 {
245 _, err := blockchain.WriteVarstr31(w, data)
248 return writeFastHash(w, data)
251 func writeFastHash(w io.Writer, d []byte) error {
253 _, err := blockchain.WriteVarstr31(w, nil)
257 sha3pool.Sum256(h[:], d)
258 _, err := blockchain.WriteVarstr31(w, h[:])