-
Notifications
You must be signed in to change notification settings - Fork 0
/
fuel.go
157 lines (134 loc) · 4.68 KB
/
fuel.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package entity
import (
"strconv"
"strings"
"time"
"github.com/music-gang/music-gang-api/app/apperr"
)
// Fuel is a virtual unit of measure for the power consuption of the MusicGang VM.
// Like the real world, the fuel is limited, so the VM will stop if the fuel usage reaches the max capacity.
type Fuel uint64
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (f Fuel) MarshalBinary() (data []byte, err error) {
return strconv.AppendUint(nil, uint64(f), 10), nil
}
// Fuel*ActionCost rappresents the cost of an action.
// Greater is the execution time, greater is the cost.
const (
FuelInstantActionAmount = Fuel(50)
FuelQuickActionAmount = Fuel(200)
FuelFastestActionAmount = Fuel(400)
FuelFastActionAmount = Fuel(600)
FuelMidActionAmount = Fuel(800)
FuelSlowActionAmount = Fuel(1200)
FuelLongActionAmount = Fuel(2500)
FuelExtremeActionAmount = Fuel(5000)
FuelAbsoluteActionAmount = Fuel(10000)
)
// vFuel rappresents the virtual units of measure for the power consuption of the MusicGang VM.
const (
vFuel = Fuel(1) // virtual fuel unit for the fuel tank
vKFuel = Fuel(1024)
vMFuel = vKFuel << 10
vGFuel = vMFuel << 10
vTFuel = vGFuel << 10
)
// FuelRefillAmount retruns how much fuel is refilled at a time.
// It is equivalent to 5% of the capacity of the fuel tank.
// This is the default value that may be overwritten by the init function.
var FuelRefillAmount = Fuel(FuelTankCapacity * 5 / 100)
// FuelRefillRate returns the rate of fuel refill.
// This is the default value that may be overwritten by the init function.
var FuelRefillRate = 400 * time.Millisecond
// FuelTankCapacity is the maximum capacity of the fuel tank.
// This is the default value that may be overwritten by the init function.
var FuelTankCapacity = 100 * vKFuel
// MaxExecutionTime returns the maximum execution time of an action.
// This is the default value that may be overwritten by the init function.
var MaxExecutionTime = 10 * time.Second
var (
// fuelAmountTable is a grid of fuel costs based on the execution time.
// It can be read as:
// from [0 - 100]ms: FuelInstantActionAmount
// from (100 - 200]ms: FuelQuickActionAmount
// from (200 - 300]ms: FuelFastestActionAmount
// from (300 - 500]ms: FuelFastActionAmount
// from (500 - 1000]ms: FuelMidActionAmount
// from (1000 - 2000]ms: FuelSlowActionAmount
// from (2000 - 3000]ms: FuelLongActionAmount
// from (3000 - 5000]ms: FuelExtremeActionAmount
// over 5000ms: FuelAbsoluteActionAmount
fuelAmountTable = map[time.Duration]Fuel{
time.Millisecond * 100: FuelInstantActionAmount,
time.Millisecond * 200: FuelQuickActionAmount,
time.Millisecond * 300: FuelFastestActionAmount,
time.Millisecond * 500: FuelFastActionAmount,
time.Millisecond * 1000: FuelMidActionAmount,
time.Millisecond * 2000: FuelSlowActionAmount,
time.Millisecond * 3000: FuelLongActionAmount,
time.Millisecond * 5000: FuelExtremeActionAmount,
}
)
// FuelAmount returns the cost of an action based only on the execution time.
func FuelAmount(execution time.Duration) Fuel {
for t, fuel := range fuelAmountTable {
if execution <= t {
return fuel
}
}
return FuelAbsoluteActionAmount
}
func FuelFromCustomFuel(customFuel Fuel) Fuel {
for _, f := range fuelAmountTable {
if customFuel <= f {
return f
}
}
return FuelAbsoluteActionAmount
}
// MaxExecutionTime returns the maximum execution time of the contract.
// MaxExecutionTime is based on max fuel compared with fuelAmountTable.
func MaxExecutionTimeFromFuel(fuel Fuel) time.Duration {
for t, f := range fuelAmountTable {
if fuel <= f {
return t
}
}
return MaxExecutionTime
}
// ParseFuel accepts a string and returns a Fuel unit measurement, like the vFuel, vKFuel, vMFuel, vGFuel, vTFuel.
// for an example, 10 vKFuel is equal to 10 * 1024 = 10240.
func ParseFuel(s string) (Fuel, error) {
var fuel Fuel
arrF := strings.Split(s, " ")
if len(arrF) != 2 {
return 0, apperr.Errorf(apperr.EINVALID, "invalid config fuel format: %s", s)
}
f, err := strconv.ParseUint(arrF[0], 10, 64)
if err != nil {
return 0, apperr.Errorf(apperr.EINVALID, "Cannot parse fuel amount: %s", s)
}
fuel = Fuel(f)
switch arrF[1] {
case "vFuel":
break
case "vKFuel":
fuel *= vKFuel
case "vMFuel":
fuel *= vMFuel
case "vGFuel":
fuel *= vGFuel
case "vTFuel":
fuel *= vTFuel
default:
return 0, apperr.Errorf(apperr.EINVALID, "invalid config fuel format: %s", s)
}
return Fuel(fuel), nil
}
// FuelStats represents the statistics of the fuel tank.
type FuelStat struct {
FuelCapacity Fuel `json:"fuel_capacity"`
FuelUsed Fuel `json:"fuel_used"`
LastRefuelAmout Fuel `json:"last_refuel_amount"`
LastRefuelAt time.Time `json:"last_refuel_at"`
}