aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSonic <sonic@dexon.org>2019-01-18 11:55:51 +0800
committerWei-Ning Huang <w@dexon.org>2019-03-12 12:19:09 +0800
commit0826bd64ff765250ff5a4b2448eadc98d3285c03 (patch)
treef818191c9e8e6441c43bf47fdb6b224988d60ad6
parentcd0d64a6deba5e1fef2b71e341afa67e09c1b639 (diff)
downloaddexon-0826bd64ff765250ff5a4b2448eadc98d3285c03.tar
dexon-0826bd64ff765250ff5a4b2448eadc98d3285c03.tar.gz
dexon-0826bd64ff765250ff5a4b2448eadc98d3285c03.tar.bz2
dexon-0826bd64ff765250ff5a4b2448eadc98d3285c03.tar.lz
dexon-0826bd64ff765250ff5a4b2448eadc98d3285c03.tar.xz
dexon-0826bd64ff765250ff5a4b2448eadc98d3285c03.tar.zst
dexon-0826bd64ff765250ff5a4b2448eadc98d3285c03.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.
-rw-r--r--core/block_validator.go14
-rw-r--r--core/blockchain.go6
-rw-r--r--core/blockchain_test.go38
-rw-r--r--core/types.go3
-rw-r--r--core/types/block.go6
-rw-r--r--dex/app.go25
-rw-r--r--dex/app_test.go12
7 files changed, 30 insertions, 74 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 80d11becd..2567505b8 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 e0e7671e1..d18cfd604 100644
--- a/core/blockchain_test.go
+++ b/core/blockchain_test.go
@@ -1456,20 +1456,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)
}
@@ -1517,11 +1509,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)
}
@@ -1540,11 +1528,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)
}
@@ -1558,16 +1542,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)
}
@@ -1595,11 +1575,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 f98dfbf94..137585b6a 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.
diff --git a/dex/app.go b/dex/app.go
index 3ea8953f5..e4fac8c7f 100644
--- a/dex/app.go
+++ b/dex/app.go
@@ -298,10 +298,7 @@ func (d *DexconApp) PrepareWitness(consensusHeight uint64) (witness coreTypes.Wi
return witness, fmt.Errorf("current height < consensus height")
}
- witnessData, err := rlp.EncodeToBytes(&types.WitnessData{
- Root: witnessBlock.Root(),
- ReceiptHash: witnessBlock.ReceiptHash(),
- })
+ witnessData, err := rlp.EncodeToBytes(witnessBlock.Hash())
if err != nil {
return
}
@@ -314,8 +311,8 @@ func (d *DexconApp) PrepareWitness(consensusHeight uint64) (witness coreTypes.Wi
// VerifyBlock verifies if the payloads are valid.
func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifyStatus {
- var witnessData types.WitnessData
- err := rlp.DecodeBytes(block.Witness.Data, &witnessData)
+ var witnessBlockHash common.Hash
+ err := rlp.DecodeBytes(block.Witness.Data, &witnessBlockHash)
if err != nil {
log.Error("Failed to RLP decode witness data", "error", err)
return coreTypes.VerifyInvalidBlock
@@ -329,23 +326,19 @@ func (d *DexconApp) VerifyBlock(block *coreTypes.Block) coreTypes.BlockVerifySta
b := d.blockchain.GetBlockByNumber(block.Witness.Height)
if b == nil {
- log.Error("Can not get block by height %v", block.Witness.Height)
+ log.Error("Can not get block by height", "height", block.Witness.Height)
return coreTypes.VerifyInvalidBlock
}
- if b.Root() != witnessData.Root {
- log.Error("Witness root not correct expect %v but %v", b.Root(), witnessData.Root)
+ if b.Hash() != witnessBlockHash {
+ log.Error("Witness block hash not match",
+ "expect", b.Hash().String(), "got", witnessBlockHash.String())
return coreTypes.VerifyInvalidBlock
}
- if b.ReceiptHash() != witnessData.ReceiptHash {
- log.Error("Witness receipt hash not correct expect %v but %v", b.ReceiptHash(), witnessData.ReceiptHash)
- return coreTypes.VerifyInvalidBlock
- }
-
- _, err = d.blockchain.StateAt(witnessData.Root)
+ _, err = d.blockchain.StateAt(b.Root())
if err != nil {
- log.Error("Get state by root %v error: %v", witnessData.Root, err)
+ log.Error("Get state by root %v error: %v", b.Root(), err)
return coreTypes.VerifyInvalidBlock
}
diff --git a/dex/app_test.go b/dex/app_test.go
index 7d665a0af..34b31d3d3 100644
--- a/dex/app_test.go
+++ b/dex/app_test.go
@@ -119,18 +119,14 @@ func TestPrepareWitness(t *testing.T) {
t.Fatalf("unexpeted witness height %v", witness.Height)
}
- var witnessData types.WitnessData
- err = rlp.DecodeBytes(witness.Data, &witnessData)
+ var witnessBlockHash common.Hash
+ err = rlp.DecodeBytes(witness.Data, &witnessBlockHash)
if err != nil {
t.Fatalf("rlp decode error: %v", err)
}
- if witnessData.Root != currentBlock.Root() {
- t.Fatalf("expect root %v but %v", currentBlock.Root(), witnessData.Root)
- }
-
- if witnessData.ReceiptHash != currentBlock.ReceiptHash() {
- t.Fatalf("expect receipt hash %v but %v", currentBlock.ReceiptHash(), witnessData.ReceiptHash)
+ if witnessBlockHash != currentBlock.Hash() {
+ t.Fatalf("expect root %v but %v", currentBlock.Hash(), witnessBlockHash)
}
if _, err := dex.app.PrepareWitness(999); err == nil {