block.go 7.3 KB
Newer Older
1
package types
O
obscuren 已提交
2 3

import (
O
obscuren 已提交
4
	"bytes"
O
obscuren 已提交
5
	"encoding/binary"
O
obscuren 已提交
6
	"fmt"
O
obscuren 已提交
7
	"math/big"
O
obscuren 已提交
8
	"sort"
O
obscuren 已提交
9
	"time"
O
obscuren 已提交
10

O
obscuren 已提交
11
	"github.com/ethereum/go-ethereum/crypto"
O
obscuren 已提交
12
	"github.com/ethereum/go-ethereum/common"
O
obscuren 已提交
13
	"github.com/ethereum/go-ethereum/rlp"
O
obscuren 已提交
14 15
)

O
obscuren 已提交
16
type Header struct {
O
obscuren 已提交
17
	// Hash to the previous block
18
	ParentHash []byte
O
obscuren 已提交
19
	// Uncles of this block
O
obscuren 已提交
20
	UncleHash []byte
O
obscuren 已提交
21 22 23
	// The coin base address
	Coinbase []byte
	// Block Trie state
O
obscuren 已提交
24 25 26 27 28 29 30
	Root []byte
	// Tx sha
	TxHash []byte
	// Receipt sha
	ReceiptHash []byte
	// Bloom
	Bloom []byte
O
obscuren 已提交
31 32
	// Difficulty for the current block
	Difficulty *big.Int
O
obscuren 已提交
33 34 35 36 37 38
	// The block number
	Number *big.Int
	// Gas limit
	GasLimit *big.Int
	// Gas used
	GasUsed *big.Int
O
obscuren 已提交
39 40
	// Creation time
	Time uint64
O
obscuren 已提交
41 42
	// Extra data
	Extra string
43
	// Mix digest for quick checking to prevent DOS
44
	MixDigest []byte
45 46
	// Nonce
	Nonce []byte
O
obscuren 已提交
47 48
}

O
obscuren 已提交
49
func (self *Header) rlpData(withNonce bool) []interface{} {
M
Matthew Wampler-Doty 已提交
50 51 52 53 54 55 56 57 58 59 60 61 62
	fields := []interface{}{
		self.ParentHash,
		self.UncleHash,
		self.Coinbase,
		self.Root,
		self.TxHash,
		self.ReceiptHash,
		self.Bloom,
		self.Difficulty,
		self.Number,
		self.GasLimit,
		self.GasUsed,
		self.Time,
63 64
		self.Extra,
	}
O
obscuren 已提交
65
	if withNonce {
66
		fields = append(fields, self.MixDigest, self.Nonce)
O
obscuren 已提交
67
	}
O
obscuren 已提交
68

O
obscuren 已提交
69 70 71 72 73
	return fields
}

func (self *Header) RlpData() interface{} {
	return self.rlpData(true)
O
obscuren 已提交
74 75
}

O
obscuren 已提交
76
func (self *Header) Hash() []byte {
O
obscuren 已提交
77
	return crypto.Sha3(common.Encode(self.rlpData(true)))
O
obscuren 已提交
78
}
O
obscuren 已提交
79

O
obscuren 已提交
80
func (self *Header) HashNoNonce() []byte {
O
obscuren 已提交
81
	return crypto.Sha3(common.Encode(self.rlpData(false)))
O
obscuren 已提交
82 83
}

O
obscuren 已提交
84
type Block struct {
O
Merge  
obscuren 已提交
85 86 87 88 89 90 91
	// Preset Hash for mock
	HeaderHash       []byte
	ParentHeaderHash []byte
	header           *Header
	uncles           []*Header
	transactions     Transactions
	Td               *big.Int
O
obscuren 已提交
92 93 94 95 96

	receipts Receipts
	Reward   *big.Int
}

O
obscuren 已提交
97
func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.Int, nonce uint64, extra string) *Block {
O
obscuren 已提交
98 99 100 101 102 103
	header := &Header{
		Root:       root,
		ParentHash: parentHash,
		Coinbase:   coinbase,
		Difficulty: difficulty,
		Time:       uint64(time.Now().Unix()),
O
obscuren 已提交
104 105 106
		Extra:      extra,
		GasUsed:    new(big.Int),
		GasLimit:   new(big.Int),
O
obscuren 已提交
107
	}
O
obscuren 已提交
108
	header.setNonce(nonce)
O
obscuren 已提交
109

O
obscuren 已提交
110
	block := &Block{header: header, Reward: new(big.Int)}
O
obscuren 已提交
111 112 113 114

	return block
}

