func main() { // Print header fmt.Printf("%64s %34s %34s\n", "Private", "Public", "Public Compressed") // Initialise big numbers with small numbers count, one := big.NewInt(0), big.NewInt(1) // Create a slice to pad our count to 32 bytes padded := make([]byte, 32) // Loop forever because we're never going to hit the end anyway for { // Increment our counter count.Add(count, one) // Copy count value's bytes to padded slice copy(padded[32-len(count.Bytes()):], count.Bytes()) // Get public key _, public := btcec.PrivKeyFromBytes(btcec.S256(), padded) // Get compressed and uncompressed addresses caddr, _ := btcutil.NewAddressPubKey(public.SerializeCompressed(), &btcnet.MainNetParams) uaddr, _ := btcutil.NewAddressPubKey(public.SerializeUncompressed(), &btcnet.MainNetParams) // Print keys fmt.Printf("%x %34s %34s\n", padded, uaddr.EncodeAddress(), caddr.EncodeAddress()) } }
func (w *LibbitcoinWallet) GetCurrentKey(purpose bitcoin.KeyPurpose) *b32.Key { key, used, _ := w.db.Keys().GetLastKey(purpose) if key == nil { // No keys in this chain have been generated yet. Let's generate key 0. childKey := w.generateChildKey(purpose, 0) addr, _ := btc.NewAddressPubKey(childKey.PublicKey().Key, w.params) script, _ := txscript.PayToAddrScript(addr.AddressPubKeyHash()) w.db.Keys().Put(childKey, script, purpose) if purpose == bitcoin.RECEIVING || purpose == bitcoin.REFUND { w.SubscribeAddress(addr.AddressPubKeyHash()) } return childKey } else if used { // The last key in the chain has been used. Let's generated a new key and save it in the db. index := binary.BigEndian.Uint32(key.ChildNumber) childKey := w.generateChildKey(purpose, index+1) addr, _ := btc.NewAddressPubKey(childKey.PublicKey().Key, w.params) script, _ := txscript.PayToAddrScript(addr.AddressPubKeyHash()) w.db.Keys().Put(childKey, script, purpose) if purpose == bitcoin.RECEIVING || purpose == bitcoin.REFUND { w.SubscribeAddress(addr.AddressPubKeyHash()) } return childKey } else { // The last key in the chain is unused so let's just return it. return key } }
func compute(count *big.Int) (keys [ResultsPerPage]Key, length int) { var padded [32]byte var i int for i = 0; i < ResultsPerPage; i++ { // Increment our counter count.Add(count, one) // Check to make sure we're not out of range if count.Cmp(total) > 0 { break } // Copy count value's bytes to padded slice copy(padded[32-len(count.Bytes()):], count.Bytes()) // Get private and public keys privKey, public := btcec.PrivKeyFromBytes(btcec.S256(), padded[:]) // Get compressed and uncompressed addresses for public key caddr, _ := btcutil.NewAddressPubKey(public.SerializeCompressed(), &btcnet.MainNetParams) uaddr, _ := btcutil.NewAddressPubKey(public.SerializeUncompressed(), &btcnet.MainNetParams) // Encode addresses wif, _ := btcutil.NewWIF(privKey, &btcnet.MainNetParams, false) keys[i].private = wif.String() keys[i].number = count.String() keys[i].compressed = caddr.EncodeAddress() keys[i].uncompressed = uaddr.EncodeAddress() } return keys, i }
func (w *LibbitcoinWallet) subscribeAll() { keys, _ := w.db.Keys().GetAll() for _, k := range keys { addr, _ := btc.NewAddressPubKey(k.PublicKey().Key, w.params) w.SubscribeAddress(addr.AddressPubKeyHash()) } }
func TestPutDuplicateKey(t *testing.T) { addr, _ := btc.NewAddressPubKey(bip32key.PublicKey().Key, &chaincfg.MainNetParams) keysdb.Put(bip32key, addr.ScriptAddress(), bitcoin.RECEIVING) err := keysdb.Put(bip32key, addr.ScriptAddress(), bitcoin.RECEIVING) if err == nil { t.Error("Expected unquire constriant error to be thrown") } }
// keyToAddr maps the passed private to corresponding p2pkh address. func keyToAddr(key *btcec.PrivateKey, net *chaincfg.Params) (btcutil.Address, error) { serializedKey := key.PubKey().SerializeCompressed() pubKeyAddr, err := btcutil.NewAddressPubKey(serializedKey, net) if err != nil { return nil, err } return pubKeyAddr.AddressPubKeyHash(), nil }
// newAddressPubKey returns a new btcutil.AddressPubKey from the provided // serialized public key. It panics if an error occurs. This is only used in // the tests as a helper since the only way it can fail is if there is an error // in the test source code. func newAddressPubKey(serializedPubKey []byte) btcutil.Address { addr, err := btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) if err != nil { panic("invalid public key in test source") } return addr }
func (w *LibbitcoinWallet) GetFreshKey(purpose bitcoin.KeyPurpose) *b32.Key { key, _, _ := w.db.Keys().GetLastKey(purpose) index := binary.BigEndian.Uint32(key.ChildNumber) childKey := w.generateChildKey(purpose, index+1) addr, _ := btc.NewAddressPubKey(childKey.PublicKey().Key, w.params) script, _ := txscript.PayToAddrScript(addr.AddressPubKeyHash()) w.db.Keys().Put(childKey, script, purpose) if purpose == bitcoin.RECEIVING || purpose == bitcoin.REFUND { w.SubscribeAddress(addr.AddressPubKeyHash()) } return childKey }
// Loop through each address in the wallet and fetch the history from the libbitcoin server. // For each returned txid, fetch the full transaction, checking the mempool first then the blockchain. // If a transaction is returned well will parse it and check to see if we need to update our wallet state. func (w *LibbitcoinWallet) updateWalletBalances() { keys, _ := w.db.Keys().GetAll() for _, k := range keys { addr, _ := btc.NewAddressPubKey(k.PublicKey().Key, w.params) // FIXME: we don't want to fetch from height zero every time. Ideally it would use the height of the last // FIXME: seen block but to handle cases where the server failed to send a transaction we should probably // FIXME: use the last height of any transaction in the database ― which requires another db function. w.Client.FetchHistory2(addr.AddressPubKeyHash(), 0, func(i interface{}, err error) { for _, response := range i.([]libbitcoin.FetchHistory2Resp) { w.fetchFullTx(response.TxHash, response.Height) } }) } }
func TestPutKey(t *testing.T) { addr, _ := btc.NewAddressPubKey(bip32key.PublicKey().Key, &chaincfg.MainNetParams) err := keysdb.Put(bip32key, addr.ScriptAddress(), bitcoin.RECEIVING) if err != nil { t.Error(err) } stmt, err := keysdb.db.Prepare("select key from keys where key=?") defer stmt.Close() var retKey string err = stmt.QueryRow(bip32key.String()).Scan(&retKey) if err != nil { t.Error(err) } if retKey != bip32key.String() { t.Errorf(`Expected %s got %s`, bip32key.String(), retKey) } }
// DepositScript constructs and returns a multi-signature redemption script where // a certain number (Series.reqSigs) of the public keys belonging to the series // with the given ID are required to sign the transaction for it to be successful. func (p *Pool) DepositScript(seriesID uint32, branch Branch, index Index) ([]byte, error) { series := p.Series(seriesID) if series == nil { str := fmt.Sprintf("series #%d does not exist", seriesID) return nil, newError(ErrSeriesNotExists, str, nil) } pubKeys, err := branchOrder(series.publicKeys, branch) if err != nil { return nil, err } pks := make([]*btcutil.AddressPubKey, len(pubKeys)) for i, key := range pubKeys { child, err := key.Child(uint32(index)) // TODO: implement getting the next index until we find a valid one, // in case there is a hdkeychain.ErrInvalidChild. if err != nil { str := fmt.Sprintf("child #%d for this pubkey %d does not exist", index, i) return nil, newError(ErrKeyChain, str, err) } pubkey, err := child.ECPubKey() if err != nil { str := fmt.Sprintf("child #%d for this pubkey %d does not exist", index, i) return nil, newError(ErrKeyChain, str, err) } pks[i], err = btcutil.NewAddressPubKey(pubkey.SerializeCompressed(), p.manager.ChainParams()) if err != nil { str := fmt.Sprintf( "child #%d for this pubkey %d could not be converted to an address", index, i) return nil, newError(ErrKeyChain, str, err) } } script, err := txscript.MultiSigScript(pks, int(series.reqSigs)) if err != nil { str := fmt.Sprintf("error while making multisig script hash, %d", len(pks)) return nil, newError(ErrScriptCreation, str, err) } return script, nil }
// newBobNode generates a test "ln node" to interact with Alice (us). For the // funding transaction, bob has a single output totaling 7BTC. For our basic // test, he'll fund the channel with 5BTC, leaving 2BTC to the change output. // TODO(roasbeef): proper handling of change etc. func newBobNode() (*bobNode, error) { // First, parse Bob's priv key in order to obtain a key he'll use for the // multi-sig funding transaction. privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), bobsPrivKey) // Next, generate an output redeemable by bob. bobAddr, err := btcutil.NewAddressPubKey(privKey.PubKey().SerializeCompressed(), ActiveNetParams) if err != nil { return nil, err } bobAddrScript, err := txscript.PayToAddrScript(bobAddr.AddressPubKeyHash()) if err != nil { return nil, err } prevOut := wire.NewOutPoint(&wire.ShaHash{}, ^uint32(0)) // TODO(roasbeef): When the chain rpc is hooked in, assert bob's output // actually exists and it unspent in the chain. bobTxIn := wire.NewTxIn(prevOut, nil) // Using bobs priv key above, create a change address he can spend. bobChangeOutput := wire.NewTxOut(2*1e8, bobAddrScript) // Bob's initial revocation hash is just his private key with the first // byte changed... var revocation [20]byte copy(revocation[:], bobsPrivKey) revocation[0] = 0xff // His ID is just as creative... var id [wire.HashSize]byte id[0] = 0xff return &bobNode{ id: id, privKey: privKey, channelKey: pubKey, deliveryAddress: bobAddr, revocation: revocation, delay: 5, availableOutputs: []*wire.TxIn{bobTxIn}, changeOutputs: []*wire.TxOut{bobChangeOutput}, }, nil }
// generateKeyPair generates and stores an ECDSA keypair to a file. func generateKeyPair(filename string) error { // Generate keypairs. aKeypair, err := ecdsa.GenerateKey(btcec.S256(), crand.Reader) if err != nil { return err } pubkeyBtcec := btcec.PublicKey{aKeypair.PublicKey.Curve, aKeypair.PublicKey.X, aKeypair.PublicKey.Y} keypairBtcec := btcec.PrivateKey{aKeypair.PublicKey, aKeypair.D} // Create a map to json marshal keypairMap := make(map[string]string) keypairMap["pubkey"] = hex.EncodeToString(pubkeyBtcec.SerializeCompressed()) keypairMap["privkey"] = hex.EncodeToString(keypairBtcec.Serialize()) // Store the address in case anyone wants to use it for BTC pkh, err := btcutil.NewAddressPubKey(pubkeyBtcec.SerializeCompressed(), &btcnet.MainNetParams) if err != nil { return err } keypairMap["address"] = pkh.EncodeAddress() b, err := json.Marshal(keypairMap) if err != nil { return err } err = ioutil.WriteFile(filename, b, 0644) if err != nil { return err } return nil }
func TestAddresses(t *testing.T) { tests := []struct { name string addr string encoded string valid bool result btcutil.Address f func() (btcutil.Address, error) net *chaincfg.Params }{ // Positive P2PKH tests. { name: "mainnet p2pkh", addr: "1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", encoded: "1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX", valid: true, result: btcutil.TstAddressPubKeyHash( [ripemd160.Size]byte{ 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84}, chaincfg.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { pkHash := []byte{ 0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc, 0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84} return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { name: "mainnet p2pkh 2", addr: "12MzCDwodF9G1e7jfwLXfR164RNtx4BRVG", encoded: "12MzCDwodF9G1e7jfwLXfR164RNtx4BRVG", valid: true, result: btcutil.TstAddressPubKeyHash( [ripemd160.Size]byte{ 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa}, chaincfg.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { pkHash := []byte{ 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa} return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { name: "testnet p2pkh", addr: "mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", encoded: "mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", valid: true, result: btcutil.TstAddressPubKeyHash( [ripemd160.Size]byte{ 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f}, chaincfg.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { pkHash := []byte{ 0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83, 0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f} return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.TestNet3Params) }, net: &chaincfg.TestNet3Params, }, // Negative P2PKH tests. { name: "p2pkh wrong hash length", addr: "", valid: false, f: func() (btcutil.Address, error) { pkHash := []byte{ 0x00, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa} return btcutil.NewAddressPubKeyHash(pkHash, &chaincfg.MainNetParams) }, }, { name: "p2pkh bad checksum", addr: "1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gY", valid: false, }, // Positive P2SH tests. { // Taken from transactions: // output: 3c9018e8d5615c306d72397f8f5eef44308c98fb576a88e030c25456b4f3a7ac // input: 837dea37ddc8b1e3ce646f1a656e79bbd8cc7f558ac56a169626d649ebe2a3ba. name: "mainnet p2sh", addr: "3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC", encoded: "3QJmV3qfvL9SuYo34YihAf3sRCW3qSinyC", valid: true, result: btcutil.TstAddressScriptHash( [ripemd160.Size]byte{ 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0xf2, 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0x10}, chaincfg.MainNetParams.ScriptHashAddrID), f: func() (btcutil.Address, error) { script := []byte{ 0x52, 0x41, 0x04, 0x91, 0xbb, 0xa2, 0x51, 0x09, 0x12, 0xa5, 0xbd, 0x37, 0xda, 0x1f, 0xb5, 0xb1, 0x67, 0x30, 0x10, 0xe4, 0x3d, 0x2c, 0x6d, 0x81, 0x2c, 0x51, 0x4e, 0x91, 0xbf, 0xa9, 0xf2, 0xeb, 0x12, 0x9e, 0x1c, 0x18, 0x33, 0x29, 0xdb, 0x55, 0xbd, 0x86, 0x8e, 0x20, 0x9a, 0xac, 0x2f, 0xbc, 0x02, 0xcb, 0x33, 0xd9, 0x8f, 0xe7, 0x4b, 0xf2, 0x3f, 0x0c, 0x23, 0x5d, 0x61, 0x26, 0xb1, 0xd8, 0x33, 0x4f, 0x86, 0x41, 0x04, 0x86, 0x5c, 0x40, 0x29, 0x3a, 0x68, 0x0c, 0xb9, 0xc0, 0x20, 0xe7, 0xb1, 0xe1, 0x06, 0xd8, 0xc1, 0x91, 0x6d, 0x3c, 0xef, 0x99, 0xaa, 0x43, 0x1a, 0x56, 0xd2, 0x53, 0xe6, 0x92, 0x56, 0xda, 0xc0, 0x9e, 0xf1, 0x22, 0xb1, 0xa9, 0x86, 0x81, 0x8a, 0x7c, 0xb6, 0x24, 0x53, 0x2f, 0x06, 0x2c, 0x1d, 0x1f, 0x87, 0x22, 0x08, 0x48, 0x61, 0xc5, 0xc3, 0x29, 0x1c, 0xcf, 0xfe, 0xf4, 0xec, 0x68, 0x74, 0x41, 0x04, 0x8d, 0x24, 0x55, 0xd2, 0x40, 0x3e, 0x08, 0x70, 0x8f, 0xc1, 0xf5, 0x56, 0x00, 0x2f, 0x1b, 0x6c, 0xd8, 0x3f, 0x99, 0x2d, 0x08, 0x50, 0x97, 0xf9, 0x97, 0x4a, 0xb0, 0x8a, 0x28, 0x83, 0x8f, 0x07, 0x89, 0x6f, 0xba, 0xb0, 0x8f, 0x39, 0x49, 0x5e, 0x15, 0xfa, 0x6f, 0xad, 0x6e, 0xdb, 0xfb, 0x1e, 0x75, 0x4e, 0x35, 0xfa, 0x1c, 0x78, 0x44, 0xc4, 0x1f, 0x32, 0x2a, 0x18, 0x63, 0xd4, 0x62, 0x13, 0x53, 0xae} return btcutil.NewAddressScriptHash(script, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { // Taken from transactions: // output: b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d // input: (not yet redeemed at time test was written) name: "mainnet p2sh 2", addr: "3NukJ6fYZJ5Kk8bPjycAnruZkE5Q7UW7i8", encoded: "3NukJ6fYZJ5Kk8bPjycAnruZkE5Q7UW7i8", valid: true, result: btcutil.TstAddressScriptHash( [ripemd160.Size]byte{ 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4}, chaincfg.MainNetParams.ScriptHashAddrID), f: func() (btcutil.Address, error) { hash := []byte{ 0xe8, 0xc3, 0x00, 0xc8, 0x79, 0x86, 0xef, 0xa8, 0x4c, 0x37, 0xc0, 0x51, 0x99, 0x29, 0x01, 0x9e, 0xf8, 0x6e, 0xb5, 0xb4} return btcutil.NewAddressScriptHashFromHash(hash, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { // Taken from bitcoind base58_keys_valid. name: "testnet p2sh", addr: "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", encoded: "2NBFNJTktNa7GZusGbDbGKRZTxdK9VVez3n", valid: true, result: btcutil.TstAddressScriptHash( [ripemd160.Size]byte{ 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a}, chaincfg.TestNet3Params.ScriptHashAddrID), f: func() (btcutil.Address, error) { hash := []byte{ 0xc5, 0x79, 0x34, 0x2c, 0x2c, 0x4c, 0x92, 0x20, 0x20, 0x5e, 0x2c, 0xdc, 0x28, 0x56, 0x17, 0x04, 0x0c, 0x92, 0x4a, 0x0a} return btcutil.NewAddressScriptHashFromHash(hash, &chaincfg.TestNet3Params) }, net: &chaincfg.TestNet3Params, }, // Negative P2SH tests. { name: "p2sh wrong hash length", addr: "", valid: false, f: func() (btcutil.Address, error) { hash := []byte{ 0x00, 0xf8, 0x15, 0xb0, 0x36, 0xd9, 0xbb, 0xbc, 0xe5, 0xe9, 0xf2, 0xa0, 0x0a, 0xbd, 0x1b, 0xf3, 0xdc, 0x91, 0xe9, 0x55, 0x10} return btcutil.NewAddressScriptHashFromHash(hash, &chaincfg.MainNetParams) }, }, // Positive P2PK tests. { name: "mainnet p2pk compressed (0x02)", addr: "02192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4", encoded: "13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4}, btcutil.PKFCompressed, chaincfg.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { name: "mainnet p2pk compressed (0x03)", addr: "03b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65", encoded: "15sHANNUBSh6nDp8XkDPmQcW6n3EFwmvE6", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65}, btcutil.PKFCompressed, chaincfg.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { name: "mainnet p2pk uncompressed (0x04)", addr: "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2" + "e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3", encoded: "12cbQLTFMXRnSzktFkuoG3eHoMeFtpTu3S", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3}, btcutil.PKFUncompressed, chaincfg.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { name: "mainnet p2pk hybrid (0x06)", addr: "06192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4" + "0d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453e", encoded: "1Ja5rs7XBZnK88EuLVcFqYGMEbBitzchmX", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e}, btcutil.PKFHybrid, chaincfg.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { name: "mainnet p2pk hybrid (0x07)", addr: "07b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65" + "37a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b", encoded: "1ExqMmf6yMxcBMzHjbj41wbqYuqoX6uBLG", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b}, btcutil.PKFHybrid, chaincfg.MainNetParams.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.MainNetParams) }, net: &chaincfg.MainNetParams, }, { name: "testnet p2pk compressed (0x02)", addr: "02192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4", encoded: "mhiDPVP2nJunaAgTjzWSHCYfAqxxrxzjmo", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4}, btcutil.PKFCompressed, chaincfg.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x02, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) }, net: &chaincfg.TestNet3Params, }, { name: "testnet p2pk compressed (0x03)", addr: "03b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65", encoded: "mkPETRTSzU8MZLHkFKBmbKppxmdw9qT42t", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65}, btcutil.PKFCompressed, chaincfg.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x03, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) }, net: &chaincfg.TestNet3Params, }, { name: "testnet p2pk uncompressed (0x04)", addr: "0411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5" + "cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3", encoded: "mh8YhPYEAYs3E7EVyKtB5xrcfMExkkdEMF", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3}, btcutil.PKFUncompressed, chaincfg.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x04, 0x11, 0xdb, 0x93, 0xe1, 0xdc, 0xdb, 0x8a, 0x01, 0x6b, 0x49, 0x84, 0x0f, 0x8c, 0x53, 0xbc, 0x1e, 0xb6, 0x8a, 0x38, 0x2e, 0x97, 0xb1, 0x48, 0x2e, 0xca, 0xd7, 0xb1, 0x48, 0xa6, 0x90, 0x9a, 0x5c, 0xb2, 0xe0, 0xea, 0xdd, 0xfb, 0x84, 0xcc, 0xf9, 0x74, 0x44, 0x64, 0xf8, 0x2e, 0x16, 0x0b, 0xfa, 0x9b, 0x8b, 0x64, 0xf9, 0xd4, 0xc0, 0x3f, 0x99, 0x9b, 0x86, 0x43, 0xf6, 0x56, 0xb4, 0x12, 0xa3} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) }, net: &chaincfg.TestNet3Params, }, { name: "testnet p2pk hybrid (0x06)", addr: "06192d74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b" + "40d45264838c0bd96852662ce6a847b197376830160c6d2eb5e6a4c44d33f453e", encoded: "my639vCVzbDZuEiX44adfTUg6anRomZLEP", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e}, btcutil.PKFHybrid, chaincfg.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x06, 0x19, 0x2d, 0x74, 0xd0, 0xcb, 0x94, 0x34, 0x4c, 0x95, 0x69, 0xc2, 0xe7, 0x79, 0x01, 0x57, 0x3d, 0x8d, 0x79, 0x03, 0xc3, 0xeb, 0xec, 0x3a, 0x95, 0x77, 0x24, 0x89, 0x5d, 0xca, 0x52, 0xc6, 0xb4, 0x0d, 0x45, 0x26, 0x48, 0x38, 0xc0, 0xbd, 0x96, 0x85, 0x26, 0x62, 0xce, 0x6a, 0x84, 0x7b, 0x19, 0x73, 0x76, 0x83, 0x01, 0x60, 0xc6, 0xd2, 0xeb, 0x5e, 0x6a, 0x4c, 0x44, 0xd3, 0x3f, 0x45, 0x3e} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) }, net: &chaincfg.TestNet3Params, }, { name: "testnet p2pk hybrid (0x07)", addr: "07b0bd634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e6" + "537a576782eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3c1e0908ef7b", encoded: "muUnepk5nPPrxUTuTAhRqrpAQuSWS5fVii", valid: true, result: btcutil.TstAddressPubKey( []byte{ 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b}, btcutil.PKFHybrid, chaincfg.TestNet3Params.PubKeyHashAddrID), f: func() (btcutil.Address, error) { serializedPubKey := []byte{ 0x07, 0xb0, 0xbd, 0x63, 0x42, 0x34, 0xab, 0xbb, 0x1b, 0xa1, 0xe9, 0x86, 0xe8, 0x84, 0x18, 0x5c, 0x61, 0xcf, 0x43, 0xe0, 0x01, 0xf9, 0x13, 0x7f, 0x23, 0xc2, 0xc4, 0x09, 0x27, 0x3e, 0xb1, 0x6e, 0x65, 0x37, 0xa5, 0x76, 0x78, 0x2e, 0xba, 0x66, 0x8a, 0x7e, 0xf8, 0xbd, 0x3b, 0x3c, 0xfb, 0x1e, 0xdb, 0x71, 0x17, 0xab, 0x65, 0x12, 0x9b, 0x8a, 0x2e, 0x68, 0x1f, 0x3c, 0x1e, 0x09, 0x08, 0xef, 0x7b} return btcutil.NewAddressPubKey(serializedPubKey, &chaincfg.TestNet3Params) }, net: &chaincfg.TestNet3Params, }, } for _, test := range tests { // Decode addr and compare error against valid. decoded, err := btcutil.DecodeAddress(test.addr, test.net) if (err == nil) != test.valid { t.Errorf("%v: decoding test failed: %v", test.name, err) return } if err == nil { // Ensure the stringer returns the same address as the // original. if decodedStringer, ok := decoded.(fmt.Stringer); ok { if test.addr != decodedStringer.String() { t.Errorf("%v: String on decoded value does not match expected value: %v != %v", test.name, test.addr, decodedStringer.String()) return } } // Encode again and compare against the original. encoded := decoded.EncodeAddress() if test.encoded != encoded { t.Errorf("%v: decoding and encoding produced different addressess: %v != %v", test.name, test.encoded, encoded) return } // Perform type-specific calculations. var saddr []byte switch d := decoded.(type) { case *btcutil.AddressPubKeyHash: saddr = btcutil.TstAddressSAddr(encoded) case *btcutil.AddressScriptHash: saddr = btcutil.TstAddressSAddr(encoded) case *btcutil.AddressPubKey: // Ignore the error here since the script // address is checked below. saddr, _ = hex.DecodeString(d.String()) } // Check script address, as well as the Hash160 method for P2PKH and // P2SH addresses. if !bytes.Equal(saddr, decoded.ScriptAddress()) { t.Errorf("%v: script addresses do not match:\n%x != \n%x", test.name, saddr, decoded.ScriptAddress()) return } switch a := decoded.(type) { case *btcutil.AddressPubKeyHash: if h := a.Hash160()[:]; !bytes.Equal(saddr, h) { t.Errorf("%v: hashes do not match:\n%x != \n%x", test.name, saddr, h) return } case *btcutil.AddressScriptHash: if h := a.Hash160()[:]; !bytes.Equal(saddr, h) { t.Errorf("%v: hashes do not match:\n%x != \n%x", test.name, saddr, h) return } } // Ensure the address is for the expected network. if !decoded.IsForNet(test.net) { t.Errorf("%v: calculated network does not match expected", test.name) return } } if !test.valid { // If address is invalid, but a creation function exists, // verify that it returns a nil addr and non-nil error. if test.f != nil { _, err := test.f() if err == nil { t.Errorf("%v: address is invalid but creating new address succeeded", test.name) return } } continue } // Valid test, compare address created with f against expected result. addr, err := test.f() if err != nil { t.Errorf("%v: address is valid but creating new address failed with error %v", test.name, err) return } if !reflect.DeepEqual(addr, test.result) { t.Errorf("%v: created address does not match expected result", test.name) return } } }
func TestOpenChannelEncodeDecode(t *testing.T) { teardown, manager := createTestManager(t) defer teardown() privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), key[:]) addr, err := btcutil.NewAddressPubKey(pubKey.SerializeCompressed(), ActiveNetParams) if err != nil { t.Fatalf("unable to create delivery address") } script, err := txscript.MultiSigScript([]*btcutil.AddressPubKey{addr, addr}, 2) if err != nil { t.Fatalf("unable to create redeemScript") } state := OpenChannel{ TheirLNID: id, ChanID: id, MinFeePerKb: btcutil.Amount(5000), OurCommitKey: privKey, TheirCommitKey: pubKey, Capacity: btcutil.Amount(10000), OurBalance: btcutil.Amount(3000), TheirBalance: btcutil.Amount(7000), TheirCommitTx: testTx, OurCommitTx: testTx, FundingTx: testTx, MultiSigKey: privKey, FundingRedeemScript: script, TheirCurrentRevocation: rev, OurDeliveryAddress: addr, TheirDeliveryAddress: addr, CsvDelay: 5, NumUpdates: 1, TotalSatoshisSent: 1, TotalSatoshisReceived: 2, CreationTime: time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC), } var b bytes.Buffer if err := state.Encode(&b, manager); err != nil { t.Fatalf("unable to encode channel state: %v", err) } reader := bytes.NewReader(b.Bytes()) newState := &OpenChannel{} if err := newState.Decode(reader, manager); err != nil { t.Fatalf("unable to decode channel state: %v", err) } // The decoded channel state should be identical to what we stored // above. if !bytes.Equal(state.TheirLNID[:], newState.TheirLNID[:]) { t.Fatalf("their id doesn't match") } if !bytes.Equal(state.ChanID[:], newState.ChanID[:]) { t.Fatalf("chan id's don't match") } if state.MinFeePerKb != newState.MinFeePerKb { t.Fatalf("fee/kb doens't match") } if !bytes.Equal(state.OurCommitKey.Serialize(), newState.OurCommitKey.Serialize()) { t.Fatalf("our commit key dont't match") } if !bytes.Equal(state.TheirCommitKey.SerializeCompressed(), newState.TheirCommitKey.SerializeCompressed()) { t.Fatalf("their commit key dont't match") } if state.Capacity != newState.Capacity { t.Fatalf("capacity doesn't match") } if state.OurBalance != newState.OurBalance { t.Fatalf("our balance doesn't match") } if state.TheirBalance != newState.TheirBalance { t.Fatalf("their balance doesn't match") } var b1, b2 bytes.Buffer if err := state.TheirCommitTx.Serialize(&b1); err != nil { t.Fatalf("unable to serialize transaction") } if err := newState.TheirCommitTx.Serialize(&b2); err != nil { t.Fatalf("unable to serialize transaction") } if !bytes.Equal(b1.Bytes(), b2.Bytes()) { t.Fatalf("theirCommitTx doesn't match") } b1.Reset() b2.Reset() if err := state.OurCommitTx.Serialize(&b1); err != nil { t.Fatalf("unable to serialize transaction") } if err := newState.OurCommitTx.Serialize(&b2); err != nil { t.Fatalf("unable to serialize transaction") } if !bytes.Equal(b1.Bytes(), b2.Bytes()) { t.Fatalf("ourCommitTx doesn't match") } b1.Reset() b2.Reset() if err := state.FundingTx.Serialize(&b1); err != nil { t.Fatalf("unable to serialize transaction") } if err := newState.FundingTx.Serialize(&b2); err != nil { t.Fatalf("unable to serialize transaction") } if !bytes.Equal(b1.Bytes(), b2.Bytes()) { t.Fatalf("funding tx doesn't match") } if !bytes.Equal(state.MultiSigKey.Serialize(), newState.MultiSigKey.Serialize()) { t.Fatalf("multisig key doesn't match") } if !bytes.Equal(state.FundingRedeemScript, newState.FundingRedeemScript) { t.Fatalf("redeem script doesn't match") } if state.OurDeliveryAddress.EncodeAddress() != newState.OurDeliveryAddress.EncodeAddress() { t.Fatalf("our delivery address doesn't match") } if state.TheirDeliveryAddress.EncodeAddress() != newState.TheirDeliveryAddress.EncodeAddress() { t.Fatalf("their delivery address doesn't match") } if state.NumUpdates != newState.NumUpdates { t.Fatalf("num updates doesn't match: %v vs %v", state.NumUpdates, newState.NumUpdates) } if state.CsvDelay != newState.CsvDelay { t.Fatalf("csv delay doesn't match: %v vs %v", state.CsvDelay, newState.CsvDelay) } if state.TotalSatoshisSent != newState.TotalSatoshisSent { t.Fatalf("satoshis sent doesn't match: %v vs %v", state.TotalSatoshisSent, newState.TotalSatoshisSent) } if state.TotalSatoshisReceived != newState.TotalSatoshisReceived { t.Fatalf("satoshis received doesn't match") } if state.CreationTime.Unix() != newState.CreationTime.Unix() { t.Fatalf("creation time doesn't match") } }
// ExtractPkScriptAddrs returns the type of script, addresses and required // signatures associated with the passed PkScript. Note that it only works for // 'standard' transaction script types. Any data such as public keys which are // invalid are omitted from the results. func ExtractPkScriptAddrs(pkScript []byte, chainParams *chaincfg.Params) (ScriptClass, []btcutil.Address, int, error) { var addrs []btcutil.Address var requiredSigs int // No valid addresses or required signatures if the script doesn't // parse. pops, err := parseScript(pkScript) if err != nil { return NonStandardTy, nil, 0, err } scriptClass := typeOfScript(pops) switch scriptClass { case PubKeyHashTy: // A pay-to-pubkey-hash script is of the form: // OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG // Therefore the pubkey hash is the 3rd item on the stack. // Skip the pubkey hash if it's invalid for some reason. requiredSigs = 1 addr, err := btcutil.NewAddressPubKeyHash(pops[2].data, chainParams) if err == nil { addrs = append(addrs, addr) } case PubKeyTy: // A pay-to-pubkey script is of the form: // <pubkey> OP_CHECKSIG // Therefore the pubkey is the first item on the stack. // Skip the pubkey if it's invalid for some reason. requiredSigs = 1 addr, err := btcutil.NewAddressPubKey(pops[0].data, chainParams) if err == nil { addrs = append(addrs, addr) } case ScriptHashTy: // A pay-to-script-hash script is of the form: // OP_HASH160 <scripthash> OP_EQUAL // Therefore the script hash is the 2nd item on the stack. // Skip the script hash if it's invalid for some reason. requiredSigs = 1 addr, err := btcutil.NewAddressScriptHashFromHash(pops[1].data, chainParams) if err == nil { addrs = append(addrs, addr) } case MultiSigTy: // A multi-signature script is of the form: // <numsigs> <pubkey> <pubkey> <pubkey>... <numpubkeys> OP_CHECKMULTISIG // Therefore the number of required signatures is the 1st item // on the stack and the number of public keys is the 2nd to last // item on the stack. requiredSigs = asSmallInt(pops[0].opcode) numPubKeys := asSmallInt(pops[len(pops)-2].opcode) // Extract the public keys while skipping any that are invalid. addrs = make([]btcutil.Address, 0, numPubKeys) for i := 0; i < numPubKeys; i++ { addr, err := btcutil.NewAddressPubKey(pops[i+1].data, chainParams) if err == nil { addrs = append(addrs, addr) } } case NullDataTy: // Null data transactions have no addresses or required // signatures. case NonStandardTy: // Don't attempt to extract addresses or required signatures for // nonstandard transactions. } return scriptClass, addrs, requiredSigs, nil }
// TestMultiSigScript ensures the MultiSigScript function returns the expected // scripts and errors. func TestMultiSigScript(t *testing.T) { t.Parallel() // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg p2pkCompressedMain, err := btcutil.NewAddressPubKey(decodeHex("02192d7"+ "4d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed): %v", err) return } p2pkCompressed2Main, err := btcutil.NewAddressPubKey(decodeHex("03b0bd"+ "634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed 2): %v", err) return } p2pkUncompressedMain, err := btcutil.NewAddressPubKey(decodeHex("0411d"+ "b93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c"+ "b2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b41"+ "2a3"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (uncompressed): %v", err) return } tests := []struct { keys []*btcutil.AddressPubKey nrequired int expected string err error }{ { []*btcutil.AddressPubKey{ p2pkCompressedMain, p2pkCompressed2Main, }, 1, "1 DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c" + "3ebec3a957724895dca52c6b4 DATA_33 0x03b0bd634" + "234abbb1ba1e986e884185c61cf43e001f9137f23c2c4" + "09273eb16e65 2 CHECKMULTISIG", nil, }, { []*btcutil.AddressPubKey{ p2pkCompressedMain, p2pkCompressed2Main, }, 2, "2 DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c" + "3ebec3a957724895dca52c6b4 DATA_33 0x03b0bd634" + "234abbb1ba1e986e884185c61cf43e001f9137f23c2c4" + "09273eb16e65 2 CHECKMULTISIG", nil, }, { []*btcutil.AddressPubKey{ p2pkCompressedMain, p2pkCompressed2Main, }, 3, "", txscript.ErrBadNumRequired, }, { []*btcutil.AddressPubKey{ p2pkUncompressedMain, }, 1, "1 DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382" + "e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf97444" + "64f82e160bfa9b8b64f9d4c03f999b8643f656b412a3 " + "1 CHECKMULTISIG", nil, }, { []*btcutil.AddressPubKey{ p2pkUncompressedMain, }, 2, "", txscript.ErrBadNumRequired, }, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { script, err := txscript.MultiSigScript(test.keys, test.nrequired) if err != test.err { t.Errorf("MultiSigScript #%d unexpected error - "+ "got %v, want %v", i, err, test.err) continue } expected := mustParseShortForm(test.expected) if !bytes.Equal(script, expected) { t.Errorf("MultiSigScript #%d got: %x\nwant: %x", i, script, expected) continue } } }
// TestPayToAddrScript ensures the PayToAddrScript function generates the // correct scripts for the various types of addresses. func TestPayToAddrScript(t *testing.T) { t.Parallel() // 1MirQ9bwyQcGVJPwKUgapu5ouK2E2Ey4gX p2pkhMain, err := btcutil.NewAddressPubKeyHash(decodeHex("e34cce70c863"+ "73273efcc54ce7d2a491bb4a0e84"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create public key hash address: %v", err) return } // Taken from transaction: // b0539a45de13b3e0403909b8bd1a555b8cbe45fd4e3f3fda76f3a5f52835c29d p2shMain, _ := btcutil.NewAddressScriptHashFromHash(decodeHex("e8c300"+ "c87986efa84c37c0519929019ef86eb5b4"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create script hash address: %v", err) return } // mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg p2pkCompressedMain, err := btcutil.NewAddressPubKey(decodeHex("02192d74"+ "d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed): %v", err) return } p2pkCompressed2Main, err := btcutil.NewAddressPubKey(decodeHex("03b0bd"+ "634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (compressed 2): %v", err) return } p2pkUncompressedMain, err := btcutil.NewAddressPubKey(decodeHex("0411db"+ "93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2"+ "e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3"), &chaincfg.MainNetParams) if err != nil { t.Errorf("Unable to create pubkey address (uncompressed): %v", err) return } tests := []struct { in btcutil.Address expected string err error }{ // pay-to-pubkey-hash address on mainnet { p2pkhMain, "DUP HASH160 DATA_20 0xe34cce70c86373273efcc54ce7d2a4" + "91bb4a0e8488 CHECKSIG", nil, }, // pay-to-script-hash address on mainnet { p2shMain, "HASH160 DATA_20 0xe8c300c87986efa84c37c0519929019ef8" + "6eb5b4 EQUAL", nil, }, // pay-to-pubkey address on mainnet. compressed key. { p2pkCompressedMain, "DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c3" + "ebec3a957724895dca52c6b4 CHECKSIG", nil, }, // pay-to-pubkey address on mainnet. compressed key (other way). { p2pkCompressed2Main, "DATA_33 0x03b0bd634234abbb1ba1e986e884185c61cf43e001" + "f9137f23c2c409273eb16e65 CHECKSIG", nil, }, // pay-to-pubkey address on mainnet. uncompressed key. { p2pkUncompressedMain, "DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" + "97b1482ecad7b148a6909a5cb2e0eaddfb84ccf97444" + "64f82e160bfa9b8b64f9d4c03f999b8643f656b412a3 " + "CHECKSIG", nil, }, // Supported address types with nil pointers. {(*btcutil.AddressPubKeyHash)(nil), "", txscript.ErrUnsupportedAddress}, {(*btcutil.AddressScriptHash)(nil), "", txscript.ErrUnsupportedAddress}, {(*btcutil.AddressPubKey)(nil), "", txscript.ErrUnsupportedAddress}, // Unsupported address type. {&bogusAddress{}, "", txscript.ErrUnsupportedAddress}, } t.Logf("Running %d tests", len(tests)) for i, test := range tests { pkScript, err := txscript.PayToAddrScript(test.in) if err != test.err { t.Errorf("PayToAddrScript #%d unexpected error - "+ "got %v, want %v", i, err, test.err) continue } expected := mustParseShortForm(test.expected) if !bytes.Equal(pkScript, expected) { t.Errorf("PayToAddrScript #%d got: %x\nwant: %x", i, pkScript, expected) continue } } }
// newBobNode generates a test "ln node" to interact with Alice (us). For the // funding transaction, bob has a single output totaling 7BTC. For our basic // test, he'll fund the channel with 5BTC, leaving 2BTC to the change output. // TODO(roasbeef): proper handling of change etc. func newBobNode(miner *rpctest.Harness) (*bobNode, error) { // First, parse Bob's priv key in order to obtain a key he'll use for the // multi-sig funding transaction. privKey, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), bobsPrivKey) // Next, generate an output redeemable by bob. bobAddrPk, err := btcutil.NewAddressPubKey(privKey.PubKey().SerializeCompressed(), miner.ActiveNet) if err != nil { return nil, err } bobAddr := bobAddrPk.AddressPubKeyHash() bobAddrScript, err := txscript.PayToAddrScript(bobAddr) if err != nil { return nil, err } // Give bobNode one 7 BTC output for use in creating channels. outputMap := map[string]btcutil.Amount{ bobAddr.String(): btcutil.Amount(7e8), } mainTxid, err := miner.CoinbaseSpend(outputMap) if err != nil { return nil, err } // Mine a block in order to include the above output in a block. During // the reservation workflow, we currently test to ensure that the funding // output we're given actually exists. if _, err := miner.Node.Generate(1); err != nil { return nil, err } // Grab the transaction in order to locate the output index to Bob. tx, err := miner.Node.GetRawTransaction(mainTxid) if err != nil { return nil, err } found, index := findScriptOutputIndex(tx.MsgTx(), bobAddrScript) if !found { return nil, fmt.Errorf("output to bob never created") } prevOut := wire.NewOutPoint(mainTxid, index) // TODO(roasbeef): When the chain rpc is hooked in, assert bob's output // actually exists and it unspent in the chain. bobTxIn := wire.NewTxIn(prevOut, nil) // Using bobs priv key above, create a change output he can spend. bobChangeOutput := wire.NewTxOut(2*1e8, bobAddrScript) // Bob's initial revocation hash is just his private key with the first // byte changed... var revocation [20]byte copy(revocation[:], bobsPrivKey) revocation[0] = 0xff // His ID is just as creative... var id [wire.HashSize]byte id[0] = 0xff return &bobNode{ id: id, privKey: privKey, channelKey: pubKey, deliveryAddress: bobAddr, revocation: revocation, delay: 5, availableOutputs: []*wire.TxIn{bobTxIn}, changeOutputs: []*wire.TxOut{bobChangeOutput}, }, nil }
func (w *LibbitcoinWallet) GetFreshAddress(purpose bitcoin.KeyPurpose) *btc.AddressPubKeyHash { key := w.GetFreshKey(purpose) addr, _ := btc.NewAddressPubKey(key.PublicKey().Key, w.params) return addr.AddressPubKeyHash() }
func loadTestCredits(w *LightningWallet, numOutputs, btcPerOutput int) error { // Import the priv key (converting to WIF) above that controls all our // available outputs. privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), testWalletPrivKey) if err := w.Unlock(privPass, time.Duration(0)); err != nil { return err } bs := &waddrmgr.BlockStamp{Hash: *genBlockHash(1), Height: 1} wif, err := btcutil.NewWIF(privKey, ActiveNetParams, true) if err != nil { return err } if _, err := w.ImportPrivateKey(wif, bs, false); err != nil { return nil } if err := w.Manager.SetSyncedTo(&waddrmgr.BlockStamp{int32(1), *genBlockHash(1)}); err != nil { return err } blk := wtxmgr.BlockMeta{wtxmgr.Block{Hash: *genBlockHash(2), Height: 2}, time.Now()} // Create a simple P2PKH pubkey script spendable by Alice. For simplicity // all of Alice's spendable funds will reside in this output. satosihPerOutput := int64(btcPerOutput * 1e8) walletAddr, err := btcutil.NewAddressPubKey(privKey.PubKey().SerializeCompressed(), ActiveNetParams) if err != nil { return err } walletScriptCredit, err := txscript.PayToAddrScript(walletAddr.AddressPubKeyHash()) if err != nil { return err } // Create numOutputs outputs spendable by our wallet each holding btcPerOutput // in satoshis. tx := wire.NewMsgTx() prevOut := wire.NewOutPoint(genBlockHash(999), 1) txIn := wire.NewTxIn(prevOut, []byte{txscript.OP_0, txscript.OP_0}) tx.AddTxIn(txIn) for i := 0; i < numOutputs; i++ { tx.AddTxOut(wire.NewTxOut(satosihPerOutput, walletScriptCredit)) } txCredit, err := wtxmgr.NewTxRecordFromMsgTx(tx, time.Now()) if err != nil { return err } if err := addTestTx(w, txCredit, &blk); err != nil { return err } if err := w.Manager.SetSyncedTo(&waddrmgr.BlockStamp{int32(2), *genBlockHash(2)}); err != nil { return err } // Make the wallet think it's been synced to block 10. This way the // outputs we added above will have sufficient confirmations // (hard coded to 6 atm). for i := 3; i < 10; i++ { sha := *genBlockHash(i) if err := w.Manager.SetSyncedTo(&waddrmgr.BlockStamp{int32(i), sha}); err != nil { return err } } return nil }
func (w *LibbitcoinWallet) Spend(amount int64, addr btc.Address, feeLevel bitcoin.FeeLevel) error { // Check for dust script, _ := txscript.PayToAddrScript(addr) if txrules.IsDustAmount(btc.Amount(amount), len(script), txrules.DefaultRelayFeePerKb) { return errors.New("Amount is below dust threshold") } var additionalPrevScripts map[wire.OutPoint][]byte var additionalKeysByAddress map[string]*btc.WIF // Create input source coinMap := w.gatherCoins() coins := make([]coinset.Coin, 0, len(coinMap)) for k := range coinMap { coins = append(coins, k) } inputSource := func(target btc.Amount) (total btc.Amount, inputs []*wire.TxIn, scripts [][]byte, err error) { // TODO: maybe change the coin selection algorithm? We're using min coins right now because // TODO: we don't know the number of confirmations on each coin without querying the libbitcoin server. coinSelector := coinset.MinNumberCoinSelector{MaxInputs: 10000, MinChangeAmount: btc.Amount(10000)} coins, err := coinSelector.CoinSelect(target, coins) if err != nil { return total, inputs, scripts, errors.New("insuffient funds") } additionalPrevScripts = make(map[wire.OutPoint][]byte) additionalKeysByAddress = make(map[string]*btc.WIF) for _, c := range coins.Coins() { total += c.Value() outpoint := wire.NewOutPoint(c.Hash(), c.Index()) in := wire.NewTxIn(outpoint, []byte{}) in.Sequence = 0 // Opt-in RBF so we can bump fees inputs = append(inputs, in) additionalPrevScripts[*outpoint] = c.PkScript() key := coinMap[c] addr, _ := btc.NewAddressPubKey(key.PublicKey().Key, w.params) pk, _ := btcec.PrivKeyFromBytes(btcec.S256(), key.Key) wif, _ := btc.NewWIF(pk, w.params, true) additionalKeysByAddress[addr.AddressPubKeyHash().EncodeAddress()] = wif } return total, inputs, scripts, nil } // Get the fee per kilobyte feePerKB := int64(w.getFeePerByte(feeLevel)) * 1000 // outputs out := wire.NewTxOut(amount, script) // Create change source changeSource := func() ([]byte, error) { addr := w.GetCurrentAddress(bitcoin.CHANGE) script, err := txscript.PayToAddrScript(addr) if err != nil { return []byte{}, err } return script, nil } authoredTx, err := txauthor.NewUnsignedTransaction([]*wire.TxOut{out}, btc.Amount(feePerKB), inputSource, changeSource) if err != nil { return err } // BIP 69 sorting txsort.InPlaceSort(authoredTx.Tx) // Sign tx getKey := txscript.KeyClosure(func(addr btc.Address) ( *btcec.PrivateKey, bool, error) { addrStr := addr.EncodeAddress() wif := additionalKeysByAddress[addrStr] return wif.PrivKey, wif.CompressPubKey, nil }) getScript := txscript.ScriptClosure(func( addr btc.Address) ([]byte, error) { return []byte{}, nil }) for i, txIn := range authoredTx.Tx.TxIn { prevOutScript := additionalPrevScripts[txIn.PreviousOutPoint] script, err := txscript.SignTxOutput(w.params, authoredTx.Tx, i, prevOutScript, txscript.SigHashAll, getKey, getScript, txIn.SignatureScript) if err != nil { return errors.New("Failed to sign transaction") } txIn.SignatureScript = script } // Broadcast tx to bitcoin network serializedTx := new(bytes.Buffer) authoredTx.Tx.Serialize(serializedTx) w.Client.Broadcast(serializedTx.Bytes(), func(i interface{}, err error) { if err == nil { log.Infof("Broadcast tx %s to bitcoin network\n", authoredTx.Tx.TxSha().String()) } else { log.Errorf("Failed to broadcast tx, reason: %s\n", err) } }) // Update the db w.ProcessTransaction(btc.NewTx(authoredTx.Tx), 0) return nil }
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, } 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, sigScript, scriptPkScript) if err != nil { t.Errorf("fully signed script invalid for "+ "%s: %v", msg, err) break } } } }
// newPoolHarness returns a new instance of a pool harness initialized with a // fake chain and a TxPool bound to it that is configured with a policy suitable // for testing. Also, the fake chain is populated with the returned spendable // outputs so the caller can easily create new valid transactions which build // off of it. func newPoolHarness(chainParams *chaincfg.Params) (*poolHarness, []spendableOutput, error) { // Use a hard coded key pair for deterministic results. keyBytes, err := hex.DecodeString("700868df1838811ffbdf918fb482c1f7e" + "ad62db4b97bd7012c23e726485e577d") if err != nil { return nil, nil, err } signKey, signPub := btcec.PrivKeyFromBytes(btcec.S256(), keyBytes) // Generate associated pay-to-script-hash address and resulting payment // script. pubKeyBytes := signPub.SerializeCompressed() payPubKeyAddr, err := btcutil.NewAddressPubKey(pubKeyBytes, chainParams) if err != nil { return nil, nil, err } payAddr := payPubKeyAddr.AddressPubKeyHash() pkScript, err := txscript.PayToAddrScript(payAddr) if err != nil { return nil, nil, err } // Create a new fake chain and harness bound to it. chain := &fakeChain{utxos: blockchain.NewUtxoViewpoint()} harness := poolHarness{ signKey: signKey, payAddr: payAddr, payScript: pkScript, chainParams: chainParams, chain: chain, txPool: New(&Config{ Policy: Policy{ DisableRelayPriority: true, FreeTxRelayLimit: 15.0, MaxOrphanTxs: 5, MaxOrphanTxSize: 1000, MaxSigOpsPerTx: blockchain.MaxSigOpsPerBlock / 5, MinRelayTxFee: 1000, // 1 Satoshi per byte MaxTxVersion: 1, }, ChainParams: chainParams, FetchUtxoView: chain.FetchUtxoView, BestHeight: chain.BestHeight, MedianTimePast: chain.MedianTimePast, CalcSequenceLock: chain.CalcSequenceLock, SigCache: nil, AddrIndex: nil, }), } // Create a single coinbase transaction and add it to the harness // chain's utxo set and set the harness chain height such that the // coinbase will mature in the next block. This ensures the txpool // accepts transactions which spend immature coinbases that will become // mature in the next block. numOutputs := uint32(1) outputs := make([]spendableOutput, 0, numOutputs) curHeight := harness.chain.BestHeight() coinbase, err := harness.CreateCoinbaseTx(curHeight+1, numOutputs) if err != nil { return nil, nil, err } harness.chain.utxos.AddTxOuts(coinbase, curHeight+1) for i := uint32(0); i < numOutputs; i++ { outputs = append(outputs, txOutToSpendableOut(coinbase, i)) } harness.chain.SetHeight(int32(chainParams.CoinbaseMaturity) + curHeight) harness.chain.SetMedianTimePast(time.Now()) return &harness, outputs, nil }