This repository has been archived by the owner on Jul 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
direct.go
127 lines (107 loc) · 2.83 KB
/
direct.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package auth
import (
"context"
"github.com/ava-labs/hypersdk/chain"
"github.com/ava-labs/hypersdk/codec"
"github.com/ava-labs/hypersdk/crypto"
"github.com/ava-labs/indexvm/storage"
)
var _ chain.Auth = (*Direct)(nil)
type Direct struct {
Signer crypto.PublicKey `json:"signer"`
Signature crypto.Signature `json:"signature"`
}
func (*Direct) MaxUnits(
chain.Rules,
) uint64 {
return crypto.PublicKeyLen + crypto.SignatureLen*5 // make signatures more expensive
}
func (*Direct) ValidRange(chain.Rules) (int64, int64) {
return -1, -1
}
func (d *Direct) StateKeys() [][]byte {
return [][]byte{
storage.PrefixBalanceKey(d.Signer), // fee payer
storage.PrefixPermissionsKey(d.Signer, d.Signer),
}
}
func (d *Direct) AsyncVerify(msg []byte) error {
if !crypto.Verify(msg, d.Signer, d.Signature) {
return ErrInvalidSignature
}
return nil
}
// Verify could be used to perform complex ACL rules that require state access
// to check.
func (d *Direct) Verify(
ctx context.Context,
r chain.Rules,
db chain.Database,
action chain.Action,
) (uint64, error) {
// Could have modified perms before doing a simple signature so we must check
// to make sure we are still authorized to act on behalf of [Signer]
if err := Authorized(ctx, db, action, d.Signer, d.Signer, true); err != nil {
return 0, err
}
return d.MaxUnits(r), nil
}
func (d *Direct) Payer() []byte {
return d.Signer[:]
}
func (d *Direct) Marshal(p *codec.Packer) {
p.PackPublicKey(d.Signer)
p.PackSignature(d.Signature)
}
func UnmarshalDirect(p *codec.Packer) (chain.Auth, error) {
var d Direct
p.UnpackPublicKey(&d.Signer)
p.UnpackSignature(&d.Signature)
return &d, p.Err()
}
func (d *Direct) CanDeduct(
ctx context.Context,
db chain.Database,
amount uint64,
) error {
// Account must exist if [u] > 0
u, _, err := storage.GetBalance(ctx, db, d.Signer)
if err != nil {
return err
}
if u < amount {
return storage.ErrInvalidBalance
}
return nil
}
func (d *Direct) Deduct(
ctx context.Context,
db chain.Database,
amount uint64,
) error {
return storage.SubUnlockedBalance(ctx, db, d.Signer, amount)
}
func (d *Direct) Refund(
ctx context.Context,
db chain.Database,
amount uint64,
) error {
// Discard any funds returned if the account doesn't exist
//
// This could occur if the transaction closes out the account
_, err := storage.AddUnlockedBalance(ctx, db, d.Signer, amount, true)
return err
}
var _ chain.AuthFactory = (*DirectFactory)(nil)
func NewDirectFactory(priv crypto.PrivateKey) *DirectFactory {
return &DirectFactory{priv}
}
type DirectFactory struct {
priv crypto.PrivateKey
}
func (d *DirectFactory) Sign(msg []byte, _ chain.Action) (chain.Auth, error) {
sig := crypto.Sign(msg, d.priv)
return &Direct{d.priv.PublicKey(), sig}, nil
}