Skip to content

Commit

Permalink
Handle elided transactions during block processing.
Browse files Browse the repository at this point in the history
  • Loading branch information
nickeskov committed Aug 21, 2024
1 parent 99cc150 commit 8fe1d04
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 8 deletions.
29 changes: 21 additions & 8 deletions pkg/state/appender.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ func (a *txAppender) appendTxs(
if err != nil {
return proto.BlockSnapshot{}, crypto.Digest{}, err
}
_, isBlockWithChallenge := params.block.GetChallengedHeader()
// Check and append transactions.
var bs proto.BlockSnapshot
appendTxArgs := &appendTxParams{
Expand All @@ -697,22 +698,34 @@ func (a *txAppender) appendTxs(
currentMinerPK: params.block.GeneratorPublicKey,
}
for _, tx := range params.transactions {
txSnapshots, errAppendTx := a.appendTx(tx, appendTxArgs)
if errAppendTx != nil {
return proto.BlockSnapshot{}, crypto.Digest{}, errAppendTx
}
bs.AppendTxSnapshot(txSnapshots.regular)

txID, idErr := tx.GetID(a.settings.AddressSchemeCharacter)
if idErr != nil {
return proto.BlockSnapshot{}, crypto.Digest{}, idErr
}

if len(txSnapshots.regular) == 0 { // sanity check
txSnap, errAppendTx := a.appendTx(tx, appendTxArgs)
if errAppendTx != nil { // TODO: check error type for elided tx
if !isBlockWithChallenge {
return proto.BlockSnapshot{}, crypto.Digest{}, errAppendTx
}
txSnap = txSnapshot{
regular: []proto.AtomicSnapshot{
&proto.TransactionStatusSnapshot{Status: proto.TransactionElided},
},
internal: nil,
}
if aErr := txSnap.Apply(a.txHandler.sa, tx, appendTxArgs.validatingUtx); aErr != nil {
return proto.BlockSnapshot{}, crypto.Digest{},
errors.Wrapf(aErr, "failed to apply elided tx (ID=%q) snapshot", base58.Encode(txID))
}
}
bs.AppendTxSnapshot(txSnap.regular)

if len(txSnap.regular) == 0 { // sanity check
return proto.BlockSnapshot{}, crypto.Digest{},
errors.Errorf("snapshot of txID %q cannot be empty", base58.Encode(txID))
}
txSh, shErr := calculateTxSnapshotStateHash(hasher, txID, blockInfo.Height, stateHash, txSnapshots.regular)
txSh, shErr := calculateTxSnapshotStateHash(hasher, txID, blockInfo.Height, stateHash, txSnap.regular)
if shErr != nil {
return proto.BlockSnapshot{}, crypto.Digest{}, errors.Wrapf(shErr,
"failed to calculate tx snapshot hash for txID %q at height %d", base58.Encode(txID), blockInfo.Height,
Expand Down
35 changes: 35 additions & 0 deletions pkg/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -1242,6 +1242,11 @@ func (s *stateManager) beforeAppendBlock(block *proto.Block, blockHeight proto.H
if err := s.stor.scores.appendBlockScore(block, blockHeight); err != nil {
return err
}
// Handle challenged header if it exists.
// Light node fields check performed in ValidateHeaderBeforeBlockApplying.
if chErr := s.handleChallengedHeaderIfExists(block, blockHeight); chErr != nil {
return chErr
}
// Indicate new block for storage.
if err := s.rw.startBlock(block.BlockID()); err != nil {
return err
Expand All @@ -1250,6 +1255,36 @@ func (s *stateManager) beforeAppendBlock(block *proto.Block, blockHeight proto.H
return s.rw.writeBlockHeader(&block.BlockHeader)
}

func (s *stateManager) handleChallengedHeaderIfExists(block *proto.Block, blockHeight proto.Height) error {
challengedHeader, ok := block.GetChallengedHeader()
if !ok { // nothing to do, no challenge to handle
return nil
}
var (
scheme = s.settings.AddressSchemeCharacter
blockID = block.BlockID()
)
challenger, err := proto.NewAddressFromPublicKey(scheme, block.GeneratorPublicKey)
if err != nil {
return errors.Wrapf(err, "failed to create challenger address from public key '%s'",
challengedHeader.GeneratorPublicKey.String(),
)
}
challenged, err := proto.NewAddressFromPublicKey(scheme, challengedHeader.GeneratorPublicKey)
if err != nil {
return errors.Wrapf(err, "failed to create challenged address from public key '%s'",
challengedHeader.GeneratorPublicKey.String(),
)
}
if chErr := s.stor.balances.storeChallenge(challenger.ID(), challenged.ID(), blockHeight, blockID); chErr != nil {
return errors.Wrapf(chErr,
"failed to store challenge for block '%s' at height %d with challenger '%s' and challenged '%s'",
blockID.String(), blockHeight, challenger.String(), challenged.String(),
)
}
return nil
}

func (s *stateManager) afterAppendBlock(block *proto.Block, blockHeight proto.Height) error {
// Let block storage know that the current block is over.
if err := s.rw.finishBlock(block.BlockID()); err != nil {
Expand Down

0 comments on commit 8fe1d04

Please sign in to comment.