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 }