decred.org/dcrwallet/v3@v3.1.0/wallet/udb/treasury.go (about) 1 // Copyright (c) 2020-2021 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package udb 6 7 import ( 8 "decred.org/dcrwallet/v3/errors" 9 "decred.org/dcrwallet/v3/wallet/walletdb" 10 "github.com/decred/dcrd/blockchain/stake/v5" 11 "github.com/decred/dcrd/chaincfg/chainhash" 12 ) 13 14 var ( 15 tspendPolicyBucketKey = []byte("tspendpolicy") // by tspend hash 16 treasuryPolicyBucketKey = []byte("treasurypolicy") // by treasury key 17 18 vspTspendPolicyBucketKey = []byte("vsptspendpolicy") // by ticket | tspend hash 19 vspTreasuryPolicyBucketKey = []byte("vsptreasurypolicy") // by ticket | treasury key 20 ) 21 22 type VSPTSpend struct { 23 Ticket, TSpend chainhash.Hash 24 } 25 26 type VSPTreasuryKey struct { 27 Ticket chainhash.Hash 28 TreasuryKey string 29 } 30 31 // SetTSpendPolicy sets a tspend vote policy for a specific tspend transaction 32 // hash. 33 func SetTSpendPolicy(dbtx walletdb.ReadWriteTx, hash *chainhash.Hash, 34 policy stake.TreasuryVoteT) error { 35 36 b := dbtx.ReadWriteBucket(tspendPolicyBucketKey) 37 if policy == stake.TreasuryVoteInvalid { 38 err := b.Delete(hash[:]) 39 if err != nil { 40 return errors.E(errors.IO, err) 41 } 42 return nil 43 } 44 return b.Put(hash[:], []byte{byte(policy)}) 45 } 46 47 // SetVSPTSpendPolicy sets a tspend vote policy for a specific tspend 48 // transaction hash for a VSP customer's ticket hash. 49 func SetVSPTSpendPolicy(dbtx walletdb.ReadWriteTx, ticketHash, tspendHash *chainhash.Hash, 50 policy stake.TreasuryVoteT) error { 51 52 k := make([]byte, 64) 53 copy(k, ticketHash[:]) 54 copy(k[32:], tspendHash[:]) 55 56 b := dbtx.ReadWriteBucket(vspTspendPolicyBucketKey) 57 if policy == stake.TreasuryVoteInvalid { 58 err := b.Delete(k) 59 if err != nil { 60 return errors.E(errors.IO, err) 61 } 62 return nil 63 } 64 return b.Put(k, []byte{byte(policy)}) 65 } 66 67 // TSpendPolicy returns the tspend vote policy for a specific tspend transaction 68 // hash. 69 func TSpendPolicy(dbtx walletdb.ReadTx, hash *chainhash.Hash) (stake.TreasuryVoteT, error) { 70 b := dbtx.ReadBucket(tspendPolicyBucketKey) 71 v := b.Get(hash[:]) 72 if v == nil { 73 return stake.TreasuryVoteInvalid, nil 74 } 75 if len(v) != 1 { 76 err := errors.Errorf("invalid length %v for tspend "+ 77 "vote policy", len(v)) 78 return 0, errors.E(errors.IO, err) 79 } 80 return stake.TreasuryVoteT(v[0]), nil 81 } 82 83 // VSPTSpendPolicy returns the tspend vote policy for a specific tspend 84 // transaction hash for a VSP customer's ticket hash. 85 func VSPTSpendPolicy(dbtx walletdb.ReadTx, ticketHash, 86 tspendHash *chainhash.Hash) (stake.TreasuryVoteT, error) { 87 88 key := make([]byte, 64) 89 copy(key, ticketHash[:]) 90 copy(key[32:], tspendHash[:]) 91 92 b := dbtx.ReadBucket(vspTspendPolicyBucketKey) 93 v := b.Get(key) 94 if v == nil { 95 return stake.TreasuryVoteInvalid, nil 96 } 97 if len(v) != 1 { 98 err := errors.Errorf("invalid length %v for tspend "+ 99 "vote policy", len(v)) 100 return 0, errors.E(errors.IO, err) 101 } 102 return stake.TreasuryVoteT(v[0]), nil 103 } 104 105 // TSpendPolicies returns all tspend vote policies keyed by a tspend hash. 106 // Abstaining policies are excluded. 107 func TSpendPolicies(dbtx walletdb.ReadTx) (map[chainhash.Hash]stake.TreasuryVoteT, error) { 108 b := dbtx.ReadBucket(tspendPolicyBucketKey) 109 policies := make(map[chainhash.Hash]stake.TreasuryVoteT) 110 err := b.ForEach(func(hash, _ []byte) error { 111 var tspendHash chainhash.Hash 112 copy(tspendHash[:], hash) 113 policy, err := TSpendPolicy(dbtx, &tspendHash) 114 if err != nil { 115 return err 116 } 117 if policy == stake.TreasuryVoteInvalid { 118 return nil 119 } 120 policies[tspendHash] = policy 121 return nil 122 }) 123 return policies, err 124 } 125 126 // VSPTSpendPolicies returns all tspend vote policies keyed by a tspend hash and 127 // a VSP customer's ticket hash. Abstaining policies are excluded. 128 func VSPTSpendPolicies(dbtx walletdb.ReadTx) (map[VSPTSpend]stake.TreasuryVoteT, error) { 129 b := dbtx.ReadBucket(vspTspendPolicyBucketKey) 130 policies := make(map[VSPTSpend]stake.TreasuryVoteT) 131 err := b.ForEach(func(k, _ []byte) error { 132 var key VSPTSpend 133 copy(key.Ticket[:], k) 134 copy(key.TSpend[:], k[32:]) 135 136 policy, err := VSPTSpendPolicy(dbtx, &key.Ticket, &key.TSpend) 137 if err != nil { 138 return err 139 } 140 if policy == stake.TreasuryVoteInvalid { 141 return nil 142 } 143 policies[key] = policy 144 return nil 145 }) 146 return policies, err 147 } 148 149 // SetTreasuryKeyPolicy sets a tspend vote policy for a specific Politeia 150 // instance key. 151 func SetTreasuryKeyPolicy(dbtx walletdb.ReadWriteTx, pikey []byte, 152 policy stake.TreasuryVoteT) error { 153 154 b := dbtx.ReadWriteBucket(treasuryPolicyBucketKey) 155 if policy == stake.TreasuryVoteInvalid { 156 err := b.Delete(pikey) 157 if err != nil { 158 return errors.E(errors.IO, err) 159 } 160 return nil 161 } 162 return b.Put(pikey, []byte{byte(policy)}) 163 } 164 165 // SetVSPTreasuryKeyPolicy sets a tspend vote policy for a specific Politeia 166 // instance key for a VSP customer's ticket. 167 func SetVSPTreasuryKeyPolicy(dbtx walletdb.ReadWriteTx, ticket *chainhash.Hash, 168 pikey []byte, policy stake.TreasuryVoteT) error { 169 170 k := make([]byte, 0, chainhash.HashSize+len(pikey)) 171 k = append(k, ticket[:]...) 172 k = append(k, pikey...) 173 174 b := dbtx.ReadWriteBucket(vspTreasuryPolicyBucketKey) 175 if policy == stake.TreasuryVoteInvalid { 176 err := b.Delete(k) 177 if err != nil { 178 return errors.E(errors.IO, err) 179 } 180 return nil 181 } 182 return b.Put(k, []byte{byte(policy)}) 183 } 184 185 // TreasuryKeyPolicy returns the tspend vote policy for a specific Politeia 186 // instance key. 187 func TreasuryKeyPolicy(dbtx walletdb.ReadTx, pikey []byte) (stake.TreasuryVoteT, error) { 188 b := dbtx.ReadBucket(treasuryPolicyBucketKey) 189 v := b.Get(pikey) 190 if v == nil { 191 return stake.TreasuryVoteInvalid, nil 192 } 193 if len(v) != 1 { 194 err := errors.Errorf("invalid length %v for treasury "+ 195 "key policy", len(v)) 196 return 0, errors.E(errors.IO, err) 197 } 198 return stake.TreasuryVoteT(v[0]), nil 199 } 200 201 // VSPTreasuryKeyPolicy returns the tspend vote policy for a specific Politeia 202 // instance key for a VSP customer's ticket. 203 func VSPTreasuryKeyPolicy(dbtx walletdb.ReadTx, ticket *chainhash.Hash, 204 pikey []byte) (stake.TreasuryVoteT, error) { 205 206 k := make([]byte, 0, chainhash.HashSize+len(pikey)) 207 k = append(k, ticket[:]...) 208 k = append(k, pikey...) 209 210 b := dbtx.ReadBucket(vspTreasuryPolicyBucketKey) 211 v := b.Get(k) 212 if v == nil { 213 return stake.TreasuryVoteInvalid, nil 214 } 215 if len(v) != 1 { 216 err := errors.Errorf("invalid length %v for treasury "+ 217 "key policy", len(v)) 218 return 0, errors.E(errors.IO, err) 219 } 220 return stake.TreasuryVoteT(v[0]), nil 221 } 222 223 // TreasuryKeyPolicies returns all tspend vote policies keyed by a Politeia 224 // instance key. Abstaining policies are excluded. 225 func TreasuryKeyPolicies(dbtx walletdb.ReadTx) (map[string]stake.TreasuryVoteT, error) { 226 b := dbtx.ReadBucket(treasuryPolicyBucketKey) 227 policies := make(map[string]stake.TreasuryVoteT) 228 err := b.ForEach(func(pikey, _ []byte) error { 229 policy, err := TreasuryKeyPolicy(dbtx, pikey) 230 if err != nil { 231 return err 232 } 233 if policy == stake.TreasuryVoteInvalid { 234 return nil 235 } 236 policies[string(pikey)] = policy 237 return nil 238 }) 239 return policies, err 240 } 241 242 // VSPTreasuryKeyPolicies returns all tspend vote policies keyed by a Politeia 243 // instance key for a VSP customer's ticket. Abstaining policies are excluded. 244 func VSPTreasuryKeyPolicies(dbtx walletdb.ReadTx) (map[VSPTreasuryKey]stake.TreasuryVoteT, error) { 245 b := dbtx.ReadBucket(vspTreasuryPolicyBucketKey) 246 policies := make(map[VSPTreasuryKey]stake.TreasuryVoteT) 247 err := b.ForEach(func(k, _ []byte) error { 248 var key VSPTreasuryKey 249 pikey := k[chainhash.HashSize:] 250 copy(key.Ticket[:], k) 251 key.TreasuryKey = string(pikey) 252 253 policy, err := VSPTreasuryKeyPolicy(dbtx, &key.Ticket, pikey) 254 if err != nil { 255 return err 256 } 257 if policy == stake.TreasuryVoteInvalid { 258 return nil 259 } 260 policies[key] = policy 261 return nil 262 }) 263 return policies, err 264 }