github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/services/notary/notary_test.go (about) 1 package notary 2 3 import ( 4 "testing" 5 6 "github.com/nspcc-dev/neo-go/internal/fakechain" 7 "github.com/nspcc-dev/neo-go/pkg/config" 8 "github.com/nspcc-dev/neo-go/pkg/config/netmode" 9 "github.com/nspcc-dev/neo-go/pkg/core/mempool" 10 "github.com/nspcc-dev/neo-go/pkg/core/transaction" 11 "github.com/nspcc-dev/neo-go/pkg/crypto/hash" 12 "github.com/nspcc-dev/neo-go/pkg/crypto/keys" 13 "github.com/nspcc-dev/neo-go/pkg/smartcontract" 14 "github.com/nspcc-dev/neo-go/pkg/util" 15 "github.com/nspcc-dev/neo-go/pkg/vm/opcode" 16 "github.com/stretchr/testify/require" 17 "go.uber.org/zap/zaptest" 18 ) 19 20 func TestWallet(t *testing.T) { 21 bc := fakechain.NewFakeChain() 22 mainCfg := config.P2PNotary{Enabled: true} 23 cfg := Config{ 24 MainCfg: mainCfg, 25 Chain: bc, 26 Log: zaptest.NewLogger(t), 27 } 28 t.Run("unexisting wallet", func(t *testing.T) { 29 cfg.MainCfg.UnlockWallet.Path = "./testdata/does_not_exists.json" 30 _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true, nil), nil) 31 require.Error(t, err) 32 }) 33 34 t.Run("bad password", func(t *testing.T) { 35 cfg.MainCfg.UnlockWallet.Path = "./testdata/notary1.json" 36 cfg.MainCfg.UnlockWallet.Password = "invalid" 37 _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true, nil), nil) 38 require.Error(t, err) 39 }) 40 41 t.Run("good", func(t *testing.T) { 42 cfg.MainCfg.UnlockWallet.Path = "./testdata/notary1.json" 43 cfg.MainCfg.UnlockWallet.Password = "one" 44 _, err := NewNotary(cfg, netmode.UnitTestNet, mempool.New(1, 1, true, nil), nil) 45 require.NoError(t, err) 46 }) 47 } 48 49 func TestVerifyIncompleteRequest(t *testing.T) { 50 bc := fakechain.NewFakeChain() 51 notaryContractHash := util.Uint160{1, 2, 3} 52 bc.NotaryContractScriptHash = notaryContractHash 53 _, ntr, _ := getTestNotary(t, bc, "./testdata/notary1.json", "one") 54 sig := append([]byte{byte(opcode.PUSHDATA1), keys.SignatureLen}, make([]byte, keys.SignatureLen)...) // we're not interested in signature correctness 55 acc1, _ := keys.NewPrivateKey() 56 acc2, _ := keys.NewPrivateKey() 57 acc3, _ := keys.NewPrivateKey() 58 sigScript1 := acc1.PublicKey().GetVerificationScript() 59 sigScript2 := acc2.PublicKey().GetVerificationScript() 60 sigScript3 := acc3.PublicKey().GetVerificationScript() 61 multisigScript1, err := smartcontract.CreateMultiSigRedeemScript(1, keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}) 62 require.NoError(t, err) 63 multisigScriptHash1 := hash.Hash160(multisigScript1) 64 multisigScript2, err := smartcontract.CreateMultiSigRedeemScript(2, keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}) 65 require.NoError(t, err) 66 multisigScriptHash2 := hash.Hash160(multisigScript2) 67 68 checkErr := func(t *testing.T, tx *transaction.Transaction, nKeys uint8) { 69 witnessInfo, err := ntr.verifyIncompleteWitnesses(tx, nKeys) 70 require.Error(t, err) 71 require.Nil(t, witnessInfo) 72 } 73 74 errCases := map[string]struct { 75 tx *transaction.Transaction 76 nKeys uint8 77 }{ 78 "not enough signers": { 79 tx: &transaction.Transaction{ 80 Signers: []transaction.Signer{{Account: notaryContractHash}}, 81 Scripts: []transaction.Witness{{}}, 82 }, 83 }, 84 "missing Notary witness": { 85 tx: &transaction.Transaction{ 86 Signers: []transaction.Signer{{Account: acc1.GetScriptHash()}, {Account: acc2.GetScriptHash()}}, 87 Scripts: []transaction.Witness{{}, {}}, 88 }, 89 }, 90 "bad verification script": { 91 tx: &transaction.Transaction{ 92 Signers: []transaction.Signer{{Account: acc1.PublicKey().GetScriptHash()}, {Account: notaryContractHash}}, 93 Scripts: []transaction.Witness{ 94 { 95 InvocationScript: []byte{}, 96 VerificationScript: []byte{1, 2, 3}, 97 }, 98 {}, 99 }, 100 }, 101 }, 102 "sig: bad nKeys": { 103 tx: &transaction.Transaction{ 104 Signers: []transaction.Signer{{Account: acc1.PublicKey().GetScriptHash()}, {Account: acc2.PublicKey().GetScriptHash()}, {Account: notaryContractHash}}, 105 Scripts: []transaction.Witness{ 106 { 107 InvocationScript: sig, 108 VerificationScript: sigScript1, 109 }, 110 { 111 InvocationScript: sig, 112 VerificationScript: sigScript2, 113 }, 114 {}, 115 }, 116 }, 117 nKeys: 3, 118 }, 119 "multisig: bad witnesses count": { 120 tx: &transaction.Transaction{ 121 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: notaryContractHash}}, 122 Scripts: []transaction.Witness{ 123 { 124 InvocationScript: sig, 125 VerificationScript: multisigScript1, 126 }, 127 }, 128 }, 129 nKeys: 2, 130 }, 131 "multisig: bad nKeys": { 132 tx: &transaction.Transaction{ 133 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: notaryContractHash}}, 134 Scripts: []transaction.Witness{ 135 { 136 InvocationScript: sig, 137 VerificationScript: multisigScript1, 138 }, 139 {}, 140 }, 141 }, 142 nKeys: 2, 143 }, 144 } 145 146 for name, errCase := range errCases { 147 t.Run(name, func(t *testing.T) { 148 checkErr(t, errCase.tx, errCase.nKeys) 149 }) 150 } 151 152 testCases := map[string]struct { 153 tx *transaction.Transaction 154 nKeys uint8 155 expectedInfo []witnessInfo 156 }{ 157 "single sig": { 158 tx: &transaction.Transaction{ 159 Signers: []transaction.Signer{{Account: acc1.GetScriptHash()}, {Account: notaryContractHash}}, 160 Scripts: []transaction.Witness{ 161 { 162 InvocationScript: sig, 163 VerificationScript: sigScript1, 164 }, 165 {}, 166 }, 167 }, 168 nKeys: 1, 169 expectedInfo: []witnessInfo{ 170 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 171 {typ: Contract}, 172 }, 173 }, 174 "multiple sig": { 175 tx: &transaction.Transaction{ 176 Signers: []transaction.Signer{{Account: acc1.GetScriptHash()}, {Account: acc2.GetScriptHash()}, {Account: acc3.GetScriptHash()}, {Account: notaryContractHash}}, 177 Scripts: []transaction.Witness{ 178 { 179 InvocationScript: sig, 180 VerificationScript: sigScript1, 181 }, 182 { 183 InvocationScript: []byte{}, 184 VerificationScript: sigScript2, 185 }, 186 { 187 InvocationScript: sig, 188 VerificationScript: sigScript3, 189 }, 190 {}, 191 }, 192 }, 193 nKeys: 3, 194 expectedInfo: []witnessInfo{ 195 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 196 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc2.PublicKey()}}, 197 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc3.PublicKey()}}, 198 {typ: Contract}, 199 }, 200 }, 201 "single multisig 1 out of 3": { 202 tx: &transaction.Transaction{ 203 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: notaryContractHash}}, 204 Scripts: []transaction.Witness{ 205 { 206 InvocationScript: sig, 207 VerificationScript: multisigScript1, 208 }, 209 {}, 210 }, 211 }, 212 nKeys: 3, 213 expectedInfo: []witnessInfo{ 214 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 215 {typ: Contract}, 216 }, 217 }, 218 "single multisig 2 out of 3": { 219 tx: &transaction.Transaction{ 220 Signers: []transaction.Signer{{Account: multisigScriptHash2}, {Account: notaryContractHash}}, 221 Scripts: []transaction.Witness{ 222 { 223 InvocationScript: sig, 224 VerificationScript: multisigScript2, 225 }, 226 {}, 227 }, 228 }, 229 nKeys: 3, 230 expectedInfo: []witnessInfo{ 231 {typ: MultiSignature, nSigsLeft: 2, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 232 {typ: Contract}, 233 }, 234 }, 235 "empty sig + single multisig 1 out of 3": { 236 tx: &transaction.Transaction{ 237 Signers: []transaction.Signer{{Account: acc1.PublicKey().GetScriptHash()}, {Account: multisigScriptHash1}, {Account: notaryContractHash}}, 238 Scripts: []transaction.Witness{ 239 { 240 InvocationScript: []byte{}, 241 VerificationScript: sigScript1, 242 }, 243 { 244 InvocationScript: sig, 245 VerificationScript: multisigScript1, 246 }, 247 {}, 248 }, 249 }, 250 nKeys: 1 + 3, 251 expectedInfo: []witnessInfo{ 252 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 253 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 254 {typ: Contract}, 255 }, 256 }, 257 "single multisig 1 out of 3 + empty single sig": { 258 tx: &transaction.Transaction{ 259 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: acc1.PublicKey().GetScriptHash()}, {Account: notaryContractHash}}, 260 Scripts: []transaction.Witness{ 261 { 262 InvocationScript: sig, 263 VerificationScript: multisigScript1, 264 }, 265 { 266 InvocationScript: []byte{}, 267 VerificationScript: sigScript1, 268 }, 269 {}, 270 }, 271 }, 272 nKeys: 3 + 1, 273 expectedInfo: []witnessInfo{ 274 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 275 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 276 {typ: Contract}, 277 }, 278 }, 279 "several multisig witnesses": { 280 tx: &transaction.Transaction{ 281 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: multisigScriptHash2}, {Account: notaryContractHash}}, 282 Scripts: []transaction.Witness{ 283 { 284 InvocationScript: sig, 285 VerificationScript: multisigScript1, 286 }, 287 { 288 InvocationScript: sig, 289 VerificationScript: multisigScript2, 290 }, 291 {}, 292 }, 293 }, 294 nKeys: 3 + 3, 295 expectedInfo: []witnessInfo{ 296 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 297 {typ: MultiSignature, nSigsLeft: 2, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 298 {typ: Contract}, 299 }, 300 }, 301 "multisig + sig": { 302 tx: &transaction.Transaction{ 303 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: acc1.PublicKey().GetScriptHash()}, {Account: notaryContractHash}}, 304 Scripts: []transaction.Witness{ 305 { 306 InvocationScript: sig, 307 VerificationScript: multisigScript1, 308 }, 309 { 310 InvocationScript: sig, 311 VerificationScript: sigScript1, 312 }, 313 {}, 314 }, 315 }, 316 nKeys: 3 + 1, 317 expectedInfo: []witnessInfo{ 318 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 319 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 320 {typ: Contract}, 321 }, 322 }, 323 "sig + multisig": { 324 tx: &transaction.Transaction{ 325 Signers: []transaction.Signer{{Account: acc1.PublicKey().GetScriptHash()}, {Account: multisigScriptHash1}, {Account: notaryContractHash}}, 326 Scripts: []transaction.Witness{ 327 { 328 InvocationScript: sig, 329 VerificationScript: sigScript1, 330 }, 331 { 332 InvocationScript: sig, 333 VerificationScript: multisigScript1, 334 }, 335 {}, 336 }, 337 }, 338 nKeys: 1 + 3, 339 expectedInfo: []witnessInfo{ 340 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 341 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 342 {typ: Contract}, 343 }, 344 }, 345 "empty multisig + sig": { 346 tx: &transaction.Transaction{ 347 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: acc1.PublicKey().GetScriptHash()}, {Account: notaryContractHash}}, 348 Scripts: []transaction.Witness{ 349 { 350 InvocationScript: []byte{}, 351 VerificationScript: multisigScript1, 352 }, 353 { 354 InvocationScript: sig, 355 VerificationScript: sigScript1, 356 }, 357 {}, 358 }, 359 }, 360 nKeys: 3 + 1, 361 expectedInfo: []witnessInfo{ 362 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 363 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 364 {typ: Contract}, 365 }, 366 }, 367 "sig + empty multisig": { 368 tx: &transaction.Transaction{ 369 Signers: []transaction.Signer{{Account: acc1.PublicKey().GetScriptHash()}, {Account: multisigScriptHash1}, {Account: notaryContractHash}}, 370 Scripts: []transaction.Witness{ 371 { 372 InvocationScript: sig, 373 VerificationScript: sigScript1, 374 }, 375 { 376 InvocationScript: []byte{}, 377 VerificationScript: multisigScript1, 378 }, 379 {}, 380 }, 381 }, 382 nKeys: 1 + 3, 383 expectedInfo: []witnessInfo{ 384 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 385 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 386 {typ: Contract}, 387 }, 388 }, 389 "multisig + empty sig": { 390 tx: &transaction.Transaction{ 391 Signers: []transaction.Signer{{Account: multisigScriptHash1}, {Account: acc1.PublicKey().GetScriptHash()}, {Account: notaryContractHash}}, 392 Scripts: []transaction.Witness{ 393 { 394 InvocationScript: sig, 395 VerificationScript: multisigScript1, 396 }, 397 { 398 InvocationScript: []byte{}, 399 VerificationScript: sigScript1, 400 }, 401 {}, 402 }, 403 }, 404 nKeys: 3 + 1, 405 expectedInfo: []witnessInfo{ 406 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 407 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 408 {typ: Contract}, 409 }, 410 }, 411 "empty sig + multisig": { 412 tx: &transaction.Transaction{ 413 Signers: []transaction.Signer{{Account: acc1.PublicKey().GetScriptHash()}, {Account: multisigScriptHash1}, {Account: notaryContractHash}}, 414 Scripts: []transaction.Witness{ 415 { 416 InvocationScript: []byte{}, 417 VerificationScript: sigScript1, 418 }, 419 { 420 InvocationScript: sig, 421 VerificationScript: multisigScript1, 422 }, 423 {}, 424 }, 425 }, 426 nKeys: 1 + 3, 427 expectedInfo: []witnessInfo{ 428 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 429 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 430 {typ: Contract}, 431 }, 432 }, 433 "multiple sigs + multiple multisigs": { 434 tx: &transaction.Transaction{ 435 Signers: []transaction.Signer{{Account: multisigScriptHash1}, 436 {Account: acc1.PublicKey().GetScriptHash()}, 437 {Account: acc2.PublicKey().GetScriptHash()}, 438 {Account: acc3.PublicKey().GetScriptHash()}, 439 {Account: multisigScriptHash2}, 440 {Account: notaryContractHash}}, 441 Scripts: []transaction.Witness{ 442 { 443 InvocationScript: sig, 444 VerificationScript: multisigScript1, 445 }, 446 { 447 InvocationScript: sig, 448 VerificationScript: sigScript1, 449 }, 450 { 451 InvocationScript: []byte{}, 452 VerificationScript: sigScript2, 453 }, 454 { 455 InvocationScript: sig, 456 VerificationScript: sigScript3, 457 }, 458 { 459 InvocationScript: []byte{}, 460 VerificationScript: multisigScript2, 461 }, 462 {}, 463 }, 464 }, 465 nKeys: 3 + 1 + 1 + 1 + 3, 466 expectedInfo: []witnessInfo{ 467 {typ: MultiSignature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 468 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc1.PublicKey()}}, 469 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc2.PublicKey()}}, 470 {typ: Signature, nSigsLeft: 1, pubs: keys.PublicKeys{acc3.PublicKey()}}, 471 {typ: MultiSignature, nSigsLeft: 2, pubs: keys.PublicKeys{acc1.PublicKey(), acc2.PublicKey(), acc3.PublicKey()}}, 472 {typ: Contract}, 473 }, 474 }, 475 } 476 477 for name, testCase := range testCases { 478 t.Run(name, func(t *testing.T) { 479 actualInfo, err := ntr.verifyIncompleteWitnesses(testCase.tx, testCase.nKeys) 480 require.NoError(t, err) 481 require.Equal(t, len(testCase.expectedInfo), len(actualInfo)) 482 for i, expected := range testCase.expectedInfo { 483 actual := actualInfo[i] 484 require.Equal(t, expected.typ, actual.typ) 485 require.Equal(t, expected.nSigsLeft, actual.nSigsLeft) 486 require.ElementsMatch(t, expected.pubs, actual.pubs) 487 require.Nil(t, actual.sigs) 488 } 489 }) 490 } 491 }