github.com/fozzysec/SiaPrime@v0.0.0-20190612043147-66c8e8d11fe3/modules/host/announce_test.go (about) 1 package host 2 3 import ( 4 "bytes" 5 "net" 6 "testing" 7 8 "SiaPrime/modules" 9 "SiaPrime/types" 10 ) 11 12 // announcementFinder is a quick module that parses the blockchain for host 13 // announcements, keeping a record of all the announcements that get found. 14 type announcementFinder struct { 15 cs modules.ConsensusSet 16 17 // Announcements that have been seen. The two slices are wedded. 18 netAddresses []modules.NetAddress 19 publicKeys []types.SiaPublicKey 20 } 21 22 // ProcessConsensusChange receives consensus changes from the consensus set and 23 // parses them for valid host announcements. 24 func (af *announcementFinder) ProcessConsensusChange(cc modules.ConsensusChange) { 25 for _, block := range cc.AppliedBlocks { 26 for _, txn := range block.Transactions { 27 for _, arb := range txn.ArbitraryData { 28 addr, pubKey, err := modules.DecodeAnnouncement(arb) 29 if err == nil { 30 af.netAddresses = append(af.netAddresses, addr) 31 af.publicKeys = append(af.publicKeys, pubKey) 32 } 33 } 34 } 35 } 36 } 37 38 // Close will shut down the announcement finder. 39 func (af *announcementFinder) Close() error { 40 af.cs.Unsubscribe(af) 41 return nil 42 } 43 44 // newAnnouncementFinder will create and return an announcement finder. 45 func newAnnouncementFinder(cs modules.ConsensusSet) (*announcementFinder, error) { 46 af := &announcementFinder{ 47 cs: cs, 48 } 49 err := cs.ConsensusSetSubscribe(af, modules.ConsensusChangeBeginning, nil) 50 if err != nil { 51 return nil, err 52 } 53 return af, nil 54 } 55 56 // TestHostAnnounce checks that the host announce function is operating 57 // correctly. 58 func TestHostAnnounce(t *testing.T) { 59 if testing.Short() { 60 t.SkipNow() 61 } 62 t.Parallel() 63 ht, err := newHostTester("TestHostAnnounce") 64 if err != nil { 65 t.Fatal(err) 66 } 67 defer ht.Close() 68 69 // Create an announcement finder to scan the blockchain for host 70 // announcements. 71 af, err := newAnnouncementFinder(ht.cs) 72 if err != nil { 73 t.Fatal(err) 74 } 75 defer af.Close() 76 77 // Create an announcement, then use the address finding module to scan the 78 // blockchain for the host's address. 79 err = ht.host.Announce() 80 if err != nil { 81 t.Fatal(err) 82 } 83 _, err = ht.miner.AddBlock() 84 if err != nil { 85 t.Fatal(err) 86 } 87 if len(af.publicKeys) != 1 { 88 t.Fatal("could not find host announcement in blockchain") 89 } 90 if af.netAddresses[0] != ht.host.autoAddress { 91 t.Error("announcement has wrong address") 92 } 93 if !bytes.Equal(af.publicKeys[0].Key, ht.host.publicKey.Key) { 94 t.Error("announcement has wrong host key") 95 } 96 } 97 98 // TestHostAnnounceAddress checks that the host announce address function is 99 // operating correctly. 100 func TestHostAnnounceAddress(t *testing.T) { 101 if testing.Short() { 102 t.SkipNow() 103 } 104 t.Parallel() 105 ht, err := newHostTester("TestHostAnnounceAddress") 106 if err != nil { 107 t.Fatal(err) 108 } 109 defer ht.Close() 110 111 // Create an announcement finder to scan the blockchain for host 112 // announcements. 113 af, err := newAnnouncementFinder(ht.cs) 114 if err != nil { 115 t.Fatal(err) 116 } 117 defer af.Close() 118 119 // Create an announcement, then use the address finding module to scan the 120 // blockchain for the host's address. 121 addr := modules.NetAddress("foo.com:1234") 122 err = ht.host.AnnounceAddress(addr) 123 if err != nil { 124 t.Fatal(err) 125 } 126 _, err = ht.miner.AddBlock() 127 if err != nil { 128 t.Fatal(err) 129 } 130 if len(af.netAddresses) != 1 { 131 t.Fatal("could not find host announcement in blockchain") 132 } 133 if af.netAddresses[0] != addr { 134 t.Error("announcement has wrong address") 135 } 136 if !bytes.Equal(af.publicKeys[0].Key, ht.host.publicKey.Key) { 137 t.Error("announcement has wrong host key") 138 } 139 } 140 141 // TestHostAnnounceCheckUnlockHash verifies that the host's unlock hash is 142 // checked when an announcement is performed. 143 func TestHostAnnounceCheckUnlockHash(t *testing.T) { 144 if testing.Short() { 145 t.SkipNow() 146 } 147 t.Parallel() 148 ht, err := newHostTester(t.Name()) 149 if err != nil { 150 t.Fatal(err) 151 } 152 defer ht.Close() 153 154 ht.host.mu.RLock() 155 oldUnlockHash := ht.host.unlockHash 156 ht.host.mu.RUnlock() 157 158 err = ht.wallet.Reset() 159 if err != nil { 160 t.Fatal(err) 161 } 162 err = ht.initWallet() 163 if err != nil { 164 t.Fatal(err) 165 } 166 for i := types.BlockHeight(0); i <= types.MaturityDelay; i++ { 167 _, err = ht.miner.AddBlock() 168 if err != nil { 169 t.Fatal(err) 170 } 171 } 172 err = ht.host.Announce() 173 if err != nil { 174 t.Fatal(err) 175 } 176 _, err = ht.miner.AddBlock() 177 if err != nil { 178 t.Fatal(err) 179 } 180 ht.host.mu.RLock() 181 newUnlockHash := ht.host.unlockHash 182 ht.host.mu.RUnlock() 183 if newUnlockHash == oldUnlockHash { 184 t.Fatal("host did not set a new unlock hash after announce with reset wallet") 185 } 186 hasAddr := false 187 addrs, err := ht.wallet.AllAddresses() 188 if err != nil { 189 t.Fatal(err) 190 } 191 for _, addr := range addrs { 192 if addr == newUnlockHash { 193 hasAddr = true 194 break 195 } 196 } 197 if !hasAddr { 198 t.Fatal("host unlock has did not exist in wallet") 199 } 200 } 201 202 // TestHostVerifyAnnouncementAddress tests various edge cases of the 203 // staticVerifyAnnouncementAddress function. 204 func TestHostVerifyAnnouncementAddress(t *testing.T) { 205 ipv4loopback := net.IPv4(127, 0, 0, 1) 206 if testing.Short() { 207 t.SkipNow() 208 } 209 // Create custom dependency to test edge cases for various hostnames. 210 deps := NewDependencyCustomLookupIP(func(host string) ([]net.IP, error) { 211 switch host { 212 case "TwoIPv4Loopback.com": 213 return []net.IP{ipv4loopback, ipv4loopback}, nil 214 case "TwoIPv6Loopback.com": 215 return []net.IP{net.IPv6loopback, net.IPv6loopback}, nil 216 case "DifferentLoopback.com": 217 return []net.IP{ipv4loopback, net.IPv6loopback}, nil 218 case "MoreThanTwo.com": 219 return []net.IP{{}, {}, {}}, nil 220 case "LessThanOne.com": 221 return []net.IP{}, nil 222 case "OneValidIP.com": 223 return []net.IP{{1, 2, 3, 4}}, nil 224 case "TwoValidIP.com": 225 return []net.IP{{1, 2, 3, 4}, {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}}, nil 226 case "TwoIPSameType.com": 227 return []net.IP{{1, 2, 3, 4}, {4, 3, 2, 1}}, nil 228 default: 229 t.Fatal("shouldn't happen") 230 } 231 return nil, nil 232 }) 233 // Create host from dependency. 234 ht, err := newMockHostTester(deps, t.Name()) 235 if err != nil { 236 t.Fatal(err) 237 } 238 // Create host addresses. 239 host1 := modules.NetAddress("TwoIPv4Loopback.com:1234") 240 host2 := modules.NetAddress("TwoIPv6Loopback.com:1234") 241 host3 := modules.NetAddress("DifferentLoopback.com:1234") 242 host4 := modules.NetAddress("MoreThanTwo.com:1234") 243 host5 := modules.NetAddress("LessThanOne.com:1234") 244 host6 := modules.NetAddress("OneValidIP.com:1234") 245 host7 := modules.NetAddress("TwoValidIP.com:1234") 246 host8 := modules.NetAddress("TwoIPSameType.com:1234") 247 248 // Test individual hosts. 249 if err := ht.host.staticVerifyAnnouncementAddress(host1); err == nil { 250 t.Error("Announcing host1 should have failed but didn't") 251 } 252 if err := ht.host.staticVerifyAnnouncementAddress(host2); err == nil { 253 t.Error("Announcing host2 should have failed but didn't") 254 } 255 if err := ht.host.staticVerifyAnnouncementAddress(host3); err != nil { 256 t.Error("Announcing host3 shouldn't have failed but did", err) 257 } 258 if err := ht.host.staticVerifyAnnouncementAddress(host4); err == nil { 259 t.Error("Announcing host4 should have failed but didn't") 260 } 261 if err := ht.host.staticVerifyAnnouncementAddress(host5); err == nil { 262 t.Error("Announcing host5 should have failed but didn't") 263 } 264 if err := ht.host.staticVerifyAnnouncementAddress(host6); err != nil { 265 t.Error("Announcing host6 shouldn't have failed but did", err) 266 } 267 if err := ht.host.staticVerifyAnnouncementAddress(host7); err != nil { 268 t.Error("Announcing host7 shouldn't have failed but did", err) 269 } 270 if err := ht.host.staticVerifyAnnouncementAddress(host8); err == nil { 271 t.Error("Announcing host8 should have failed but didn't") 272 } 273 }