code.vegaprotocol.io/vega@v0.79.0/core/pow/snapshot.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package pow 17 18 import ( 19 "context" 20 "sort" 21 22 "code.vegaprotocol.io/vega/core/types" 23 snapshot "code.vegaprotocol.io/vega/protos/vega/snapshot/v1" 24 25 "github.com/golang/protobuf/proto" 26 ) 27 28 func (e *Engine) Namespace() types.SnapshotNamespace { 29 return types.PoWSnapshot 30 } 31 32 func (e *Engine) Keys() []string { 33 return e.hashKeys 34 } 35 36 func (e *Engine) Stopped() bool { 37 return false 38 } 39 40 // get the serialised form and hash of the given key. 41 func (e *Engine) serialise() ([]byte, error) { 42 nonceHeights := map[uint64][]*snapshot.NonceRef{} 43 44 for k, v := range e.heightToNonceRef { 45 refs := make([]*snapshot.NonceRef, 0, len(v)) 46 for _, ref := range v { 47 refs = append(refs, &snapshot.NonceRef{Party: ref.party, Nonce: ref.nonce}) 48 } 49 nonceHeights[k] = refs 50 } 51 52 payloadProofOfWork := &types.PayloadProofOfWork{ 53 BlockHeight: e.blockHeight[:ringSize], 54 BlockHash: e.blockHash[:ringSize], 55 HeightToTx: e.heightToTx, 56 HeightToTid: e.heightToTid, 57 HeightToNonceRef: nonceHeights, 58 ActiveParams: e.paramsToSnapshotParams(), 59 ActiveStates: e.statesToSnapshotStates(), 60 LastPruningBlock: e.lastPruningBlock, 61 } 62 payload := types.Payload{ 63 Data: payloadProofOfWork, 64 } 65 66 data, err := proto.Marshal(payload.IntoProto()) 67 if err != nil { 68 return nil, err 69 } 70 71 return data, nil 72 } 73 74 func (e *Engine) GetState(k string) ([]byte, []types.StateProvider, error) { 75 state, err := e.serialise() 76 return state, nil, err 77 } 78 79 func (e *Engine) paramsToSnapshotParams() []*snapshot.ProofOfWorkParams { 80 params := make([]*snapshot.ProofOfWorkParams, 0, len(e.activeParams)) 81 for _, p := range e.activeParams { 82 until := int64(-1) 83 if p.untilBlock != nil { 84 until = int64(*p.untilBlock) 85 } 86 params = append(params, &snapshot.ProofOfWorkParams{ 87 SpamPowNumberOfPastBlocks: p.spamPoWNumberOfPastBlocks, 88 SpamPowDifficulty: uint32(p.spamPoWDifficulty), 89 SpamPowHashFunction: p.spamPoWHashFunction, 90 SpamPowNumberOfTxPerBlock: p.spamPoWNumberOfTxPerBlock, 91 SpamPowIncreasingDifficulty: p.spamPoWIncreasingDifficulty, 92 FromBlock: p.fromBlock, 93 UntilBlock: until, 94 }) 95 } 96 return params 97 } 98 99 func (e *Engine) blocksState(state map[uint64]map[string]*partyStateForBlock) []*snapshot.ProofOfWorkBlockState { 100 states := make([]*snapshot.ProofOfWorkBlockState, 0, len(state)) 101 for k, v := range state { 102 partyStates := make([]*snapshot.ProofOfWorkPartyStateForBlock, 0, len(v)) 103 for party, psfb := range v { 104 partyStates = append(partyStates, &snapshot.ProofOfWorkPartyStateForBlock{ 105 Party: party, 106 ObservedDifficulty: uint64(psfb.observedDifficulty), 107 SeenCount: uint64(psfb.seenCount), 108 }) 109 } 110 sort.Slice(partyStates, func(i, j int) bool { return partyStates[i].Party < partyStates[j].Party }) 111 112 states = append(states, &snapshot.ProofOfWorkBlockState{ 113 BlockHeight: k, 114 PartyState: partyStates, 115 }) 116 } 117 sort.Slice(states, func(i, j int) bool { return states[i].BlockHeight < states[j].BlockHeight }) 118 return states 119 } 120 121 func (e *Engine) statesToSnapshotStates() []*snapshot.ProofOfWorkState { 122 states := make([]*snapshot.ProofOfWorkState, 0, len(e.activeStates)) 123 for _, s := range e.activeStates { 124 states = append(states, &snapshot.ProofOfWorkState{ 125 PowState: e.blocksState(s.blockToPartyState), 126 }) 127 } 128 return states 129 } 130 131 func (e *Engine) snapshotParamsToParams(activeParams []*snapshot.ProofOfWorkParams) []*params { 132 pars := make([]*params, 0, len(activeParams)) 133 for _, p := range activeParams { 134 param := ¶ms{ 135 spamPoWNumberOfPastBlocks: p.SpamPowNumberOfPastBlocks, 136 spamPoWDifficulty: uint(p.SpamPowDifficulty), 137 spamPoWHashFunction: p.SpamPowHashFunction, 138 spamPoWNumberOfTxPerBlock: p.SpamPowNumberOfTxPerBlock, 139 spamPoWIncreasingDifficulty: p.SpamPowIncreasingDifficulty, 140 fromBlock: p.FromBlock, 141 untilBlock: nil, 142 } 143 if p.UntilBlock >= 0 { 144 param.untilBlock = new(uint64) 145 *param.untilBlock = uint64(p.UntilBlock) 146 } 147 pars = append(pars, param) 148 } 149 return pars 150 } 151 152 func (e *Engine) snapshotStatesToStates(activeStates []*snapshot.ProofOfWorkState) []*state { 153 states := make([]*state, 0, len(activeStates)) 154 for _, s := range activeStates { 155 currentState := &state{} 156 currentState.blockToPartyState = make(map[uint64]map[string]*partyStateForBlock, len(s.PowState)) 157 for _, powbs := range s.PowState { 158 currentState.blockToPartyState[powbs.BlockHeight] = make(map[string]*partyStateForBlock, len(powbs.PartyState)) 159 for _, partyState := range powbs.PartyState { 160 currentState.blockToPartyState[powbs.BlockHeight][partyState.Party] = &partyStateForBlock{ 161 observedDifficulty: uint(partyState.ObservedDifficulty), 162 seenCount: uint(partyState.SeenCount), 163 } 164 } 165 } 166 states = append(states, currentState) 167 } 168 return states 169 } 170 171 func (e *Engine) LoadState(ctx context.Context, p *types.Payload) ([]types.StateProvider, error) { 172 if e.Namespace() != p.Data.Namespace() { 173 return nil, types.ErrInvalidSnapshotNamespace 174 } 175 pl := p.Data.(*types.PayloadProofOfWork) 176 copy(e.blockHash[:], pl.BlockHash[:ringSize]) 177 copy(e.blockHeight[:], pl.BlockHeight[:ringSize]) 178 e.heightToTx = pl.HeightToTx 179 e.heightToTid = pl.HeightToTid 180 181 for k, v := range pl.HeightToNonceRef { 182 refs := make([]nonceRef, 0, len(v)) 183 for _, ref := range v { 184 refs = append(refs, nonceRef{ref.Party, ref.Nonce}) 185 } 186 e.heightToNonceRef[k] = refs 187 } 188 189 e.seenTx = map[string]struct{}{} 190 e.seenTid = map[string]struct{}{} 191 for _, block := range e.heightToTid { 192 for _, v := range block { 193 e.seenTid[v] = struct{}{} 194 } 195 } 196 for _, block := range e.heightToTx { 197 for _, v := range block { 198 e.seenTx[v] = struct{}{} 199 } 200 } 201 for _, block := range e.heightToNonceRef { 202 for _, v := range block { 203 e.seenNonceRef[v] = struct{}{} 204 } 205 } 206 e.activeParams = e.snapshotParamsToParams(pl.ActiveParams) 207 e.activeStates = e.snapshotStatesToStates(pl.ActiveStates) 208 e.lastPruningBlock = pl.LastPruningBlock 209 return nil, nil 210 }