aboutsummaryrefslogblamecommitdiffstats
path: root/Godeps/_workspace/src/github.com/ethereum/ethash/ethash_test.go
blob: e6833e3434ccd51dcb182abeca6902c47b38b91c (plain) (tree)








































                                                                                                                  
                                                                                                                  






                                                                                                                  
                                                                                                                  






                                                                                                                  
                                                                                                                  



















                                                                                             
                                           
                           
                                                






















                                                                      




                               



                                                                   
                                              



                                             
                                          

                                      
                                                            
                                
                                                                  






                                                 
                      



                          


                                                    













                                                                          
                                                   
                                   
                                                        































                                                                                                                  
package ethash

import (
    "bytes"
    "crypto/rand"
    "encoding/hex"
    "log"
    "math/big"
    "os"
    "sync"
    "testing"

    "github.com/ethereum/go-ethereum/common"
)

func init() {
    // glog.SetV(6)
    // glog.SetToStderr(true)
}

type testBlock struct {
    difficulty  *big.Int
    hashNoNonce common.Hash
    nonce       uint64
    mixDigest   common.Hash
    number      uint64
}

func (b *testBlock) Difficulty() *big.Int     { return b.difficulty }
func (b *testBlock) HashNoNonce() common.Hash { return b.hashNoNonce }
func (b *testBlock) Nonce() uint64            { return b.nonce }
func (b *testBlock) MixDigest() common.Hash   { return b.mixDigest }
func (b *testBlock) NumberU64() uint64        { return b.number }

var validBlocks = []*testBlock{
    // from proof of concept nine testnet, epoch 0
    {
        number:      22,
        hashNoNonce: common.HexToHash("372eca2454ead349c3df0ab5d00b0b706b23e49d469387db91811cee0358fc6d"),
        difficulty:  big.NewInt(132416),
        nonce:       0x495732e0ed7a801c,
        mixDigest:   common.HexToHash("2f74cdeb198af0b9abe65d22d372e22fb2d474371774a9583c1cc427a07939f5"),
    },
    // from proof of concept nine testnet, epoch 1
    {
        number:      30001,
        hashNoNonce: common.HexToHash("7e44356ee3441623bc72a683fd3708fdf75e971bbe294f33e539eedad4b92b34"),
        difficulty:  big.NewInt(1532671),
        nonce:       0x318df1c8adef7e5e,
        mixDigest:   common.HexToHash("144b180aad09ae3c81fb07be92c8e6351b5646dda80e6844ae1b697e55ddde84"),
    },
    // from proof of concept nine testnet, epoch 2
    {
        number:      60000,
        hashNoNonce: common.HexToHash("5fc898f16035bf5ac9c6d9077ae1e3d5fc1ecc3c9fd5bee8bb00e810fdacbaa0"),
        difficulty:  big.NewInt(2467358),
        nonce:       0x50377003e5d830ca,
        mixDigest:   common.HexToHash("ab546a5b73c452ae86dadd36f0ed83a6745226717d3798832d1b20b489e82063"),
    },
}

func TestEthashVerifyValid(t *testing.T) {
    eth := New()
    for i, block := range validBlocks {
        if !eth.Verify(block) {
            t.Errorf("block %d (%x) did not validate.", i, block.hashNoNonce[:6])
        }
    }
}

func TestEthashConcurrentVerify(t *testing.T) {
    eth, err := NewForTesting()
    if err != nil {
        t.Fatal(err)
    }
    defer os.RemoveAll(eth.Full.Dir)

    block := &testBlock{difficulty: big.NewInt(10)}
    nonce, md := eth.Search(block, nil)
    block.nonce = nonce
    block.mixDigest = common.BytesToHash(md)

    // Verify the block concurrently to check for data races.
    var wg sync.WaitGroup
    wg.Add(100)
    for i := 0; i < 100; i++ {
        go func() {
            if !eth.Verify(block) {
                t.Error("Block could not be verified")
            }
            wg.Done()
        }()
    }
    wg.Wait()
}

func TestEthashConcurrentSearch(t *testing.T) {
    eth, err := NewForTesting()
    if err != nil {
        t.Fatal(err)
    }
    eth.Turbo(true)
    defer os.RemoveAll(eth.Full.Dir)

    type searchRes struct {
        n  uint64
        md []byte
    }

    var (
        block   = &testBlock{difficulty: big.NewInt(35000)}
        nsearch = 10
        wg      = new(sync.WaitGroup)
        found   = make(chan searchRes)
        stop    = make(chan struct{})
    )
    rand.Read(block.hashNoNonce[:])
    wg.Add(nsearch)
    // launch n searches concurrently.
    for i := 0; i < nsearch; i++ {
        go func() {
            nonce, md := eth.Search(block, stop)
            select {
            case found <- searchRes{n: nonce, md: md}:
            case <-stop:
            }
            wg.Done()
        }()
    }

    // wait for one of them to find the nonce
    res := <-found
    // stop the others
    close(stop)
    wg.Wait()

    block.nonce = res.n
    block.mixDigest = common.BytesToHash(res.md)
    if !eth.Verify(block) {
        t.Error("Block could not be verified")
    }
}

func TestEthashSearchAcrossEpoch(t *testing.T) {
    eth, err := NewForTesting()
    if err != nil {
        t.Fatal(err)
    }
    defer os.RemoveAll(eth.Full.Dir)

    for i := epochLength - 40; i < epochLength+40; i++ {
        block := &testBlock{number: i, difficulty: big.NewInt(90)}
        rand.Read(block.hashNoNonce[:])
        nonce, md := eth.Search(block, nil)
        block.nonce = nonce
        block.mixDigest = common.BytesToHash(md)
        if !eth.Verify(block) {
            t.Fatalf("Block could not be verified")
        }
    }
}

func TestGetSeedHash(t *testing.T) {
    seed0, err := GetSeedHash(0)
    if err != nil {
        t.Errorf("Failed to get seedHash for block 0: %v", err)
    }
    if bytes.Compare(seed0, make([]byte, 32)) != 0 {
        log.Printf("seedHash for block 0 should be 0s, was: %v\n", seed0)
    }
    seed1, err := GetSeedHash(30000)
    if err != nil {
        t.Error(err)
    }

    // From python:
    // > from pyethash import get_seedhash
    // > get_seedhash(30000)
    expectedSeed1, err := hex.DecodeString("290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563")
    if err != nil {
        t.Error(err)
    }

    if bytes.Compare(seed1, expectedSeed1) != 0 {
        log.Printf("seedHash for block 1 should be: %v,\nactual value: %v\n", expectedSeed1, seed1)
    }

}