-
Notifications
You must be signed in to change notification settings - Fork 4
/
checked_extrinsic.go
105 lines (89 loc) 路 3.62 KB
/
checked_extrinsic.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package types
import (
sc "github.com/LimeChain/goscale"
"github.com/LimeChain/gosemble/frame/support"
"github.com/LimeChain/gosemble/primitives/log"
primitives "github.com/LimeChain/gosemble/primitives/types"
)
// CheckedExtrinsic is the definition of something that the external world might want to say; its
// existence implies that it has been checked and is good, particularly
// in regard to the signature.
type checkedExtrinsic struct {
// Who this purports to be from and the number of extrinsics have come before
// from the same signer, if anyone (note this is not a signature).
signer sc.Option[primitives.AccountId]
function primitives.Call
extra primitives.SignedExtra
transactional support.Transactional[primitives.PostDispatchInfo]
}
func NewCheckedExtrinsic(signer sc.Option[primitives.AccountId], function primitives.Call, extra primitives.SignedExtra, logger log.WarnLogger) primitives.CheckedExtrinsic {
return checkedExtrinsic{
signer: signer,
function: function,
extra: extra,
transactional: support.NewTransactional[primitives.PostDispatchInfo](logger),
}
}
func (c checkedExtrinsic) Function() primitives.Call {
return c.function
}
func (c checkedExtrinsic) Apply(validator primitives.UnsignedValidator, info *primitives.DispatchInfo, length sc.Compact) (primitives.PostDispatchInfo, error) {
var (
maybeWho sc.Option[primitives.AccountId]
maybePre sc.Option[sc.Sequence[primitives.Pre]]
)
if c.signer.HasValue {
id := c.signer.Value
pre, err := c.extra.PreDispatch(id, c.function, info, length)
if err != nil {
return primitives.PostDispatchInfo{}, err
}
maybeWho, maybePre = sc.NewOption[primitives.AccountId](id), sc.NewOption[sc.Sequence[primitives.Pre]](pre)
} else {
// Do any pre-flight stuff for an unsigned transaction.
//
// Note this function by default delegates to `ValidateUnsigned`, so that
// all checks performed for the transaction queue are also performed during
// the dispatch phase (applying the extrinsic).
//
// If you ever override this function, you need to make sure to always
// perform the same validation as in `ValidateUnsigned`.
err := c.extra.PreDispatchUnsigned(c.function, info, length)
if err != nil {
return primitives.PostDispatchInfo{}, err
}
_, err = validator.PreDispatch(c.function)
if err != nil {
return primitives.PostDispatchInfo{}, err
}
maybeWho, maybePre = sc.NewOption[primitives.AccountId](nil), sc.NewOption[sc.Sequence[primitives.Pre]](nil)
}
postInfo, err := c.transactional.WithStorageLayer(
func() (primitives.PostDispatchInfo, error) {
return c.dispatch(maybeWho)
},
)
// TODO: handle error
if err := c.extra.PostDispatch(maybePre, info, &postInfo, length, err); err != nil {
return primitives.PostDispatchInfo{}, err
}
return postInfo, err
}
func (c checkedExtrinsic) Validate(validator primitives.UnsignedValidator, source primitives.TransactionSource, info *primitives.DispatchInfo, length sc.Compact) (primitives.ValidTransaction, error) {
if c.signer.HasValue {
id := c.signer.Value
return c.extra.Validate(id, c.function, info, length)
}
valid, err := c.extra.ValidateUnsigned(c.function, info, length)
if err != nil {
return primitives.ValidTransaction{}, err
}
unsignedValidation, err := validator.ValidateUnsigned(source, c.function)
if err != nil {
return primitives.ValidTransaction{}, err
}
return valid.CombineWith(unsignedValidation), nil
}
func (c checkedExtrinsic) dispatch(maybeWho sc.Option[primitives.AccountId]) (primitives.PostDispatchInfo, error) {
return c.function.Dispatch(primitives.RawOriginFrom(maybeWho), c.function.Args())
}