/
keeper.go
143 lines (121 loc) · 4.88 KB
/
keeper.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package keeper
import (
"errors"
"fmt"
"github.com/kelindar/bitmap"
"github.com/tendermint/tendermint/libs/log"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
bankKeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
stratos "github.com/stratosnet/stratos-chain/types"
potKeeper "github.com/stratosnet/stratos-chain/x/pot/keeper"
registerKeeper "github.com/stratosnet/stratos-chain/x/register/keeper"
registertypes "github.com/stratosnet/stratos-chain/x/register/types"
"github.com/stratosnet/stratos-chain/x/sds/types"
)
// Keeper encodes/decodes files using the go-amino (binary)
// encoding/decoding library.
type Keeper struct {
key sdk.StoreKey
cdc codec.Codec
paramSpace paramtypes.Subspace
bankKeeper bankKeeper.Keeper
registerKeeper registerKeeper.Keeper
potKeeper potKeeper.Keeper
}
// NewKeeper returns a new sdk.NewKeeper that uses go-amino to
// (binary) encode and decode concrete sdk.MsgUploadFile.
// nolint
func NewKeeper(
cdc codec.Codec,
key sdk.StoreKey,
paramSpace paramtypes.Subspace,
bankKeeper bankKeeper.Keeper,
registerKeeper registerKeeper.Keeper,
potKeeper potKeeper.Keeper,
) Keeper {
return Keeper{
key: key,
cdc: cdc,
paramSpace: paramSpace.WithKeyTable(types.ParamKeyTable()),
bankKeeper: bankKeeper,
registerKeeper: registerKeeper,
potKeeper: potKeeper,
}
}
// Logger returns a module-specific logger.
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName))
}
func (k Keeper) FileUpload(ctx sdk.Context, fileHash string, reporter stratos.SdsAddress, reporterOwner, uploader sdk.AccAddress) (err error) {
if !(k.registerKeeper.OwnMetaNode(ctx, reporterOwner, reporter)) {
return types.ErrReporterAddressOrOwner
}
var fileUploadReporters bitmap.Bitmap
// query exist fileInfo which sent by other meta node
fileInfo, found := k.GetFileInfoByFileHash(ctx, []byte(fileHash))
if !found {
fileUploadReporters = bitmap.Bitmap{}
} else {
fileUploadReporters = bitmap.FromBytes(fileInfo.GetReporters())
}
reporterIndex, err := k.registerKeeper.GetMetaNodeBitMapIndex(ctx, reporter)
fileUploadReporters.Set(uint32(reporterIndex))
height := sdk.NewInt(ctx.BlockHeight())
newFileInfo := types.NewFileInfo(height, fileUploadReporters.ToBytes(), uploader.String())
k.SetFileInfo(ctx, []byte(fileHash), newFileInfo)
return nil
}
// [S] is the initial genesis deposit by all Resource Nodes and Meta Nodes at t=0
// The current unissued prepay Volume Pool [Pt] is the total remaining prepay STOS kept by the Stratos Network but not yet issued to Resource Nodes as rewards.
// The remaining total Ozone limit [Lt] is the upper bound of the total Ozone that users can purchase from the Stratos blockchain.
// [X] is the total amount of STOS token prepaid by user at time t
// the total amount of Ozone the user gets = Lt * X / (S + Pt + X)
func (k Keeper) purchaseNozAndSubCoins(ctx sdk.Context, from sdk.AccAddress, amount sdk.Int) (sdk.Int, error) {
St := k.registerKeeper.GetEffectiveTotalDeposit(ctx)
Pt := k.registerKeeper.GetTotalUnissuedPrepay(ctx).Amount
Lt := k.registerKeeper.GetRemainingOzoneLimit(ctx)
purchased := Lt.ToDec().
Mul(amount.ToDec()).
Quo((St.
Add(Pt).
Add(amount)).ToDec()).
TruncateInt()
if purchased.GT(Lt) {
return sdk.ZeroInt(), errors.New("not enough remaining ozone limit to complete prepay")
}
// send coins to total unissued prepay pool
prepayAmt := sdk.NewCoin(k.BondDenom(ctx), amount)
err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, from, registertypes.TotalUnissuedPrepay, sdk.NewCoins(prepayAmt))
if err != nil {
return sdk.ZeroInt(), err
}
// update remaining noz limit
newRemainingOzoneLimit := Lt.Sub(purchased)
k.registerKeeper.SetRemainingOzoneLimit(ctx, newRemainingOzoneLimit)
return purchased, nil
}
func (k Keeper) simulatePurchaseNoz(ctx sdk.Context, coins sdk.Coins) sdk.Int {
amount := coins.AmountOf(k.BondDenom(ctx))
St := k.registerKeeper.GetEffectiveTotalDeposit(ctx)
Pt := k.registerKeeper.GetTotalUnissuedPrepay(ctx).Amount
Lt := k.registerKeeper.GetRemainingOzoneLimit(ctx)
purchased := Lt.ToDec().
Mul(amount.ToDec()).
Quo((St.
Add(Pt).
Add(amount)).ToDec()).
TruncateInt()
return purchased
}
// Prepay transfers coins from bank to sds (volumn) pool
func (k Keeper) Prepay(ctx sdk.Context, sender sdk.AccAddress, coins sdk.Coins) (sdk.Int, error) {
validPrepayAmt := coins.AmountOf(k.BondDenom(ctx))
hasCoin := k.bankKeeper.HasBalance(ctx, sender, sdk.NewCoin(k.BondDenom(ctx), validPrepayAmt))
if !hasCoin {
return sdk.ZeroInt(), sdkerrors.Wrapf(sdkerrors.ErrInsufficientFunds, "Insufficient balance in the acc %s", sender.String())
}
return k.purchaseNozAndSubCoins(ctx, sender, validPrepayAmt)
}