neoneo-go/pkg/core/block.go
Anthony De Meulemeester 66c8fc8012
merge original into coz repo (#10)
merged with the original repo.
2018-02-01 21:28:45 +01:00

115 lines
3.3 KiB
Go

package core
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"io"
. "github.com/CityOfZion/neo-go/pkg/util"
)
// BlockBase holds the base info of a block
type BlockBase struct {
Version uint32
// hash of the previous block.
PrevBlock Uint256
// Root hash of a transaction list.
MerkleRoot Uint256
// The time stamp of each block must be later than previous block's time stamp.
// Generally the difference of two block's time stamp is about 15 seconds and imprecision is allowed.
// The height of the block must be exactly equal to the height of the previous block plus 1.
Timestamp uint32
// height of the block
Height uint32
// Random number
Nonce uint64
// contract addresss of the next miner
NextMiner Uint160
// fixed to 1
_sep uint8
// Script used to validate the block
Script *Witness
}
// BlockHead holds the head info of a block
type BlockHead struct {
BlockBase
// fixed to 0
_sep1 uint8
}
// Block represents one block in the chain.
type Block struct {
BlockBase
// transaction list
Transactions []*Transaction
}
// encodeHashableFields will only encode the fields used for hashing.
// see Hash() for more information about the fields.
func (b *Block) encodeHashableFields(w io.Writer) error {
err := binary.Write(w, binary.LittleEndian, &b.Version)
err = binary.Write(w, binary.LittleEndian, &b.PrevBlock)
err = binary.Write(w, binary.LittleEndian, &b.MerkleRoot)
err = binary.Write(w, binary.LittleEndian, &b.Timestamp)
err = binary.Write(w, binary.LittleEndian, &b.Height)
err = binary.Write(w, binary.LittleEndian, &b.Nonce)
err = binary.Write(w, binary.LittleEndian, &b.NextMiner)
return err
}
// EncodeBinary encodes the block to the given writer.
func (b *Block) EncodeBinary(w io.Writer) error {
return nil
}
// DecodeBinary decods the block from the given reader.
func (b *Block) DecodeBinary(r io.Reader) error {
err := binary.Read(r, binary.LittleEndian, &b.Version)
err = binary.Read(r, binary.LittleEndian, &b.PrevBlock)
err = binary.Read(r, binary.LittleEndian, &b.MerkleRoot)
err = binary.Read(r, binary.LittleEndian, &b.Timestamp)
err = binary.Read(r, binary.LittleEndian, &b.Height)
err = binary.Read(r, binary.LittleEndian, &b.Nonce)
err = binary.Read(r, binary.LittleEndian, &b.NextMiner)
err = binary.Read(r, binary.LittleEndian, &b._sep)
b.Script = &Witness{}
if err := b.Script.DecodeBinary(r); err != nil {
return err
}
var lentx uint8
err = binary.Read(r, binary.LittleEndian, &lentx)
b.Transactions = make([]*Transaction, lentx)
for i := 0; i < int(lentx); i++ {
tx := &Transaction{}
if err := tx.DecodeBinary(r); err != nil {
return err
}
b.Transactions[i] = tx
}
return err
}
// Hash return the hash of the block.
// When calculating the hash value of the block, instead of calculating the entire block,
// only first seven fields in the block head will be calculated, which are
// version, PrevBlock, MerkleRoot, timestamp, and height, the nonce, NextMiner.
// Since MerkleRoot already contains the hash value of all transactions,
// the modification of transaction will influence the hash value of the block.
func (b *Block) Hash() (hash Uint256, err error) {
buf := new(bytes.Buffer)
if err = b.encodeHashableFields(buf); err != nil {
return
}
hash = sha256.Sum256(buf.Bytes())
return
}
// Size implements the payload interface.
func (b *Block) Size() uint32 { return 0 }