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  }