/
grant.go
120 lines (97 loc) · 3.19 KB
/
grant.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
package tx
import (
"bytes"
"encoding/binary"
"encoding/json"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto"
tmbytes "github.com/tendermint/tendermint/libs/bytes"
"github.com/amolabs/amoabci/amo/code"
"github.com/amolabs/amoabci/amo/store"
"github.com/amolabs/amoabci/amo/types"
)
type GrantParam struct {
Recipient crypto.Address `json:"recipient"`
Target tmbytes.HexBytes `json:"target"`
Custody tmbytes.HexBytes `json:"custody"`
Extra json.RawMessage `json:"extra,omitempty"`
}
func parseGrantParam(raw []byte) (GrantParam, error) {
var param GrantParam
err := json.Unmarshal(raw, ¶m)
if err != nil {
return param, err
}
return param, nil
}
type TxGrant struct {
TxBase
Param GrantParam `json:"-"`
}
var _ Tx = &TxGrant{}
func (t *TxGrant) Check() (uint32, string) {
txParam, err := parseGrantParam(t.getPayload())
if err != nil {
return code.TxCodeBadParam, err.Error()
}
// TODO: check format
if len(txParam.Recipient) != crypto.AddressSize {
return code.TxCodeBadParam, "improper recipient address"
}
return code.TxCodeOK, "ok"
}
func (t *TxGrant) Execute(store *store.Store) (uint32, string, []abci.Event) {
txParam, err := parseGrantParam(t.getPayload())
if err != nil {
return code.TxCodeBadParam, err.Error(), nil
}
if len(txParam.Recipient) != crypto.AddressSize {
return code.TxCodeBadParam, "improper recipient address", nil
}
grantor := t.GetSender()
parcel := store.GetParcel(txParam.Target, false)
if parcel == nil {
return code.TxCodeParcelNotFound, "parcel not found", nil
}
if !bytes.Equal(parcel.Owner, grantor) &&
!bytes.Equal(parcel.ProxyAccount, grantor) {
return code.TxCodePermissionDenied, "permission denied", nil
}
usage := store.GetUsage(txParam.Recipient, txParam.Target, false)
if usage != nil {
return code.TxCodeAlreadyGranted, "parcel already granted", nil
}
request := store.GetRequest(txParam.Recipient, txParam.Target, false)
if request == nil {
return code.TxCodeRequestNotFound, "parcel not requested", nil
}
storageID := binary.BigEndian.Uint32(txParam.Target[:types.StorageIDLen])
storage := store.GetStorage(storageID, false)
if storage == nil || storage.Active == false {
return code.TxCodeNoStorage, "no active storage for this parcel", nil
}
balance := store.GetBalance(parcel.Owner, false)
if balance.Add(&request.Payment).LessThan(&storage.HostingFee) {
return code.TxCodeNotEnoughBalance,
"not enough balance for hosting fee", nil
}
store.DeleteRequest(txParam.Recipient, txParam.Target)
store.SetUsage(txParam.Recipient, txParam.Target, &types.Usage{
Custody: txParam.Custody,
Extra: types.Extra{
Register: request.Extra.Register,
Request: request.Extra.Request,
Grant: txParam.Extra,
},
})
balance = store.GetBalance(parcel.Owner, false)
balance.Add(&request.Payment).Sub(&storage.HostingFee)
store.SetBalance(parcel.Owner, balance)
balance = store.GetBalance(storage.Owner, false)
balance.Add(&storage.HostingFee)
store.SetBalance(storage.Owner, balance)
balance = store.GetBalance(request.Dealer, false)
balance.Add(&request.DealerFee)
store.SetBalance(request.Dealer, balance)
return code.TxCodeOK, "ok", []abci.Event{}
}