github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/whisper/whisperv2/envelope.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Contains the Whisper protocol Envelope element. For formal details please see 18 // the specs at https://github.com/atheioschain/wiki/wiki/Whisper-PoC-1-Protocol-Spec#envelopes. 19 20 package whisperv2 21 22 import ( 23 "crypto/ecdsa" 24 "encoding/binary" 25 "fmt" 26 "time" 27 28 "github.com/atheioschain/go-atheios/common" 29 "github.com/atheioschain/go-atheios/crypto" 30 "github.com/atheioschain/go-atheios/crypto/ecies" 31 "github.com/atheioschain/go-atheios/rlp" 32 ) 33 34 // Envelope represents a clear-text data packet to transmit through the Whisper 35 // network. Its contents may or may not be encrypted and signed. 36 type Envelope struct { 37 Expiry uint32 // Whisper protocol specifies int32, really should be int64 38 TTL uint32 // ^^^^^^ 39 Topics []Topic 40 Data []byte 41 Nonce uint32 42 43 hash common.Hash // Cached hash of the envelope to avoid rehashing every time 44 } 45 46 // NewEnvelope wraps a Whisper message with expiration and destination data 47 // included into an envelope for network forwarding. 48 func NewEnvelope(ttl time.Duration, topics []Topic, msg *Message) *Envelope { 49 return &Envelope{ 50 Expiry: uint32(time.Now().Add(ttl).Unix()), 51 TTL: uint32(ttl.Seconds()), 52 Topics: topics, 53 Data: msg.bytes(), 54 Nonce: 0, 55 } 56 } 57 58 // Seal closes the envelope by spending the requested amount of time as a proof 59 // of work on hashing the data. 60 func (self *Envelope) Seal(pow time.Duration) { 61 d := make([]byte, 64) 62 copy(d[:32], self.rlpWithoutNonce()) 63 64 finish, bestBit := time.Now().Add(pow).UnixNano(), 0 65 for nonce := uint32(0); time.Now().UnixNano() < finish; { 66 for i := 0; i < 1024; i++ { 67 binary.BigEndian.PutUint32(d[60:], nonce) 68 69 firstBit := common.FirstBitSet(common.BigD(crypto.Keccak256(d))) 70 if firstBit > bestBit { 71 self.Nonce, bestBit = nonce, firstBit 72 } 73 nonce++ 74 } 75 } 76 } 77 78 // rlpWithoutNonce returns the RLP encoded envelope contents, except the nonce. 79 func (self *Envelope) rlpWithoutNonce() []byte { 80 enc, _ := rlp.EncodeToBytes([]interface{}{self.Expiry, self.TTL, self.Topics, self.Data}) 81 return enc 82 } 83 84 // Open extracts the message contained within a potentially encrypted envelope. 85 func (self *Envelope) Open(key *ecdsa.PrivateKey) (msg *Message, err error) { 86 // Split open the payload into a message construct 87 data := self.Data 88 89 message := &Message{ 90 Flags: data[0], 91 Sent: time.Unix(int64(self.Expiry-self.TTL), 0), 92 TTL: time.Duration(self.TTL) * time.Second, 93 Hash: self.Hash(), 94 } 95 data = data[1:] 96 97 if message.Flags&signatureFlag == signatureFlag { 98 if len(data) < signatureLength { 99 return nil, fmt.Errorf("unable to open envelope. First bit set but len(data) < len(signature)") 100 } 101 message.Signature, data = data[:signatureLength], data[signatureLength:] 102 } 103 message.Payload = data 104 105 // Decrypt the message, if requested 106 if key == nil { 107 return message, nil 108 } 109 err = message.decrypt(key) 110 switch err { 111 case nil: 112 return message, nil 113 114 case ecies.ErrInvalidPublicKey: // Payload isn't encrypted 115 return message, err 116 117 default: 118 return nil, fmt.Errorf("unable to open envelope, decrypt failed: %v", err) 119 } 120 } 121 122 // Hash returns the SHA3 hash of the envelope, calculating it if not yet done. 123 func (self *Envelope) Hash() common.Hash { 124 if (self.hash == common.Hash{}) { 125 enc, _ := rlp.EncodeToBytes(self) 126 self.hash = crypto.Keccak256Hash(enc) 127 } 128 return self.hash 129 } 130 131 // DecodeRLP decodes an Envelope from an RLP data stream. 132 func (self *Envelope) DecodeRLP(s *rlp.Stream) error { 133 raw, err := s.Raw() 134 if err != nil { 135 return err 136 } 137 // The decoding of Envelope uses the struct fields but also needs 138 // to compute the hash of the whole RLP-encoded envelope. This 139 // type has the same structure as Envelope but is not an 140 // rlp.Decoder so we can reuse the Envelope struct definition. 141 type rlpenv Envelope 142 if err := rlp.DecodeBytes(raw, (*rlpenv)(self)); err != nil { 143 return err 144 } 145 self.hash = crypto.Keccak256Hash(raw) 146 return nil 147 }