github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/whisper/whisperv6/envelope.go (about)

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