aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--whisper/whisperv6/envelope.go24
-rw-r--r--whisper/whisperv6/envelope_test.go27
2 files changed, 39 insertions, 12 deletions
diff --git a/whisper/whisperv6/envelope.go b/whisper/whisperv6/envelope.go
index c42d1fa8a..5d9d35081 100644
--- a/whisper/whisperv6/envelope.go
+++ b/whisper/whisperv6/envelope.go
@@ -27,7 +27,6 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/rlp"
@@ -82,7 +81,7 @@ func (e *Envelope) Seal(options *MessageParams) error {
return nil
}
- var target, bestBit int
+ var target, bestLeadingZeros int
if options.PoW < 0 {
// target is not set - the function should run for a period
// of time specified in WorkTime param. Since we can predict
@@ -101,10 +100,10 @@ func (e *Envelope) Seal(options *MessageParams) error {
for i := 0; i < 1024; i++ {
binary.BigEndian.PutUint64(buf[56:], nonce)
d := new(big.Int).SetBytes(crypto.Keccak256(buf))
- firstBit := math.FirstBitSet(d)
- if firstBit > bestBit {
- e.Nonce, bestBit = nonce, firstBit
- if target > 0 && bestBit >= target {
+ leadingZeros := 256 - d.BitLen()
+ if leadingZeros > bestLeadingZeros {
+ e.Nonce, bestLeadingZeros = nonce, leadingZeros
+ if target > 0 && bestLeadingZeros >= target {
return nil
}
}
@@ -112,7 +111,7 @@ func (e *Envelope) Seal(options *MessageParams) error {
}
}
- if target > 0 && bestBit < target {
+ if target > 0 && bestLeadingZeros < target {
return fmt.Errorf("failed to reach the PoW target, specified pow time (%d seconds) was insufficient", options.WorkTime)
}
@@ -130,13 +129,14 @@ func (e *Envelope) PoW() float64 {
func (e *Envelope) calculatePoW(diff uint32) {
buf := make([]byte, 64)
- h := crypto.Keccak256(e.rlpWithoutNonce())
+ rlp := e.rlpWithoutNonce()
+ h := crypto.Keccak256(rlp)
copy(buf[:32], h)
binary.BigEndian.PutUint64(buf[56:], e.Nonce)
- d := new(big.Int).SetBytes(crypto.Keccak256(buf))
- firstBit := math.FirstBitSet(d)
- x := gmath.Pow(2, float64(firstBit))
- x /= float64(e.size())
+ powHash := new(big.Int).SetBytes(crypto.Keccak256(buf))
+ leadingZeroes := 256 - powHash.BitLen()
+ x := gmath.Pow(2, float64(leadingZeroes))
+ x /= float64(len(rlp))
x /= float64(e.TTL + diff)
e.pow = x
}
diff --git a/whisper/whisperv6/envelope_test.go b/whisper/whisperv6/envelope_test.go
index 410b250a3..d6e38e683 100644
--- a/whisper/whisperv6/envelope_test.go
+++ b/whisper/whisperv6/envelope_test.go
@@ -25,6 +25,33 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)
+func TestPoWCalculationsWithNoLeadingZeros(t *testing.T) {
+ e := Envelope{
+ TTL: 1,
+ Data: []byte{0xde, 0xad, 0xbe, 0xef},
+ Nonce: 100000,
+ }
+
+ e.calculatePoW(0)
+
+ if e.pow != 0.07692307692307693 {
+ t.Fatalf("invalid PoW calculation. Expected 0.07692307692307693, got %v", e.pow)
+ }
+}
+
+func TestPoWCalculationsWith8LeadingZeros(t *testing.T) {
+ e := Envelope{
+ TTL: 1,
+ Data: []byte{0xde, 0xad, 0xbe, 0xef},
+ Nonce: 48159,
+ }
+ e.calculatePoW(0)
+
+ if e.pow != 40329.846153846156 {
+ t.Fatalf("invalid PoW calculation. Expected 0.07692307692307693, got %v", e.pow)
+ }
+}
+
func TestEnvelopeOpenAcceptsOnlyOneKeyTypeInFilter(t *testing.T) {
symKey := make([]byte, aesKeyLength)
mrand.Read(symKey)