OSDN Git Service

Merge pull request #201 from Bytom/v0.1
[bytom/vapor.git] / vendor / github.com / bytom / protocol / bc / types / block.go
diff --git a/vendor/github.com/bytom/protocol/bc/types/block.go b/vendor/github.com/bytom/protocol/bc/types/block.go
new file mode 100644 (file)
index 0000000..ddda19a
--- /dev/null
@@ -0,0 +1,115 @@
+package types
+
+import (
+       "encoding/hex"
+       "fmt"
+       "io"
+
+       "github.com/bytom/encoding/blockchain"
+       "github.com/bytom/encoding/bufpool"
+       "github.com/bytom/errors"
+)
+
+// serflag variables, start with 1
+const (
+       _ = iota
+       SerBlockHeader
+       SerBlockTransactions
+       SerBlockFull
+)
+
+// Block describes a complete block, including its header and the transactions
+// it contains.
+type Block struct {
+       BlockHeader
+       Transactions []*Tx
+}
+
+// MarshalText fulfills the json.Marshaler interface. This guarantees that
+// blocks will get deserialized correctly when being parsed from HTTP requests.
+func (b *Block) MarshalText() ([]byte, error) {
+       buf := bufpool.Get()
+       defer bufpool.Put(buf)
+
+       if _, err := b.WriteTo(buf); err != nil {
+               return nil, err
+       }
+
+       enc := make([]byte, hex.EncodedLen(buf.Len()))
+       hex.Encode(enc, buf.Bytes())
+       return enc, nil
+}
+
+// UnmarshalText fulfills the encoding.TextUnmarshaler interface.
+func (b *Block) UnmarshalText(text []byte) error {
+       decoded := make([]byte, hex.DecodedLen(len(text)))
+       if _, err := hex.Decode(decoded, text); err != nil {
+               return err
+       }
+
+       r := blockchain.NewReader(decoded)
+       if err := b.readFrom(r); err != nil {
+               return err
+       }
+
+       if trailing := r.Len(); trailing > 0 {
+               return fmt.Errorf("trailing garbage (%d bytes)", trailing)
+       }
+       return nil
+}
+
+func (b *Block) readFrom(r *blockchain.Reader) error {
+       serflags, err := b.BlockHeader.readFrom(r)
+       if err != nil {
+               return err
+       }
+
+       if serflags == SerBlockHeader {
+               return nil
+       }
+
+       n, err := blockchain.ReadVarint31(r)
+       if err != nil {
+               return errors.Wrap(err, "reading number of transactions")
+       }
+
+       for ; n > 0; n-- {
+               data := TxData{}
+               if err = data.readFrom(r); err != nil {
+                       return errors.Wrapf(err, "reading transaction %d", len(b.Transactions))
+               }
+
+               b.Transactions = append(b.Transactions, NewTx(data))
+       }
+       return nil
+}
+
+// WriteTo will write block to input io.Writer
+func (b *Block) WriteTo(w io.Writer) (int64, error) {
+       ew := errors.NewWriter(w)
+       if err := b.writeTo(ew, SerBlockFull); err != nil {
+               return 0, err
+       }
+       return ew.Written(), ew.Err()
+}
+
+func (b *Block) writeTo(w io.Writer, serflags uint8) error {
+       if err := b.BlockHeader.writeTo(w, serflags); err != nil {
+               return err
+       }
+
+       if serflags == SerBlockHeader {
+               return nil
+       }
+
+       if _, err := blockchain.WriteVarint31(w, uint64(len(b.Transactions))); err != nil {
+               return err
+       }
+
+       for _, tx := range b.Transactions {
+               if _, err := tx.WriteTo(w); err != nil {
+                       return err
+               }
+       }
+       return nil
+}