func establishTestConnection() (net.Conn, net.Conn, error) { // First, generate the long-term private keys both ends of the connection // within our test. localPriv, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, nil, err } remotePriv, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, nil, err } // Having a port of ":0" means a random port, and interface will be // chosen for our listener. addr := ":0" // Our listener will be local, and the connection remote. listener, err := NewListener(localPriv, addr) if err != nil { return nil, nil, err } defer listener.Close() netAddr := &lnwire.NetAddress{ IdentityKey: localPriv.PubKey(), Address: listener.Addr().(*net.TCPAddr), } // Initiate a connection with a separate goroutine, and listen with our // main one. If both errors are nil, then encryption+auth was succesful. errChan := make(chan error) connChan := make(chan net.Conn) go func() { conn, err := Dial(remotePriv, netAddr) errChan <- err connChan <- conn }() localConn, listenErr := listener.Accept() if listenErr != nil { return nil, nil, err } if dialErr := <-errChan; err != nil { return nil, nil, dialErr } remoteConn := <-connChan return localConn, remoteConn, nil }
func BenchmarkPathPacketConstruction(b *testing.B) { route := make([]*btcec.PublicKey, NumMaxHops) for i := 0; i < NumMaxHops; i++ { privKey, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { b.Fatalf("unable to generate key: %v", privKey) } route[i] = privKey.PubKey() } var ( err error sphinxPacket *OnionPacket ) var hopPayloads [][]byte for i := 0; i < len(route); i++ { payload := bytes.Repeat([]byte{byte('A' + i)}, HopPayloadSize) hopPayloads = append(hopPayloads, payload) } d, _ := btcec.PrivKeyFromBytes(btcec.S256(), bytes.Repeat([]byte{'A'}, 32)) for i := 0; i < b.N; i++ { sphinxPacket, err = NewOnionPacket(route, d, hopPayloads, nil) if err != nil { b.Fatalf("unable to create packet: %v", err) } } s = sphinxPacket }
// GenActTwo generates the second packet (act two) to be sent from the // responder to the initiator. The packet for act two is identify to that of // act one, but then results in a different ECDH operation between the // initiator's and responder's ephemeral keys. // // <- e, ee func (b *BrontideMachine) GenActTwo() ([ActTwoSize]byte, error) { var ( err error actTwo [ActTwoSize]byte ) // e b.localEphemeral, err = btcec.NewPrivateKey(btcec.S256()) if err != nil { return actTwo, err } ephemeral := b.localEphemeral.PubKey().SerializeCompressed() b.mixHash(b.localEphemeral.PubKey().SerializeCompressed()) // ee s := btcec.GenerateSharedSecret(b.localEphemeral, b.remoteEphemeral) b.mixKey(s) authPayload := b.EncryptAndHash([]byte{}) copy(actTwo[:33], ephemeral) copy(actTwo[33:], authPayload) return actTwo, nil }
// makeTestOutput creates an on-chain output paying to a freshly generated // p2pkh output with the specified amount. func makeTestOutput(r *rpctest.Harness, t *testing.T, amt btcutil.Amount) (*btcec.PrivateKey, *wire.OutPoint, []byte, error) { // Create a fresh key, then send some coins to an address spendable by // that key. key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, nil, nil, err } // Using the key created above, generate a pkScript which it's able to // spend. a, err := btcutil.NewAddressPubKey(key.PubKey().SerializeCompressed(), r.ActiveNet) if err != nil { return nil, nil, nil, err } selfAddrScript, err := txscript.PayToAddrScript(a.AddressPubKeyHash()) if err != nil { return nil, nil, nil, err } output := &wire.TxOut{PkScript: selfAddrScript, Value: 1e8} // Next, create and broadcast a transaction paying to the output. fundTx, err := r.CreateTransaction([]*wire.TxOut{output}, 10) if err != nil { return nil, nil, nil, err } txHash, err := r.Node.SendRawTransaction(fundTx, true) if err != nil { return nil, nil, nil, err } // The transaction created above should be included within the next // generated block. blockHash, err := r.Node.Generate(1) if err != nil { return nil, nil, nil, err } assertTxInBlock(r, t, blockHash[0], txHash) // Locate the output index of the coins spendable by the key we // generated above, this is needed in order to create a proper utxo for // this output. var outputIndex uint32 if bytes.Equal(fundTx.TxOut[0].PkScript, selfAddrScript) { outputIndex = 0 } else { outputIndex = 1 } utxo := &wire.OutPoint{ Hash: fundTx.TxHash(), Index: outputIndex, } return key, utxo, selfAddrScript, nil }
// genRandomSig returns a random message, a signature of the message under the // public key and the public key. This function is used to generate randomized // test data. func genRandomSig() (*chainhash.Hash, *btcec.Signature, *btcec.PublicKey, error) { privKey, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, nil, nil, err } var msgHash chainhash.Hash if _, err := rand.Read(msgHash[:]); err != nil { return nil, nil, nil, err } sig, err := privKey.Sign(msgHash[:]) if err != nil { return nil, nil, nil, err } return &msgHash, sig, privKey.PubKey(), nil }
func newTestRoute(numHops int) ([]*Router, *OnionPacket, error) { nodes := make([]*Router, numHops) // Create numMaxHops random sphinx nodes. for i := 0; i < len(nodes); i++ { privKey, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, nil, fmt.Errorf("Unable to generate random "+ "key for sphinx node: %v", err) } nodes[i] = NewRouter(privKey, &chaincfg.MainNetParams) } // Gather all the pub keys in the path. route := make([]*btcec.PublicKey, len(nodes)) for i := 0; i < len(nodes); i++ { route[i] = nodes[i].onionKey.PubKey() } var hopPayloads [][]byte for i := 0; i < len(nodes); i++ { payload := bytes.Repeat([]byte{byte('A' + i)}, HopPayloadSize) hopPayloads = append(hopPayloads, payload) } // Generate a forwarding message to route to the final node via the // generated intermdiates nodes above. Destination should be Hash160, // adding padding so parsing still works. sessionKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), bytes.Repeat([]byte{'A'}, 32)) fwdMsg, err := NewOnionPacket(route, sessionKey, hopPayloads, nil) if err != nil { return nil, nil, fmt.Errorf("Unable to create forwarding "+ "message: %#v", err) } return nodes, fwdMsg, nil }
// TestCheckPkScriptStandard tests the checkPkScriptStandard API. func TestCheckPkScriptStandard(t *testing.T) { var pubKeys [][]byte for i := 0; i < 4; i++ { pk, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Fatalf("TestCheckPkScriptStandard NewPrivateKey failed: %v", err) return } pubKeys = append(pubKeys, pk.PubKey().SerializeCompressed()) } tests := []struct { name string // test description. script *txscript.ScriptBuilder isStandard bool }{ { "key1 and key2", txscript.NewScriptBuilder().AddOp(txscript.OP_2). AddData(pubKeys[0]).AddData(pubKeys[1]). AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG), true, }, { "key1 or key2", txscript.NewScriptBuilder().AddOp(txscript.OP_1). AddData(pubKeys[0]).AddData(pubKeys[1]). AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG), true, }, { "escrow", txscript.NewScriptBuilder().AddOp(txscript.OP_2). AddData(pubKeys[0]).AddData(pubKeys[1]). AddData(pubKeys[2]). AddOp(txscript.OP_3).AddOp(txscript.OP_CHECKMULTISIG), true, }, { "one of four", txscript.NewScriptBuilder().AddOp(txscript.OP_1). AddData(pubKeys[0]).AddData(pubKeys[1]). AddData(pubKeys[2]).AddData(pubKeys[3]). AddOp(txscript.OP_4).AddOp(txscript.OP_CHECKMULTISIG), false, }, { "malformed1", txscript.NewScriptBuilder().AddOp(txscript.OP_3). AddData(pubKeys[0]).AddData(pubKeys[1]). AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG), false, }, { "malformed2", txscript.NewScriptBuilder().AddOp(txscript.OP_2). AddData(pubKeys[0]).AddData(pubKeys[1]). AddOp(txscript.OP_3).AddOp(txscript.OP_CHECKMULTISIG), false, }, { "malformed3", txscript.NewScriptBuilder().AddOp(txscript.OP_0). AddData(pubKeys[0]).AddData(pubKeys[1]). AddOp(txscript.OP_2).AddOp(txscript.OP_CHECKMULTISIG), false, }, { "malformed4", txscript.NewScriptBuilder().AddOp(txscript.OP_1). AddData(pubKeys[0]).AddData(pubKeys[1]). AddOp(txscript.OP_0).AddOp(txscript.OP_CHECKMULTISIG), false, }, { "malformed5", txscript.NewScriptBuilder().AddOp(txscript.OP_1). AddData(pubKeys[0]).AddData(pubKeys[1]). AddOp(txscript.OP_CHECKMULTISIG), false, }, { "malformed6", txscript.NewScriptBuilder().AddOp(txscript.OP_1). AddData(pubKeys[0]).AddData(pubKeys[1]), false, }, } for _, test := range tests { script, err := test.script.Script() if err != nil { t.Fatalf("TestCheckPkScriptStandard test '%s' "+ "failed: %v", test.name, err) continue } scriptClass := txscript.GetScriptClass(script) got := checkPkScriptStandard(script, scriptClass) if (test.isStandard && got != nil) || (!test.isStandard && got == nil) { t.Fatalf("TestCheckPkScriptStandard test '%s' failed", test.name) return } } }
func TestSignTxOutput(t *testing.T) { t.Parallel() // make key // make script based on key. // sign with magic pixie dust. hashTypes := []SigHashType{ SigHashOld, // no longer used but should act like all SigHashAll, SigHashNone, SigHashSingle, SigHashAll | SigHashAnyOneCanPay, SigHashNone | SigHashAnyOneCanPay, SigHashSingle | SigHashAnyOneCanPay, } inputAmounts := []int64{5, 10, 15} tx := &wire.MsgTx{ Version: 1, TxIn: []*wire.TxIn{ { PreviousOutPoint: wire.OutPoint{ Hash: chainhash.Hash{}, Index: 0, }, Sequence: 4294967295, }, { PreviousOutPoint: wire.OutPoint{ Hash: chainhash.Hash{}, Index: 1, }, Sequence: 4294967295, }, { PreviousOutPoint: wire.OutPoint{ Hash: chainhash.Hash{}, Index: 2, }, Sequence: 4294967295, }, }, TxOut: []*wire.TxOut{ { Value: 1, }, { Value: 2, }, { Value: 3, }, }, LockTime: 0, } // Pay to Pubkey Hash (uncompressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } if err := signAndCheck(msg, tx, i, inputAmounts[i], pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), nil); err != nil { t.Error(err) break } } } // Pay to Pubkey Hash (uncompressed) (merging with correct) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), sigScript) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, pkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // Pay to Pubkey Hash (compressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } if err := signAndCheck(msg, tx, i, inputAmounts[i], pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), nil); err != nil { t.Error(err) break } } } // Pay to Pubkey Hash (compressed) with duplicate merge for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), sigScript) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, pkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // Pay to PubKey (uncompressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } if err := signAndCheck(msg, tx, i, inputAmounts[i], pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), nil); err != nil { t.Error(err) break } } } // Pay to PubKey (uncompressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(nil), sigScript) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, pkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // Pay to PubKey (compressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } if err := signAndCheck(msg, tx, i, inputAmounts[i], pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), nil); err != nil { t.Error(err) break } } } // Pay to PubKey (compressed) with duplicate merge for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, pkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(nil), sigScript) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, pkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // As before, but with p2sh now. // Pay to Pubkey Hash (uncompressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) break } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } if err := signAndCheck(msg, tx, i, inputAmounts[i], scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil); err != nil { t.Error(err) break } } } // Pay to Pubkey Hash (uncompressed) with duplicate merge for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) break } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // Pay to Pubkey Hash (compressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } if err := signAndCheck(msg, tx, i, inputAmounts[i], scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil); err != nil { t.Error(err) break } } } // Pay to Pubkey Hash (compressed) with duplicate merge for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKeyHash( btcutil.Hash160(pk), &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // Pay to PubKey (uncompressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript( scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } if err := signAndCheck(msg, tx, i, inputAmounts[i], scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil); err != nil { t.Error(err) break } } } // Pay to PubKey (uncompressed) with duplicate merge for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeUncompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript(scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, false}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // Pay to PubKey (compressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript(scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } if err := signAndCheck(msg, tx, i, inputAmounts[i], scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil); err != nil { t.Error(err) break } } } // Pay to PubKey (compressed) for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk := (*btcec.PublicKey)(&key.PublicKey). SerializeCompressed() address, err := btcutil.NewAddressPubKey(pk, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } pkScript, err := PayToAddrScript(address) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript(scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // by the above loop, this should be valid, now sign // again and merge. sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address.EncodeAddress(): {key, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s a "+ "second time: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) if err != nil { t.Errorf("twice signed script invalid for "+ "%s: %v", msg, err) break } } } // Basic Multisig for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key1, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk1 := (*btcec.PublicKey)(&key1.PublicKey). SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } key2, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } pk2 := (*btcec.PublicKey)(&key2.PublicKey). SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address 2 for %s: %v", msg, err) break } pkScript, err := MultiSigScript( []*btcutil.AddressPubKey{address1, address2}, 2) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript(scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } if err := signAndCheck(msg, tx, i, inputAmounts[i], scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, address2.EncodeAddress(): {key2, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil); err != nil { t.Error(err) break } } } // Two part multisig, sign with one key then the other. for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key1, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk1 := (*btcec.PublicKey)(&key1.PublicKey). SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } key2, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } pk2 := (*btcec.PublicKey)(&key2.PublicKey). SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address 2 for %s: %v", msg, err) break } pkScript, err := MultiSigScript( []*btcutil.AddressPubKey{address1, address2}, 2) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript(scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // Only 1 out of 2 signed, this *should* fail. if checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) == nil { t.Errorf("part signed script valid for %s", msg) break } // Sign with the other key and merge sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address2.EncodeAddress(): {key2, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), sigScript) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) if err != nil { t.Errorf("fully signed script invalid for "+ "%s: %v", msg, err) break } } } // Two part multisig, sign with one key then both, check key dedup // correctly. for _, hashType := range hashTypes { for i := range tx.TxIn { msg := fmt.Sprintf("%d:%d", hashType, i) key1, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey for %s: %v", msg, err) break } pk1 := (*btcec.PublicKey)(&key1.PublicKey). SerializeCompressed() address1, err := btcutil.NewAddressPubKey(pk1, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address for %s: %v", msg, err) break } key2, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Errorf("failed to make privKey 2 for %s: %v", msg, err) break } pk2 := (*btcec.PublicKey)(&key2.PublicKey). SerializeCompressed() address2, err := btcutil.NewAddressPubKey(pk2, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make address 2 for %s: %v", msg, err) break } pkScript, err := MultiSigScript( []*btcutil.AddressPubKey{address1, address2}, 2) if err != nil { t.Errorf("failed to make pkscript "+ "for %s: %v", msg, err) } scriptAddr, err := btcutil.NewAddressScriptHash( pkScript, &chaincfg.TestNet3Params) if err != nil { t.Errorf("failed to make p2sh addr for %s: %v", msg, err) break } scriptPkScript, err := PayToAddrScript(scriptAddr) if err != nil { t.Errorf("failed to make script pkscript for "+ "%s: %v", msg, err) break } sigScript, err := SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), nil) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // Only 1 out of 2 signed, this *should* fail. if checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) == nil { t.Errorf("part signed script valid for %s", msg) break } // Sign with the other key and merge sigScript, err = SignTxOutput(&chaincfg.TestNet3Params, tx, i, scriptPkScript, hashType, mkGetKey(map[string]addressToKey{ address1.EncodeAddress(): {key1, true}, address2.EncodeAddress(): {key2, true}, }), mkGetScript(map[string][]byte{ scriptAddr.EncodeAddress(): pkScript, }), sigScript) if err != nil { t.Errorf("failed to sign output %s: %v", msg, err) break } // Now we should pass. err = checkScripts(msg, tx, i, inputAmounts[i], sigScript, scriptPkScript) if err != nil { t.Errorf("fully signed script invalid for "+ "%s: %v", msg, err) break } } } }
func TestImportPrivateKey(t *testing.T) { createHeight := int32(100) createdAt := makeBS(createHeight) w, err := New(dummyDir, "A wallet for testing.", []byte("banana"), tstNetParams, createdAt) if err != nil { t.Error("Error creating new wallet: " + err.Error()) return } if err = w.Unlock([]byte("banana")); err != nil { t.Errorf("Can't unlock original wallet: %v", err) return } pk, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { t.Error("Error generating private key: " + err.Error()) return } // verify that the entire wallet's sync height matches the // expected createHeight. if _, h := w.SyncedTo(); h != createHeight { t.Errorf("Initial sync height %v does not match expected %v.", h, createHeight) return } // import priv key wif, err := btcutil.NewWIF((*btcec.PrivateKey)(pk), tstNetParams, false) if err != nil { t.Fatal(err) } importHeight := int32(50) importedAt := makeBS(importHeight) address, err := w.ImportPrivateKey(wif, importedAt) if err != nil { t.Error("importing private key: " + err.Error()) return } addr, err := w.Address(address) if err != nil { t.Error("privkey just imported missing: " + err.Error()) return } pka := addr.(PubKeyAddress) // lookup address pk2, err := pka.PrivKey() if err != nil { t.Error("error looking up key: " + err.Error()) } if !reflect.DeepEqual(pk, pk2) { t.Error("original and looked-up private keys do not match.") return } // verify that the sync height now match the (smaller) import height. if _, h := w.SyncedTo(); h != importHeight { t.Errorf("After import sync height %v does not match expected %v.", h, importHeight) return } // serialise and deseralise and check still there. // Test (de)serialization of wallet. buf := new(bytes.Buffer) _, err = w.WriteTo(buf) if err != nil { t.Errorf("Cannot write wallet: %v", err) return } w2 := new(Store) _, err = w2.ReadFrom(buf) if err != nil { t.Errorf("Cannot read wallet: %v", err) return } // Verify that the sync height match expected after the reserialization. if _, h := w2.SyncedTo(); h != importHeight { t.Errorf("After reserialization sync height %v does not match expected %v.", h, importHeight) return } // Mark imported address as partially synced with a block somewhere inbetween // the import height and the chain height. partialHeight := (createHeight-importHeight)/2 + importHeight if err := w2.SetSyncStatus(address, PartialSync(partialHeight)); err != nil { t.Errorf("Cannot mark address partially synced: %v", err) return } if _, h := w2.SyncedTo(); h != partialHeight { t.Errorf("After address partial sync, sync height %v does not match expected %v.", h, partialHeight) return } // Test serialization with the partial sync. buf.Reset() _, err = w2.WriteTo(buf) if err != nil { t.Errorf("Cannot write wallet: %v", err) return } w3 := new(Store) _, err = w3.ReadFrom(buf) if err != nil { t.Errorf("Cannot read wallet: %v", err) return } // Test correct partial height after serialization. if _, h := w3.SyncedTo(); h != partialHeight { t.Errorf("After address partial sync and reserialization, sync height %v does not match expected %v.", h, partialHeight) return } // Mark imported address as not synced at all, and verify sync height is now // the import height. if err := w3.SetSyncStatus(address, Unsynced(0)); err != nil { t.Errorf("Cannot mark address synced: %v", err) return } if _, h := w3.SyncedTo(); h != importHeight { t.Errorf("After address unsync, sync height %v does not match expected %v.", h, importHeight) return } // Mark imported address as synced with the recently-seen blocks, and verify // that the sync height now equals the most recent block (the one at wallet // creation). if err := w3.SetSyncStatus(address, FullSync{}); err != nil { t.Errorf("Cannot mark address synced: %v", err) return } if _, h := w3.SyncedTo(); h != createHeight { t.Errorf("After address sync, sync height %v does not match expected %v.", h, createHeight) return } if err = w3.Unlock([]byte("banana")); err != nil { t.Errorf("Can't unlock deserialised wallet: %v", err) return } addr3, err := w3.Address(address) if err != nil { t.Error("privkey in deserialised wallet missing : " + err.Error()) return } pka3 := addr3.(PubKeyAddress) // lookup address pk2, err = pka3.PrivKey() if err != nil { t.Error("error looking up key in deserialized wallet: " + err.Error()) } if !reflect.DeepEqual(pk, pk2) { t.Error("original and deserialized private keys do not match.") return } }
// generateSphinxPacket generates then encodes a sphinx packet which encodes // the onion route specified by the passed list of graph vertexes. The blob // returned from this function can immediately be included within an HTLC add // packet to be sent to the first hop within the route. func generateSphinxPacket(vertexes []graph.ID, paymentHash []byte) ([]byte, error) { // First convert all the vertexs from the routing table to in-memory // public key objects. These objects are necessary in order to perform // the series of ECDH operations required to construct the Sphinx // packet below. route := make([]*btcec.PublicKey, len(vertexes)) for i, vertex := range vertexes { vertexBytes, err := hex.DecodeString(vertex.String()) if err != nil { return nil, err } pub, err := btcec.ParsePubKey(vertexBytes, btcec.S256()) if err != nil { return nil, err } route[i] = pub } // Next we generate the per-hop payload which gives each node within // the route the necessary information (fees, CLTV value, etc) to // properly forward the payment. // TODO(roasbeef): properly set CLTV value, payment amount, and chain // within hop paylods. var hopPayloads [][]byte for i := 0; i < len(route); i++ { payload := bytes.Repeat([]byte{byte('A' + i)}, sphinx.HopPayloadSize) hopPayloads = append(hopPayloads, payload) } sessionKey, err := btcec.NewPrivateKey(btcec.S256()) if err != nil { return nil, err } // Next generate the onion routing packet which allows // us to perform privacy preserving source routing // across the network. sphinxPacket, err := sphinx.NewOnionPacket(route, sessionKey, hopPayloads, paymentHash) if err != nil { return nil, err } // Finally, encode Sphinx packet using it's wire represenation to be // included within the HTLC add packet. var onionBlob bytes.Buffer if err := sphinxPacket.Encode(&onionBlob); err != nil { return nil, err } rpcsLog.Tracef("[sendpayment] generated sphinx packet: %v", newLogClosure(func() string { // We unset the internal curve here in order to keep // the logs from getting noisy. sphinxPacket.Header.EphemeralKey.Curve = nil return spew.Sdump(sphinxPacket) })) return onionBlob.Bytes(), nil }