-
Notifications
You must be signed in to change notification settings - Fork 286
/
treasury.go
66 lines (56 loc) · 2.76 KB
/
treasury.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
// Copyright (c) 2020 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package standalone
import "fmt"
// CalcTSpendExpiry returns the only valid value relative to the next block
// height where the transaction will expire. Two blocks are added in the end
// because transaction expiry is inclusive (>=) relative to block height.
func CalcTSpendExpiry(nextBlockHeight int64, tvi, multiplier uint64) uint32 {
nbh := uint64(nextBlockHeight)
nextTVI := nbh + (tvi - (nbh % tvi)) // Round up to next TVI
maxTVI := nextTVI + tvi*multiplier // Max TVI allowed.
return uint32(maxTVI + 2) // + 2 to deal with Expiry handling in mempool.
}
// IsTreasuryVoteInterval returns true if the passed height is on a treasury
// vote interval (TVI) and is not 0.
func IsTreasuryVoteInterval(height, tvi uint64) bool {
return height%tvi == 0 && height != 0
}
// CalcTSpendWindow calculates the start and end of a treasury voting window
// based on the parameters that are passed. An error will be returned if the
// provided expiry is not two more than a treasury vote interval (TVI) or before
// a single voting window is possible.
func CalcTSpendWindow(expiry uint32, tvi, multiplier uint64) (uint32, uint32, error) {
// Ensure the provided expiry is at least higher than a single voting
// window.
minReqExpiry := tvi*multiplier + 2
if uint64(expiry) < minReqExpiry {
str := fmt.Sprintf("expiry %d must be at least %d for the voting "+
"window defined by a TVI of %d with a multiplier of %d", expiry,
minReqExpiry, tvi, multiplier)
return 0, 0, ruleError(ErrInvalidTSpendExpiry, str)
}
// Ensure the provided expiry is two more than a TVI.
if !IsTreasuryVoteInterval(uint64(expiry-2), tvi) {
str := fmt.Sprintf("expiry %d must be two more than a multiple of the "+
"treasury vote interval %d", expiry, tvi)
return 0, 0, ruleError(ErrInvalidTSpendExpiry, str)
}
return expiry - uint32(tvi*multiplier) - 2, expiry - 2, nil
}
// InsideTSpendWindow returns true if the provided block height is inside the
// treasury vote window of the provided expiry. This function should only be
// called with an expiry that is on a TVI. Proper care must be taken to call
// this function with the correct block height. It is incumbent on the caller
// to determine if the block height is for the previous, current, or next block.
//
// Note: The end is INCLUSIVE in order to determine if a treasury spend is
// allowed in a block despite the fact that the voting window is EXCLUSIVE.
func InsideTSpendWindow(blockHeight int64, expiry uint32, tvi, multiplier uint64) bool {
start, end, err := CalcTSpendWindow(expiry, tvi, multiplier)
if err != nil {
return false
}
return uint32(blockHeight) >= start && uint32(blockHeight) <= end
}