github.com/nebulouslabs/sia@v1.3.7/modules/host/announce_test.go (about)

     1  package host
     2  
     3  import (
     4  	"bytes"
     5  	"testing"
     6  
     7  	"github.com/NebulousLabs/Sia/modules"
     8  	"github.com/NebulousLabs/Sia/types"
     9  )
    10  
    11  // announcementFinder is a quick module that parses the blockchain for host
    12  // announcements, keeping a record of all the announcements that get found.
    13  type announcementFinder struct {
    14  	cs modules.ConsensusSet
    15  
    16  	// Announcements that have been seen. The two slices are wedded.
    17  	netAddresses []modules.NetAddress
    18  	publicKeys   []types.SiaPublicKey
    19  }
    20  
    21  // ProcessConsensusChange receives consensus changes from the consensus set and
    22  // parses them for valid host announcements.
    23  func (af *announcementFinder) ProcessConsensusChange(cc modules.ConsensusChange) {
    24  	for _, block := range cc.AppliedBlocks {
    25  		for _, txn := range block.Transactions {
    26  			for _, arb := range txn.ArbitraryData {
    27  				addr, pubKey, err := modules.DecodeAnnouncement(arb)
    28  				if err == nil {
    29  					af.netAddresses = append(af.netAddresses, addr)
    30  					af.publicKeys = append(af.publicKeys, pubKey)
    31  				}
    32  			}
    33  		}
    34  	}
    35  }
    36  
    37  // Close will shut down the announcement finder.
    38  func (af *announcementFinder) Close() error {
    39  	af.cs.Unsubscribe(af)
    40  	return nil
    41  }
    42  
    43  // newAnnouncementFinder will create and return an announcement finder.
    44  func newAnnouncementFinder(cs modules.ConsensusSet) (*announcementFinder, error) {
    45  	af := &announcementFinder{
    46  		cs: cs,
    47  	}
    48  	err := cs.ConsensusSetSubscribe(af, modules.ConsensusChangeBeginning, nil)
    49  	if err != nil {
    50  		return nil, err
    51  	}
    52  	return af, nil
    53  }
    54  
    55  // TestHostAnnounce checks that the host announce function is operating
    56  // correctly.
    57  func TestHostAnnounce(t *testing.T) {
    58  	if testing.Short() {
    59  		t.SkipNow()
    60  	}
    61  	t.Parallel()
    62  	ht, err := newHostTester("TestHostAnnounce")
    63  	if err != nil {
    64  		t.Fatal(err)
    65  	}
    66  	defer ht.Close()
    67  
    68  	// Create an announcement finder to scan the blockchain for host
    69  	// announcements.
    70  	af, err := newAnnouncementFinder(ht.cs)
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	defer af.Close()
    75  
    76  	// Create an announcement, then use the address finding module to scan the
    77  	// blockchain for the host's address.
    78  	err = ht.host.Announce()
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	_, err = ht.miner.AddBlock()
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  	if len(af.publicKeys) != 1 {
    87  		t.Fatal("could not find host announcement in blockchain")
    88  	}
    89  	if af.netAddresses[0] != ht.host.autoAddress {
    90  		t.Error("announcement has wrong address")
    91  	}
    92  	if !bytes.Equal(af.publicKeys[0].Key, ht.host.publicKey.Key) {
    93  		t.Error("announcement has wrong host key")
    94  	}
    95  }
    96  
    97  // TestHostAnnounceAddress checks that the host announce address function is
    98  // operating correctly.
    99  func TestHostAnnounceAddress(t *testing.T) {
   100  	if testing.Short() {
   101  		t.SkipNow()
   102  	}
   103  	t.Parallel()
   104  	ht, err := newHostTester("TestHostAnnounceAddress")
   105  	if err != nil {
   106  		t.Fatal(err)
   107  	}
   108  	defer ht.Close()
   109  
   110  	// Create an announcement finder to scan the blockchain for host
   111  	// announcements.
   112  	af, err := newAnnouncementFinder(ht.cs)
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  	defer af.Close()
   117  
   118  	// Create an announcement, then use the address finding module to scan the
   119  	// blockchain for the host's address.
   120  	addr := modules.NetAddress("foo.com:1234")
   121  	err = ht.host.AnnounceAddress(addr)
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  	_, err = ht.miner.AddBlock()
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	if len(af.netAddresses) != 1 {
   130  		t.Fatal("could not find host announcement in blockchain")
   131  	}
   132  	if af.netAddresses[0] != addr {
   133  		t.Error("announcement has wrong address")
   134  	}
   135  	if !bytes.Equal(af.publicKeys[0].Key, ht.host.publicKey.Key) {
   136  		t.Error("announcement has wrong host key")
   137  	}
   138  }
   139  
   140  // TestHostAnnounceCheckUnlockHash verifies that the host's unlock hash is
   141  // checked when an announcement is performed.
   142  func TestHostAnnounceCheckUnlockHash(t *testing.T) {
   143  	if testing.Short() {
   144  		t.SkipNow()
   145  	}
   146  	t.Parallel()
   147  	ht, err := newHostTester(t.Name())
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	defer ht.Close()
   152  
   153  	ht.host.mu.RLock()
   154  	oldUnlockHash := ht.host.unlockHash
   155  	ht.host.mu.RUnlock()
   156  
   157  	err = ht.wallet.Reset()
   158  	if err != nil {
   159  		t.Fatal(err)
   160  	}
   161  	err = ht.initWallet()
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  	for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ {
   166  		_, err = ht.miner.AddBlock()
   167  		if err != nil {
   168  			t.Fatal(err)
   169  		}
   170  	}
   171  	err = ht.host.Announce()
   172  	if err != nil {
   173  		t.Fatal(err)
   174  	}
   175  	_, err = ht.miner.AddBlock()
   176  	if err != nil {
   177  		t.Fatal(err)
   178  	}
   179  	ht.host.mu.RLock()
   180  	newUnlockHash := ht.host.unlockHash
   181  	ht.host.mu.RUnlock()
   182  	if newUnlockHash == oldUnlockHash {
   183  		t.Fatal("host did not set a new unlock hash after announce with reset wallet")
   184  	}
   185  	hasAddr := false
   186  	addrs, err := ht.wallet.AllAddresses()
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  	for _, addr := range addrs {
   191  		if addr == newUnlockHash {
   192  			hasAddr = true
   193  			break
   194  		}
   195  	}
   196  	if !hasAddr {
   197  		t.Fatal("host unlock has did not exist in wallet")
   198  	}
   199  }