github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/whisper/whisperv6/envelope.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 // 10 // 11 // 12 // 13 // 14 // 15 // 16 // 17 // 18 // 19 // 20 // 21 // 22 // 23 // 24 25 // 26 27 package whisperv6 28 29 import ( 30 "crypto/ecdsa" 31 "encoding/binary" 32 "fmt" 33 gmath "math" 34 "math/big" 35 "time" 36 37 "github.com/ethereum/go-ethereum/common" 38 "github.com/ethereum/go-ethereum/common/math" 39 "github.com/ethereum/go-ethereum/crypto" 40 "github.com/ethereum/go-ethereum/crypto/ecies" 41 "github.com/ethereum/go-ethereum/rlp" 42 ) 43 44 // 45 // 46 type Envelope struct { 47 Expiry uint32 48 TTL uint32 49 Topic TopicType 50 Data []byte 51 Nonce uint64 52 53 pow float64 // 54 55 // 56 hash common.Hash // 57 bloom []byte 58 } 59 60 // 61 func (e *Envelope) size() int { 62 return EnvelopeHeaderLength + len(e.Data) 63 } 64 65 // 66 func (e *Envelope) rlpWithoutNonce() []byte { 67 res, _ := rlp.EncodeToBytes([]interface{}{e.Expiry, e.TTL, e.Topic, e.Data}) 68 return res 69 } 70 71 // 72 // 73 func NewEnvelope(ttl uint32, topic TopicType, msg *sentMessage) *Envelope { 74 env := Envelope{ 75 Expiry: uint32(time.Now().Add(time.Second * time.Duration(ttl)).Unix()), 76 TTL: ttl, 77 Topic: topic, 78 Data: msg.Raw, 79 Nonce: 0, 80 } 81 82 return &env 83 } 84 85 // 86 // 87 func (e *Envelope) Seal(options *MessageParams) error { 88 if options.PoW == 0 { 89 // 90 return nil 91 } 92 93 var target, bestBit int 94 if options.PoW < 0 { 95 // 96 // 97 // 98 e.Expiry += options.WorkTime 99 } else { 100 target = e.powToFirstBit(options.PoW) 101 } 102 103 buf := make([]byte, 64) 104 h := crypto.Keccak256(e.rlpWithoutNonce()) 105 copy(buf[:32], h) 106 107 finish := time.Now().Add(time.Duration(options.WorkTime) * time.Second).UnixNano() 108 for nonce := uint64(0); time.Now().UnixNano() < finish; { 109 for i := 0; i < 1024; i++ { 110 binary.BigEndian.PutUint64(buf[56:], nonce) 111 d := new(big.Int).SetBytes(crypto.Keccak256(buf)) 112 firstBit := math.FirstBitSet(d) 113 if firstBit > bestBit { 114 e.Nonce, bestBit = nonce, firstBit 115 if target > 0 && bestBit >= target { 116 return nil 117 } 118 } 119 nonce++ 120 } 121 } 122 123 if target > 0 && bestBit < target { 124 return fmt.Errorf("failed to reach the PoW target, specified pow time (%d seconds) was insufficient", options.WorkTime) 125 } 126 127 return nil 128 } 129 130 // 131 // 132 func (e *Envelope) PoW() float64 { 133 if e.pow == 0 { 134 e.calculatePoW(0) 135 } 136 return e.pow 137 } 138 139 func (e *Envelope) calculatePoW(diff uint32) { 140 buf := make([]byte, 64) 141 h := crypto.Keccak256(e.rlpWithoutNonce()) 142 copy(buf[:32], h) 143 binary.BigEndian.PutUint64(buf[56:], e.Nonce) 144 d := new(big.Int).SetBytes(crypto.Keccak256(buf)) 145 firstBit := math.FirstBitSet(d) 146 x := gmath.Pow(2, float64(firstBit)) 147 x /= float64(e.size()) 148 x /= float64(e.TTL + diff) 149 e.pow = x 150 } 151 152 func (e *Envelope) powToFirstBit(pow float64) int { 153 x := pow 154 x *= float64(e.size()) 155 x *= float64(e.TTL) 156 bits := gmath.Log2(x) 157 bits = gmath.Ceil(bits) 158 res := int(bits) 159 if res < 1 { 160 res = 1 161 } 162 return res 163 } 164 165 // 166 func (e *Envelope) Hash() common.Hash { 167 if (e.hash == common.Hash{}) { 168 encoded, _ := rlp.EncodeToBytes(e) 169 e.hash = crypto.Keccak256Hash(encoded) 170 } 171 return e.hash 172 } 173 174 // 175 func (e *Envelope) DecodeRLP(s *rlp.Stream) error { 176 raw, err := s.Raw() 177 if err != nil { 178 return err 179 } 180 // 181 // 182 // 183 // 184 // 185 type rlpenv Envelope 186 if err := rlp.DecodeBytes(raw, (*rlpenv)(e)); err != nil { 187 return err 188 } 189 e.hash = crypto.Keccak256Hash(raw) 190 return nil 191 } 192 193 // 194 func (e *Envelope) OpenAsymmetric(key *ecdsa.PrivateKey) (*ReceivedMessage, error) { 195 message := &ReceivedMessage{Raw: e.Data} 196 err := message.decryptAsymmetric(key) 197 switch err { 198 case nil: 199 return message, nil 200 case ecies.ErrInvalidPublicKey: // 201 return nil, err 202 default: 203 return nil, fmt.Errorf("unable to open envelope, decrypt failed: %v", err) 204 } 205 } 206 207 // 208 func (e *Envelope) OpenSymmetric(key []byte) (msg *ReceivedMessage, err error) { 209 msg = &ReceivedMessage{Raw: e.Data} 210 err = msg.decryptSymmetric(key) 211 if err != nil { 212 msg = nil 213 } 214 return msg, err 215 } 216 217 // 218 func (e *Envelope) Open(watcher *Filter) (msg *ReceivedMessage) { 219 if watcher == nil { 220 return nil 221 } 222 223 // 224 if watcher.expectsAsymmetricEncryption() && watcher.expectsSymmetricEncryption() { 225 return nil 226 } 227 228 if watcher.expectsAsymmetricEncryption() { 229 msg, _ = e.OpenAsymmetric(watcher.KeyAsym) 230 if msg != nil { 231 msg.Dst = &watcher.KeyAsym.PublicKey 232 } 233 } else if watcher.expectsSymmetricEncryption() { 234 msg, _ = e.OpenSymmetric(watcher.KeySym) 235 if msg != nil { 236 msg.SymKeyHash = crypto.Keccak256Hash(watcher.KeySym) 237 } 238 } 239 240 if msg != nil { 241 ok := msg.ValidateAndParse() 242 if !ok { 243 return nil 244 } 245 msg.Topic = e.Topic 246 msg.PoW = e.PoW() 247 msg.TTL = e.TTL 248 msg.Sent = e.Expiry - e.TTL 249 msg.EnvelopeHash = e.Hash() 250 } 251 return msg 252 } 253 254 // 255 func (e *Envelope) Bloom() []byte { 256 if e.bloom == nil { 257 e.bloom = TopicToBloom(e.Topic) 258 } 259 return e.bloom 260 } 261 262 // 263 func TopicToBloom(topic TopicType) []byte { 264 b := make([]byte, BloomFilterSize) 265 var index [3]int 266 for j := 0; j < 3; j++ { 267 index[j] = int(topic[j]) 268 if (topic[3] & (1 << uint(j))) != 0 { 269 index[j] += 256 270 } 271 } 272 273 for j := 0; j < 3; j++ { 274 byteIndex := index[j] / 8 275 bitIndex := index[j] % 8 276 b[byteIndex] = (1 << uint(bitIndex)) 277 } 278 return b 279 } 280 281 // 282 // 283 func (w *Whisper) GetEnvelope(hash common.Hash) *Envelope { 284 w.poolMu.RLock() 285 defer w.poolMu.RUnlock() 286 return w.envelopes[hash] 287 }