This repository has been archived by the owner on Mar 22, 2024. It is now read-only.
forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
keeper.go
135 lines (113 loc) · 3.42 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
package pow
import (
"fmt"
"strconv"
sdk "github.com/cosmos/cosmos-sdk/types"
bank "github.com/cosmos/cosmos-sdk/x/bank"
)
// module users must specify coin denomination and reward (constant) per PoW solution
type Config struct {
Denomination string
Reward int64
}
// genesis info must specify starting difficulty and starting count
type Genesis struct {
Difficulty uint64 `json:"difficulty"`
Count uint64 `json:"count"`
}
// POW Keeper
type Keeper struct {
key sdk.StoreKey
config Config
ck bank.Keeper
codespace sdk.CodespaceType
}
func NewConfig(denomination string, reward int64) Config {
return Config{denomination, reward}
}
func NewKeeper(key sdk.StoreKey, config Config, ck bank.Keeper, codespace sdk.CodespaceType) Keeper {
return Keeper{key, config, ck, codespace}
}
// InitGenesis for the POW module
func InitGenesis(ctx sdk.Context, k Keeper, genesis Genesis) error {
k.SetLastDifficulty(ctx, genesis.Difficulty)
k.SetLastCount(ctx, genesis.Count)
return nil
}
// WriteGenesis for the PoW module
func WriteGenesis(ctx sdk.Context, k Keeper) Genesis {
difficulty, err := k.GetLastDifficulty(ctx)
if err != nil {
panic(err)
}
count, err := k.GetLastCount(ctx)
if err != nil {
panic(err)
}
return Genesis{
difficulty,
count,
}
}
var lastDifficultyKey = []byte("lastDifficultyKey")
// get the last mining difficulty
func (k Keeper) GetLastDifficulty(ctx sdk.Context) (uint64, error) {
store := ctx.KVStore(k.key)
stored := store.Get(lastDifficultyKey)
if stored == nil {
panic("no stored difficulty")
} else {
return strconv.ParseUint(string(stored), 0, 64)
}
}
// set the last mining difficulty
func (k Keeper) SetLastDifficulty(ctx sdk.Context, diff uint64) {
store := ctx.KVStore(k.key)
store.Set(lastDifficultyKey, []byte(strconv.FormatUint(diff, 16)))
}
var countKey = []byte("count")
// get the last count
func (k Keeper) GetLastCount(ctx sdk.Context) (uint64, error) {
store := ctx.KVStore(k.key)
stored := store.Get(countKey)
if stored == nil {
panic("no stored count")
} else {
return strconv.ParseUint(string(stored), 0, 64)
}
}
// set the last count
func (k Keeper) SetLastCount(ctx sdk.Context, count uint64) {
store := ctx.KVStore(k.key)
store.Set(countKey, []byte(strconv.FormatUint(count, 16)))
}
// Is the keeper state valid?
func (k Keeper) CheckValid(ctx sdk.Context, difficulty uint64, count uint64) (uint64, uint64, sdk.Error) {
lastDifficulty, err := k.GetLastDifficulty(ctx)
if err != nil {
return 0, 0, ErrNonexistentDifficulty(k.codespace)
}
newDifficulty := lastDifficulty + 1
lastCount, err := k.GetLastCount(ctx)
if err != nil {
return 0, 0, ErrNonexistentCount(k.codespace)
}
newCount := lastCount + 1
if count != newCount {
return 0, 0, ErrInvalidCount(k.codespace, fmt.Sprintf("invalid count: was %d, should have been %d", count, newCount))
}
if difficulty != newDifficulty {
return 0, 0, ErrInvalidDifficulty(k.codespace, fmt.Sprintf("invalid difficulty: was %d, should have been %d", difficulty, newDifficulty))
}
return newDifficulty, newCount, nil
}
// Add some coins for a POW well done
func (k Keeper) ApplyValid(ctx sdk.Context, sender sdk.AccAddress, newDifficulty uint64, newCount uint64) sdk.Error {
_, _, ckErr := k.ck.AddCoins(ctx, sender, []sdk.Coin{sdk.NewCoin(k.config.Denomination, k.config.Reward)})
if ckErr != nil {
return ckErr
}
k.SetLastDifficulty(ctx, newDifficulty)
k.SetLastCount(ctx, newCount)
return nil
}