diff options
author | Sonic <sonic@dexon.org> | 2019-01-18 11:55:51 +0800 |
---|---|---|
committer | Wei-Ning Huang <w@byzantine-lab.io> | 2019-06-12 17:27:21 +0800 |
commit | 1c01b079c42bf410997b800c8e97b699e3ce0a93 (patch) | |
tree | 00626fcfc3bd1a4f63fd23efeb7c36f5498cbc9a /core | |
parent | 65045b14287ee4f789a491ae542a58f1f7d559b6 (diff) | |
download | go-tangerine-1c01b079c42bf410997b800c8e97b699e3ce0a93.tar.gz go-tangerine-1c01b079c42bf410997b800c8e97b699e3ce0a93.tar.zst go-tangerine-1c01b079c42bf410997b800c8e97b699e3ce0a93.zip |
core, dex: use block hash as witness data (#160)
Using only state root and receipt root as witness data can not protect
other fields in block header, ex: bloom, difficulty, gas limit, gas
used...
So that everyone can manipulate these fields to create as many valid blocks
at the same height as he want. Although this will not effect the state,
one can spam us when syncing.
Using block hash as witness data can solve this.
Diffstat (limited to 'core')
-rw-r--r-- | core/block_validator.go | 14 | ||||
-rw-r--r-- | core/blockchain.go | 6 | ||||
-rw-r--r-- | core/blockchain_test.go | 38 | ||||
-rw-r--r-- | core/types.go | 3 | ||||
-rw-r--r-- | core/types/block.go | 6 |
5 files changed, 17 insertions, 50 deletions
diff --git a/core/block_validator.go b/core/block_validator.go index c6038381f..f42ea6b11 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -19,6 +19,7 @@ package core import ( "fmt" + "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/consensus" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" @@ -101,20 +102,15 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat return nil } -func (v *BlockValidator) ValidateWitnessData(height uint64, data types.WitnessData) error { +func (v *BlockValidator) ValidateWitnessData(height uint64, blockHash common.Hash) error { b := v.bc.GetBlockByNumber(height) if b == nil { return fmt.Errorf("can not find block %v either pending or confirmed block", height) } - if b.Root() != data.Root { - return fmt.Errorf("invalid witness root %s vs %s", - b.Root().String(), data.Root.String()) - } - - if b.ReceiptHash() != data.ReceiptHash { - return fmt.Errorf("invalid witness receipt hash %s vs %s", - b.ReceiptHash().String(), data.ReceiptHash.String()) + if b.Hash() != blockHash { + return fmt.Errorf("invalid witness block %s vs %s", + b.Hash().String(), blockHash.String()) } return nil } diff --git a/core/blockchain.go b/core/blockchain.go index 99f99b64d..ea1d06489 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1834,13 +1834,13 @@ func (bc *BlockChain) processBlock( ) bstart := time.Now() - var witnessData types.WitnessData - if err := rlp.Decode(bytes.NewReader(witness.Data), &witnessData); err != nil { + var witnessBlockHash common.Hash + if err := rlp.Decode(bytes.NewReader(witness.Data), &witnessBlockHash); err != nil { log.Error("Witness rlp decode failed", "error", err) return nil, nil, nil, fmt.Errorf("rlp decode fail: %v", err) } - if err := bc.Validator().ValidateWitnessData(witness.Height, witnessData); err != nil { + if err := bc.Validator().ValidateWitnessData(witness.Height, witnessBlockHash); err != nil { return nil, nil, nil, fmt.Errorf("validate witness data error: %v", err) } diff --git a/core/blockchain_test.go b/core/blockchain_test.go index 45eb191f2..967d0d3c5 100644 --- a/core/blockchain_test.go +++ b/core/blockchain_test.go @@ -1662,20 +1662,12 @@ func TestProcessBlock(t *testing.T) { for i := 0; i < processNum; i++ { var witnessDataBytes []byte if i == 0 { - witnessData := types.WitnessData{ - Root: gspec.ToBlock(nil).Root(), - ReceiptHash: gspec.ToBlock(nil).ReceiptHash(), - } - witnessDataBytes, err = rlp.EncodeToBytes(&witnessData) + witnessDataBytes, err = rlp.EncodeToBytes(gspec.ToBlock(nil).Hash()) if err != nil { t.Fatalf("rlp encode fail: %v", err) } } else { - witnessData := types.WitnessData{ - Root: chain.CurrentBlock().Root(), - ReceiptHash: chain.CurrentBlock().ReceiptHash(), - } - witnessDataBytes, err = rlp.EncodeToBytes(&witnessData) + witnessDataBytes, err = rlp.EncodeToBytes(chain.CurrentBlock().Hash()) if err != nil { t.Fatalf("rlp encode fail: %v", err) } @@ -1723,11 +1715,7 @@ func TestProcessBlock(t *testing.T) { } // Validate witness fail with unknown block. - witnessData := types.WitnessData{ - Root: chain.CurrentBlock().Root(), - ReceiptHash: chain.CurrentBlock().ReceiptHash(), - } - witnessDataBytes, err := rlp.EncodeToBytes(&witnessData) + witnessDataBytes, err := rlp.EncodeToBytes(chain.CurrentBlock().Hash()) if err != nil { t.Fatalf("rlp encode fail: %v", err) } @@ -1746,11 +1734,7 @@ func TestProcessBlock(t *testing.T) { } // Validate witness fail with unexpected root. - witnessData = types.WitnessData{ - Root: chain.CurrentBlock().Root(), - ReceiptHash: chain.CurrentBlock().ReceiptHash(), - } - witnessDataBytes, err = rlp.EncodeToBytes(&witnessData) + witnessDataBytes, err = rlp.EncodeToBytes(chain.CurrentBlock().Hash()) if err != nil { t.Fatalf("rlp encode fail: %v", err) } @@ -1764,16 +1748,12 @@ func TestProcessBlock(t *testing.T) { Height: processNum - 1, Data: witnessDataBytes, }) - if err == nil || !strings.Contains(err.Error(), "invalid witness root") { + if err == nil || !strings.Contains(err.Error(), "invalid witness block") { t.Fatalf("not expected fail: %v", err) } // Apply transaction fail with insufficient fund. - witnessData = types.WitnessData{ - Root: chain.CurrentBlock().Root(), - ReceiptHash: chain.CurrentBlock().ReceiptHash(), - } - witnessDataBytes, err = rlp.EncodeToBytes(&witnessData) + witnessDataBytes, err = rlp.EncodeToBytes(chain.CurrentBlock().Hash()) if err != nil { t.Fatalf("rlp encode fail: %v", err) } @@ -1801,11 +1781,7 @@ func TestProcessBlock(t *testing.T) { } // Apply transaction fail with nonce too height. - witnessData = types.WitnessData{ - Root: chain.CurrentBlock().Root(), - ReceiptHash: chain.CurrentBlock().ReceiptHash(), - } - witnessDataBytes, err = rlp.EncodeToBytes(&witnessData) + witnessDataBytes, err = rlp.EncodeToBytes(chain.CurrentBlock().Hash()) if err != nil { t.Fatalf("rlp encode fail: %v", err) } diff --git a/core/types.go b/core/types.go index 327031b01..04a787b1e 100644 --- a/core/types.go +++ b/core/types.go @@ -17,6 +17,7 @@ package core import ( + "github.com/dexon-foundation/dexon/common" "github.com/dexon-foundation/dexon/core/state" "github.com/dexon-foundation/dexon/core/types" "github.com/dexon-foundation/dexon/core/vm" @@ -35,7 +36,7 @@ type Validator interface { ValidateState(block, parent *types.Block, state *state.StateDB, receipts types.Receipts, usedGas uint64) error // ValidateWitnessData validates the given witness result. - ValidateWitnessData(height uint64, data types.WitnessData) error + ValidateWitnessData(height uint64, data common.Hash) error } // Processor is an interface for processing blocks using a given initial state. diff --git a/core/types/block.go b/core/types/block.go index 96df245b7..4ff34c229 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -89,12 +89,6 @@ func (n BlockNonce) Value() (driver.Value, error) { return n[:], nil } -// WitnessData represents the witness data. -type WitnessData struct { - Root common.Hash - ReceiptHash common.Hash -} - //go:generate gencodec -type Header -field-override headerMarshaling -out gen_header_json.go // Header represents a block header in the Ethereum blockchain. |