Skip to content
Permalink
Browse files

Merge pull request #1572 from rlan35/cross-link-fork

Add cross-shard tx backward compatibility
  • Loading branch information...
rlan35 committed Sep 11, 2019
2 parents 11ad512 + 4899b24 commit aafdaa47b93dcb875a5f98c286ffd21aff43d999
Showing with 45 additions and 33 deletions.
  1. +9 −3 core/block_validator.go
  2. +14 −13 core/blockchain.go
  3. +3 −3 core/state_processor.go
  4. +4 −0 node/node_newblock.go
  5. +15 −14 node/worker/worker.go
@@ -98,9 +98,11 @@ func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *stat
return fmt.Errorf("invalid receipt root hash (remote: %x local: %x)", header.ReceiptHash(), receiptSha)
}

cxsSha := types.DeriveMultipleShardsSha(cxReceipts)
if cxsSha != header.OutgoingReceiptHash() {
return fmt.Errorf("invalid cross shard receipt root hash (remote: %x local: %x)", header.OutgoingReceiptHash(), cxsSha)
if v.config.IsCrossTx(block.Epoch()) {
cxsSha := types.DeriveMultipleShardsSha(cxReceipts)
if cxsSha != header.OutgoingReceiptHash() {
return fmt.Errorf("invalid cross shard receipt root hash (remote: %x local: %x)", header.OutgoingReceiptHash(), cxsSha)
}
}

// Validate the state root against the received state root and throw
@@ -171,6 +173,10 @@ func CalcGasLimit(parent *types.Block, gasFloor, gasCeil uint64) uint64 {

// ValidateCXReceiptsProof checks whether the given CXReceiptsProof is consistency with itself
func (v *BlockValidator) ValidateCXReceiptsProof(cxp *types.CXReceiptsProof) error {
if !v.config.IsCrossTx(cxp.Header.Epoch()) {
return ctxerror.New("[ValidateCXReceiptsProof] cross shard receipt received before cx fork")
}

toShardID, err := cxp.GetToShardID()
if err != nil {
return ctxerror.New("[ValidateCXReceiptsProof] invalid shardID").WithCause(err)
@@ -1076,22 +1076,23 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
rawdb.WriteReceipts(batch, block.Hash(), block.NumberU64(), receipts)

epoch := block.Header().Epoch()
shardingConfig := ShardingSchedule.InstanceForEpoch(epoch)
shardNum := int(shardingConfig.NumShards())
for i := 0; i < shardNum; i++ {
if i == int(block.ShardID()) {
continue
}
shardReceipts := GetToShardReceipts(cxReceipts, uint32(i))
err := rawdb.WriteCXReceipts(batch, uint32(i), block.NumberU64(), block.Hash(), shardReceipts, false)
if err != nil {
utils.Logger().Debug().Err(err).Interface("shardReceipts", shardReceipts).Int("toShardID", i).Msg("WriteCXReceipts cannot write into database")
if bc.chainConfig.IsCrossTx(block.Epoch()) {
shardingConfig := ShardingSchedule.InstanceForEpoch(epoch)
shardNum := int(shardingConfig.NumShards())
for i := 0; i < shardNum; i++ {
if i == int(block.ShardID()) {
continue
}
shardReceipts := GetToShardReceipts(cxReceipts, uint32(i))
err := rawdb.WriteCXReceipts(batch, uint32(i), block.NumberU64(), block.Hash(), shardReceipts, false)
if err != nil {
utils.Logger().Debug().Err(err).Interface("shardReceipts", shardReceipts).Int("toShardID", i).Msg("WriteCXReceipts cannot write into database")
}
}
// Mark incomingReceipts in the block as spent
bc.WriteCXReceiptsProofSpent(block.IncomingReceipts())
}

// Mark incomingReceipts in the block as spent
bc.WriteCXReceiptsProofSpent(block.IncomingReceipts())

// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
@@ -103,8 +103,8 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.DB, cfg vm.C
}

// return true if it is valid
func getTransactionType(header *block.Header, tx *types.Transaction) types.TransactionType {
if tx.ShardID() == tx.ToShardID() && header.ShardID() == tx.ShardID() {
func getTransactionType(config *params.ChainConfig, header *block.Header, tx *types.Transaction) types.TransactionType {
if header.ShardID() == tx.ShardID() && (!config.IsCrossTx(header.Epoch()) || tx.ShardID() == tx.ToShardID()) {
return types.SameShardTx
}
numShards := ShardingSchedule.InstanceForEpoch(header.Epoch()).NumShards()
@@ -120,7 +120,7 @@ func getTransactionType(header *block.Header, tx *types.Transaction) types.Trans
// for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.DB, header *block.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, *types.CXReceipt, uint64, error) {
txType := getTransactionType(header, tx)
txType := getTransactionType(config, header, tx)
if txType == types.InvalidTx {
return nil, nil, 0, fmt.Errorf("Invalid Transaction Type")
}
@@ -193,6 +193,10 @@ func (node *Node) proposeLocalShardState(block *types.Block) {
}

func (node *Node) proposeReceiptsProof() []*types.CXReceiptsProof {
if !node.Blockchain().Config().IsCrossTx(node.Worker.GetNewEpoch()) {
return []*types.CXReceiptsProof{}
}

numProposed := 0
validReceiptsList := []*types.CXReceiptsProof{}
pendingReceiptsList := []*types.CXReceiptsProof{}
@@ -234,14 +234,8 @@ func (w *Worker) UpdateCurrent(coinbase common.Address) error {
parent := w.chain.CurrentBlock()
num := parent.Number()
timestamp := time.Now().Unix()
// New block's epoch is the same as parent's...
epoch := new(big.Int).Set(parent.Header().Epoch())

// TODO: Don't depend on sharding state for epoch change.
if len(parent.Header().ShardState()) > 0 && parent.NumberU64() != 0 {
// ... except if parent has a resharding assignment it increases by 1.
epoch = epoch.Add(epoch, common.Big1)
}
epoch := w.GetNewEpoch()
header := w.factory.NewHeader(epoch).With().
ParentHash(parent.Hash()).
Number(num.Add(num, common.Big1)).
@@ -273,6 +267,19 @@ func (w *Worker) GetCurrentState() *state.DB {
return w.current.state
}

// GetNewEpoch gets the current epoch.
func (w *Worker) GetNewEpoch() *big.Int {
parent := w.chain.CurrentBlock()
epoch := new(big.Int).Set(parent.Header().Epoch())

// TODO: Don't depend on sharding state for epoch change.
if len(parent.Header().ShardState()) > 0 && parent.NumberU64() != 0 {
// ... except if parent has a resharding assignment it increases by 1.
epoch = epoch.Add(epoch, common.Big1)
}
return epoch
}

// GetCurrentReceipts get the receipts generated starting from the last state.
func (w *Worker) GetCurrentReceipts() []*types.Receipt {
return w.current.receipts
@@ -360,14 +367,8 @@ func New(config *params.ChainConfig, chain *core.BlockChain, engine consensus_en
parent := worker.chain.CurrentBlock()
num := parent.Number()
timestamp := time.Now().Unix()
// New block's epoch is the same as parent's...
epoch := parent.Header().Epoch()

// TODO: Don't depend on sharding state for epoch change.
if len(parent.Header().ShardState()) > 0 && parent.NumberU64() != 0 {
// ... except if parent has a resharding assignment it increases by 1.
epoch = epoch.Add(epoch, common.Big1)
}
epoch := worker.GetNewEpoch()
header := worker.factory.NewHeader(epoch).With().
ParentHash(parent.Hash()).
Number(num.Add(num, common.Big1)).

0 comments on commit aafdaa4

Please sign in to comment.
You can’t perform that action at this time.