-
Notifications
You must be signed in to change notification settings - Fork 176
/
transactionSequenceNum.go
84 lines (67 loc) · 2.34 KB
/
transactionSequenceNum.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package fvm
import (
"fmt"
"github.com/opentracing/opentracing-go/log"
"github.com/onflow/flow-go/fvm/errors"
"github.com/onflow/flow-go/fvm/programs"
"github.com/onflow/flow-go/fvm/state"
"github.com/onflow/flow-go/module/trace"
)
type TransactionSequenceNumberChecker struct{}
func NewTransactionSequenceNumberChecker() *TransactionSequenceNumberChecker {
return &TransactionSequenceNumberChecker{}
}
func (c *TransactionSequenceNumberChecker) Process(
_ *VirtualMachine,
ctx *Context,
proc *TransactionProcedure,
sth *state.StateHolder,
programs *programs.Programs,
) error {
return c.checkAndIncrementSequenceNumber(proc, ctx, sth)
}
func (c *TransactionSequenceNumberChecker) checkAndIncrementSequenceNumber(
proc *TransactionProcedure,
ctx *Context,
sth *state.StateHolder,
) error {
if ctx.Tracer != nil && proc.TraceSpan != nil {
span := ctx.Tracer.StartSpanFromParent(proc.TraceSpan, trace.FVMSeqNumCheckTransaction)
span.LogFields(
log.String("transaction.ID", proc.ID.String()),
)
defer span.Finish()
}
parentState := sth.State()
childState := sth.NewChild()
defer func() {
if mergeError := parentState.MergeState(childState); mergeError != nil {
panic(mergeError)
}
sth.SetActiveState(parentState)
}()
accounts := state.NewAccounts(sth)
proposalKey := proc.Transaction.ProposalKey
accountKey, err := accounts.GetPublicKey(proposalKey.Address, proposalKey.KeyIndex)
if err != nil {
err = errors.NewInvalidProposalSignatureError(proposalKey.Address, proposalKey.KeyIndex, err)
return fmt.Errorf("checking sequence number failed: %w", err)
}
if accountKey.Revoked {
err = fmt.Errorf("proposal key has been revoked")
err = errors.NewInvalidProposalSignatureError(proposalKey.Address, proposalKey.KeyIndex, err)
return fmt.Errorf("checking sequence number failed: %w", err)
}
// Note that proposal key verification happens at the txVerifier and not here.
valid := accountKey.SeqNumber == proposalKey.SequenceNumber
if !valid {
return errors.NewInvalidProposalSeqNumberError(proposalKey.Address, proposalKey.KeyIndex, accountKey.SeqNumber, proposalKey.SequenceNumber)
}
accountKey.SeqNumber++
_, err = accounts.SetPublicKey(proposalKey.Address, proposalKey.KeyIndex, accountKey)
if err != nil {
childState.View().DropDelta()
return fmt.Errorf("checking sequence number failed: %w", err)
}
return nil
}