O
obscuren 已提交
115 116 117 118 119
func (self *Header) setNonce(nonce uint64) {
	self.Nonce = make([]byte, 8)
	binary.BigEndian.PutUint64(self.Nonce, nonce)
}

O
obscuren 已提交
120 121
func NewBlockWithHeader(header *Header) *Block {
	return &Block{header: header}
O
obscuren 已提交
122 123
}

O
obscuren 已提交
124
func (self *Block) DecodeRLP(s *rlp.Stream) error {
O
Merge  
obscuren 已提交
125 126 127 128 129
	var extblock struct {
		Header *Header
		Txs    []*Transaction
		Uncles []*Header
		TD     *big.Int // optional
O
obscuren 已提交
130
	}
O
Merge  
obscuren 已提交
131
	if err := s.Decode(&extblock); err != nil {
O
obscuren 已提交
132 133
		return err
	}
O
Merge  
obscuren 已提交
134 135 136 137
	self.header = extblock.Header
	self.uncles = extblock.Uncles
	self.transactions = extblock.Txs
	self.Td = extblock.TD
O
obscuren 已提交
138
	return nil
O
obscuren 已提交
139 140
}

O
obscuren 已提交
141 142
func (self *Block) Header() *Header {
	return self.header
O
obscuren 已提交
143 144
}

O
obscuren 已提交
145 146
func (self *Block) Uncles() []*Header {
	return self.uncles
O
obscuren 已提交
147 148
}

O
obscuren 已提交
149 150
func (self *Block) SetUncles(uncleHeaders []*Header) {
	self.uncles = uncleHeaders
O
obscuren 已提交
151
	self.header.UncleHash = crypto.Sha3(common.Encode(uncleHeaders))
O
obscuren 已提交
152 153
}

O
obscuren 已提交
154 155
func (self *Block) Transactions() Transactions {
	return self.transactions
O
obscuren 已提交
156 157
}

O
obscuren 已提交
158 159 160 161
func (self *Block) Transaction(hash []byte) *Transaction {
	for _, transaction := range self.transactions {
		if bytes.Equal(hash, transaction.Hash()) {
			return transaction
O
obscuren 已提交
162 163
		}
	}
O
obscuren 已提交
164
	return nil
O
obscuren 已提交
165 166
}

O
obscuren 已提交
167 168 169
func (self *Block) SetTransactions(transactions Transactions) {
	self.transactions = transactions
	self.header.TxHash = DeriveSha(transactions)
O
obscuren 已提交
170
}
O
obscuren 已提交
171 172 173 174
func (self *Block) AddTransaction(transaction *Transaction) {
	self.transactions = append(self.transactions, transaction)
	self.SetTransactions(self.transactions)
}
O
obscuren 已提交
175

O
obscuren 已提交
176 177
func (self *Block) Receipts() Receipts {
	return self.receipts
O
obscuren 已提交
178 179
}

O
obscuren 已提交
180 181 182 183
func (self *Block) SetReceipts(receipts Receipts) {
	self.receipts = receipts
	self.header.ReceiptHash = DeriveSha(receipts)
	self.header.Bloom = CreateBloom(receipts)
184
}
O
obscuren 已提交
185 186 187 188
func (self *Block) AddReceipt(receipt *Receipt) {
	self.receipts = append(self.receipts, receipt)
	self.SetReceipts(self.receipts)
}
189

O
obscuren 已提交
190 191 192 193 194 195 196 197 198
func (self *Block) RlpData() interface{} {
	return []interface{}{self.header, self.transactions, self.uncles}
}

func (self *Block) RlpDataForStorage() interface{} {
	return []interface{}{self.header, self.transactions, self.uncles, self.Td /* TODO receipts */}
}

// Header accessors (add as you need them)
O
obscuren 已提交
199 200 201 202 203 204 205 206 207 208
func (self *Block) Number() *big.Int  { return self.header.Number }
func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() }
func (self *Block) MixDigest() []byte { return self.header.MixDigest }
func (self *Block) Nonce() uint64 {
	return binary.BigEndian.Uint64(self.header.Nonce)
}
func (self *Block) SetNonce(nonce uint64) {
	self.header.setNonce(nonce)
}

