-
Notifications
You must be signed in to change notification settings - Fork 208
/
predicate_check.go
67 lines (57 loc) · 2.46 KB
/
predicate_check.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// (c) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package core
import (
"errors"
"fmt"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/subnet-evm/core/types"
"github.com/ava-labs/subnet-evm/params"
"github.com/ava-labs/subnet-evm/precompile/precompileconfig"
"github.com/ava-labs/subnet-evm/predicate"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
var ErrMissingPredicateContext = errors.New("missing predicate context")
// CheckPredicates verifies the predicates of [tx] and returns the result. Returning an error invalidates the block.
func CheckPredicates(rules params.Rules, predicateContext *precompileconfig.PredicateContext, tx *types.Transaction) (map[common.Address][]byte, error) {
// Check that the transaction can cover its IntrinsicGas (including the gas required by the predicate) before
// verifying the predicate.
intrinsicGas, err := IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, rules)
if err != nil {
return nil, err
}
if tx.Gas() < intrinsicGas {
return nil, fmt.Errorf("%w for predicate verification (%d) < intrinsic gas (%d)", ErrIntrinsicGas, tx.Gas(), intrinsicGas)
}
predicateResults := make(map[common.Address][]byte)
// Short circuit early if there are no precompile predicates to verify
if !rules.PredicatersExist() {
return predicateResults, nil
}
// Prepare the predicate storage slots from the transaction's access list
predicateArguments := predicate.PreparePredicateStorageSlots(rules, tx.AccessList())
// If there are no predicates to verify, return early and skip requiring the proposervm block
// context to be populated.
if len(predicateArguments) == 0 {
return predicateResults, nil
}
if predicateContext == nil || predicateContext.ProposerVMBlockCtx == nil {
return nil, ErrMissingPredicateContext
}
for address, predicates := range predicateArguments {
// Since [address] is only added to [predicateArguments] when there's a valid predicate in the ruleset
// there's no need to check if the predicate exists here.
predicaterContract := rules.Predicaters[address]
bitset := set.NewBits()
for i, predicate := range predicates {
if err := predicaterContract.VerifyPredicate(predicateContext, predicate); err != nil {
bitset.Add(i)
}
}
res := bitset.Bytes()
log.Debug("predicate verify", "tx", tx.Hash(), "address", address, "res", res)
predicateResults[address] = res
}
return predicateResults, nil
}