github.com/FUSIONFoundation/efsn@v3.6.2-0.20200916075423-dbb5dd5d2cc7+incompatible/consensus/datong/snapshot.go (about) 1 package datong 2 3 import ( 4 "errors" 5 6 "github.com/FusionFoundation/efsn/common" 7 "github.com/FusionFoundation/efsn/core/types" 8 "github.com/FusionFoundation/efsn/crypto" 9 ) 10 11 // Snapshot wacom 12 type Snapshot struct { 13 Selected common.Hash `json:"selected"` 14 Retreat []common.Hash `json:"retreat"` 15 TicketNumber int `json:"ticketNumber"` 16 } 17 18 type ticketLogType byte 19 20 const ( 21 ticketSelect ticketLogType = iota + 1 22 ticketRetreat 23 ) 24 25 type ticketLog struct { 26 TicketID common.Hash 27 Type ticketLogType 28 } 29 30 type snapshot struct { 31 logs []*ticketLog 32 ticketNumber int 33 } 34 35 func newSnapshot() *snapshot { 36 return &snapshot{ 37 logs: make([]*ticketLog, 0), 38 } 39 40 } 41 42 func newSnapshotWithData(data []byte) (*snapshot, error) { 43 snap := newSnapshot() 44 if err := snap.SetBytes(data); err != nil { 45 return nil, err 46 } 47 return snap, nil 48 } 49 50 // NewSnapshotFromHeader wacom 51 func NewSnapshotFromHeader(header *types.Header) (*Snapshot, error) { 52 snap, err := newSnapshotWithData(getSnapDataByHeader(header)) 53 if err != nil { 54 return nil, err 55 } 56 return snap.ToShow(), nil 57 } 58 59 func (snap *snapshot) GetVoteTicket() common.Hash { 60 if len(snap.logs) > 0 && snap.logs[0].Type == ticketSelect { 61 return snap.logs[0].TicketID 62 } 63 return common.Hash{} 64 } 65 66 func (snap *snapshot) AddLog(log *ticketLog) { 67 snap.logs = append(snap.logs, log) 68 } 69 70 func (snap *snapshot) SetBytes(data []byte) error { 71 if len(data) <= 0 { 72 return errors.New("Empty data") 73 } 74 75 realData := data[:len(data)-1] 76 check := data[len(data)-1] 77 78 if calcCheck(realData) != check { 79 return errors.New("check error") 80 } 81 82 snap.ticketNumber = common.BytesToInt(realData[:4]) 83 84 realData = realData[4:] 85 dataLength := len(realData) 86 logLength := common.HashLength + 1 87 88 if dataLength%logLength != 0 { 89 return errors.New("data length error") 90 } 91 92 count := dataLength / logLength 93 snap.logs = make([]*ticketLog, count) 94 for i := 0; i < count; i++ { 95 base := logLength * i 96 snap.logs[i] = &ticketLog{ 97 TicketID: common.BytesToHash(realData[base : logLength+base-1]), 98 Type: ticketLogType(realData[logLength+base-1]), 99 } 100 } 101 102 return nil 103 } 104 105 func (snap *snapshot) Bytes() []byte { 106 data := make([]byte, 0) 107 108 data = append(data, common.IntToBytes(snap.ticketNumber)...) 109 110 for i := 0; i < len(snap.logs); i++ { 111 data = append(data, snap.logs[i].TicketID[:]...) 112 data = append(data, byte(snap.logs[i].Type)) 113 } 114 115 data = append(data, calcCheck(data)) 116 return data 117 } 118 119 func (snap *snapshot) TicketNumber() int { 120 return snap.ticketNumber 121 } 122 123 func (snap *snapshot) SetTicketNumber(ticketNumber int) { 124 snap.ticketNumber = ticketNumber 125 } 126 127 func (snap *snapshot) ToShow() *Snapshot { 128 var retreat []common.Hash 129 if len(snap.logs) == 0 { 130 retreat = make([]common.Hash, 0, 0) 131 } else { 132 retreat = make([]common.Hash, 0, len(snap.logs)-1) 133 for i := 1; i < len(snap.logs); i++ { 134 if snap.logs[i].Type == ticketRetreat { 135 retreat = append(retreat, snap.logs[i].TicketID) 136 } 137 } 138 } 139 return &Snapshot{ 140 Selected: snap.GetVoteTicket(), 141 Retreat: retreat, 142 TicketNumber: snap.ticketNumber, 143 } 144 } 145 146 func calcCheck(data []byte) byte { 147 hash := crypto.Keccak256Hash(data) 148 return hash[0] 149 } 150 151 func GenerateGenesisExtraData(old []byte, ticketNumber uint64) []byte { 152 snap := newSnapshot() 153 snap.SetTicketNumber(int(ticketNumber)) 154 snapBytes := snap.Bytes() 155 156 extraData := make([]byte, extraVanity) 157 copy(extraData[:], old) 158 159 extraData = append(extraData, snapBytes...) 160 161 if len(old) >= extraVanity+extraSeal { 162 extraData = append(extraData, old[len(old)-extraSeal:]...) 163 } else { 164 extraData = append(extraData, make([]byte, extraSeal)...) 165 } 166 return extraData 167 }