O
obscuren 已提交
209 210 211 212 213
func (self *Block) Bloom() []byte             { return self.header.Bloom }
func (self *Block) Coinbase() []byte          { return self.header.Coinbase }
func (self *Block) Time() int64               { return int64(self.header.Time) }
func (self *Block) GasLimit() *big.Int        { return self.header.GasLimit }
func (self *Block) GasUsed() *big.Int         { return self.header.GasUsed }
O
obscuren 已提交
214
func (self *Block) Root() []byte              { return self.header.Root }
O
Merge  
obscuren 已提交
215
func (self *Block) SetRoot(root []byte)       { self.header.Root = root }
O
obscuren 已提交
216
func (self *Block) Size() common.StorageSize { return common.StorageSize(len(common.Encode(self))) }
217 218 219 220 221 222 223 224 225 226 227 228
func (self *Block) GetTransaction(i int) *Transaction {
	if len(self.transactions) > i {
		return self.transactions[i]
	}
	return nil
}
func (self *Block) GetUncle(i int) *Header {
	if len(self.uncles) > i {
		return self.uncles[i]
	}
	return nil
}
O
obscuren 已提交
229

O
Merge  
obscuren 已提交
230
// Implement pow.Block
O
obscuren 已提交
231
func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
O
Merge  
obscuren 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
func (self *Block) HashNoNonce() []byte  { return self.header.HashNoNonce() }

func (self *Block) Hash() []byte {
	if self.HeaderHash != nil {
		return self.HeaderHash
	} else {
		return self.header.Hash()
	}
}

func (self *Block) ParentHash() []byte {
	if self.ParentHeaderHash != nil {
		return self.ParentHeaderHash
	} else {
		return self.header.ParentHash
	}
O
obscuren 已提交
248 249 250
}

func (self *Block) String() string {
251
	return fmt.Sprintf(`BLOCK(%x): Size: %v TD: %v {
O
obscuren 已提交
252
NoNonce: %x
O
obscuren 已提交
253 254
Header:
[
O
obscuren 已提交
255
%v
O
obscuren 已提交
256 257
]
Transactions:
O
obscuren 已提交
258
%v
O
obscuren 已提交
259
Uncles:
O
obscuren 已提交
260 261
%v
}
O
obscuren 已提交
262
`, self.header.Hash(), self.Size(), self.Td, self.header.HashNoNonce(), self.header, self.transactions, self.uncles)
O
obscuren 已提交
263 264 265
}

func (self *Header) String() string {
O
obscuren 已提交
266 267 268 269 270 271 272 273 274 275 276 277 278 279
	return fmt.Sprintf(`
	ParentHash:	    %x
	UncleHash:	    %x
	Coinbase:	    %x
	Root:		    %x
	TxSha		    %x
	ReceiptSha:	    %x
	Bloom:		    %x
	Difficulty:	    %v
	Number:		    %v
	GasLimit:	    %v
	GasUsed:	    %v
	Time:		    %v
	Extra:		    %v
O
obscuren 已提交
280 281
	MixDigest:          %x
	Nonce:		    %x`,
O
obscuren 已提交
282
		self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra, self.MixDigest, self.Nonce)
M
Maran 已提交
283
}
O
obscuren 已提交
284

O
obscuren 已提交
285
type Blocks []*Block
286

O
obscuren 已提交
287
type BlockBy func(b1, b2 *Block) bool
O
obscuren 已提交
288

O
obscuren 已提交
289 290 291 292
func (self BlockBy) Sort(blocks Blocks) {
	bs := blockSorter{
		blocks: blocks,
		by:     self,
O
obscuren 已提交
293
	}
O
obscuren 已提交
294
	sort.Sort(bs)
O
obscuren 已提交
295
}
O
obscuren 已提交
296

O
obscuren 已提交
297 298 299
type blockSorter struct {
	blocks Blocks
	by     func(b1, b2 *Block) bool
O
obscuren 已提交
300
}
O
obscuren 已提交
301

O
obscuren 已提交
302 303 304
func (self blockSorter) Len() int { return len(self.blocks) }
func (self blockSorter) Swap(i, j int) {
	self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i]
O
obscuren 已提交
305
}
O
obscuren 已提交
306
func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) }
O
obscuren 已提交
307

O
obscuren 已提交
308
func Number(b1, b2 *Block) bool { return b1.Header().Number.Cmp(b2.Header().Number) < 0 }