github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/block/validator.go (about)

     1  // Copyright (c) 2020 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package block
     7  
     8  import (
     9  	"context"
    10  	"sync"
    11  
    12  	"github.com/iotexproject/iotex-core/action"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  // Validator is the interface of validator
    17  type Validator interface {
    18  	// Validate validates the given block's content
    19  	Validate(ctx context.Context, block *Block) error
    20  }
    21  
    22  type validator struct {
    23  	subValidator Validator
    24  	validators   []action.SealedEnvelopeValidator
    25  }
    26  
    27  // NewValidator creates a validator with a set of sealed envelope validators
    28  func NewValidator(subsequenceValidator Validator, validators ...action.SealedEnvelopeValidator) Validator {
    29  	return &validator{subValidator: subsequenceValidator, validators: validators}
    30  }
    31  
    32  func (v *validator) Validate(ctx context.Context, blk *Block) error {
    33  	actions := blk.Actions
    34  	// Verify transfers, votes, executions, witness, and secrets
    35  	errChan := make(chan error, len(actions))
    36  
    37  	v.validateActions(ctx, actions, errChan)
    38  	close(errChan)
    39  	for err := range errChan {
    40  		return errors.Wrap(err, "failed to validate action")
    41  	}
    42  
    43  	if v.subValidator != nil {
    44  		return v.subValidator.Validate(ctx, blk)
    45  	}
    46  	return nil
    47  }
    48  
    49  func (v *validator) validateActions(
    50  	ctx context.Context,
    51  	actions []*action.SealedEnvelope,
    52  	errChan chan error,
    53  ) {
    54  	var wg sync.WaitGroup
    55  	for _, selp := range actions {
    56  		wg.Add(1)
    57  		go func(s *action.SealedEnvelope) {
    58  			defer wg.Done()
    59  			for _, sev := range v.validators {
    60  				if err := sev.Validate(ctx, s); err != nil {
    61  					errChan <- err
    62  					return
    63  				}
    64  			}
    65  		}(selp)
    66  	}
    67  	wg.Wait()
    68  }