Updates for btcutil WIF API changes.

This commit is contained in:
Josh Rickmar 2014-05-21 17:50:47 -05:00
parent 813e1b19e9
commit 987dc8f1c4
4 changed files with 51 additions and 65 deletions

View file

@ -307,14 +307,14 @@ func (a *Account) DumpPrivKeys() ([]string, error) {
if !ok { if !ok {
continue continue
} }
encKey, err := pka.ExportPrivKey() wif, err := pka.ExportPrivKey()
if err != nil { if err != nil {
// It would be nice to zero out the array here. However, // It would be nice to zero out the array here. However,
// since strings in go are immutable, and we have no // since strings in go are immutable, and we have no
// control over the caller I don't think we can. :( // control over the caller I don't think we can. :(
return nil, err return nil, err
} }
privkeys = append(privkeys, encKey) privkeys = append(privkeys, wif.String())
} }
return privkeys, nil return privkeys, nil
@ -334,16 +334,20 @@ func (a *Account) DumpWIFPrivateKey(addr btcutil.Address) (string, error) {
return "", fmt.Errorf("address %s is not a key type", addr) return "", fmt.Errorf("address %s is not a key type", addr)
} }
return pka.ExportPrivKey() wif, err := pka.ExportPrivKey()
if err != nil {
return "", err
}
return wif.String(), nil
} }
// ImportPrivateKey imports a private key to the account's wallet and // ImportPrivateKey imports a private key to the account's wallet and
// writes the new wallet to disk. // writes the new wallet to disk.
func (a *Account) ImportPrivateKey(pk []byte, compressed bool, func (a *Account) ImportPrivateKey(wif *btcutil.WIF, bs *wallet.BlockStamp,
bs *wallet.BlockStamp, rescan bool) (string, error) { rescan bool) (string, error) {
// Attempt to import private key into wallet. // Attempt to import private key into wallet.
addr, err := a.Wallet.ImportPrivateKey(pk, compressed, bs) addr, err := a.Wallet.ImportPrivateKey(wif, bs)
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -772,14 +772,14 @@ func ImportPrivKey(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
return nil, &e return nil, &e
} }
pk, net, compressed, err := btcutil.DecodePrivateKey(cmd.PrivKey) wif, err := btcutil.DecodeWIF(cmd.PrivKey)
if err != nil || net != a.Net() { if err != nil || !wif.IsForNet(a.Net()) {
return nil, &btcjson.ErrInvalidAddressOrKey return nil, &btcjson.ErrInvalidAddressOrKey
} }
// Import the private key, handling any errors. // Import the private key, handling any errors.
bs := &wallet.BlockStamp{} bs := &wallet.BlockStamp{}
switch _, err := a.ImportPrivateKey(pk, compressed, bs, cmd.Rescan); err { switch _, err := a.ImportPrivateKey(wif, bs, cmd.Rescan); err {
case nil: case nil:
// If the import was successful, reply with nil. // If the import was successful, reply with nil.
return nil, nil return nil, nil
@ -1742,12 +1742,6 @@ type pendingTx struct {
inputs []uint32 // list of inputs that care about this tx. inputs []uint32 // list of inputs that care about this tx.
} }
// keyInfo is used to store provided keys in SignRawTransaction.
type keyInfo struct {
key *ecdsa.PrivateKey
compressed bool
}
// SignRawTransaction handles the signrawtransaction command. // SignRawTransaction handles the signrawtransaction command.
func SignRawTransaction(icmd btcjson.Cmd) (interface{}, *btcjson.Error) { func SignRawTransaction(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
cmd, ok := icmd.(*btcjson.SignRawTransactionCmd) cmd, ok := icmd.(*btcjson.SignRawTransactionCmd)
@ -1854,13 +1848,12 @@ func SignRawTransaction(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
// Parse list of private keys, if present. If there are any keys here // Parse list of private keys, if present. If there are any keys here
// they are the keys that we may use for signing. If empty we will // they are the keys that we may use for signing. If empty we will
// use any keys known to us already. // use any keys known to us already.
var keys map[string]keyInfo var keys map[string]*btcutil.WIF
if len(cmd.PrivKeys) != 0 { if len(cmd.PrivKeys) != 0 {
keys = make(map[string]keyInfo) keys = make(map[string]*btcutil.WIF)
for _, key := range cmd.PrivKeys { for _, key := range cmd.PrivKeys {
key, net, compressed, err := wif, err := btcutil.DecodeWIF(key)
btcutil.DecodePrivateKey(key)
if err != nil { if err != nil {
return nil, &btcjson.Error{ return nil, &btcjson.Error{
Code: btcjson.ErrDeserialization.Code, Code: btcjson.ErrDeserialization.Code,
@ -1868,7 +1861,7 @@ func SignRawTransaction(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
} }
} }
if net != cfg.Net() { if !wif.IsForNet(cfg.Net()) {
return nil, &btcjson.Error{ return nil, &btcjson.Error{
Code: btcjson.ErrDeserialization.Code, Code: btcjson.ErrDeserialization.Code,
Message: "key network doesn't match " + Message: "key network doesn't match " +
@ -1876,35 +1869,15 @@ func SignRawTransaction(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
} }
} }
privk, pubk := btcec.PrivKeyFromBytes(btcec.S256(), addr, err := btcutil.NewAddressPubKey(wif.SerializePubKey(),
key) cfg.Net())
if err != nil {
var addr btcutil.Address return nil, &btcjson.Error{
if compressed { Code: btcjson.ErrDeserialization.Code,
pkc := pubk.SerializeCompressed() Message: err.Error(),
addr, err = btcutil.NewAddressPubKey(pkc,
cfg.Net())
if err != nil {
return nil, &btcjson.Error{
Code: btcjson.ErrDeserialization.Code,
Message: err.Error(),
}
}
} else {
pku := pubk.SerializeUncompressed()
addr, err = btcutil.NewAddressPubKey(pku,
cfg.Net())
if err != nil {
return nil, &btcjson.Error{
Code: btcjson.ErrDeserialization.Code,
Message: err.Error(),
}
} }
} }
keys[addr.EncodeAddress()] = keyInfo{ keys[addr.EncodeAddress()] = wif
key: privk.ToECDSA(),
compressed: compressed,
}
} }
} }
@ -1984,12 +1957,12 @@ func SignRawTransaction(icmd btcjson.Cmd) (interface{}, *btcjson.Error) {
getKey := btcscript.KeyClosure(func(addr btcutil.Address) ( getKey := btcscript.KeyClosure(func(addr btcutil.Address) (
*ecdsa.PrivateKey, bool, error) { *ecdsa.PrivateKey, bool, error) {
if len(keys) != 0 { if len(keys) != 0 {
info, ok := keys[addr.EncodeAddress()] wif, ok := keys[addr.EncodeAddress()]
if !ok { if !ok {
return nil, false, return nil, false,
errors.New("no key for address") errors.New("no key for address")
} }
return info.key, info.compressed, nil return wif.PrivKey.ToECDSA(), wif.CompressPubKey, nil
} }
address, err := AcctMgr.Address(addr) address, err := AcctMgr.Address(addr)
if err != nil { if err != nil {

View file

@ -1333,16 +1333,17 @@ func (w *Wallet) SetBetterEarliestBlockHeight(height int32) {
} }
} }
// ImportPrivateKey creates a new encrypted btcAddress with a // ImportPrivateKey imports a WIF private key into the keystore. The imported
// user-provided private key and adds it to the wallet. // address is created using either a compressed or uncompressed serialized
func (w *Wallet) ImportPrivateKey(privkey []byte, compressed bool, bs *BlockStamp) (btcutil.Address, error) { // public key, depending on the CompressPubKey bool of the WIF.
func (w *Wallet) ImportPrivateKey(wif *btcutil.WIF, bs *BlockStamp) (btcutil.Address, error) {
if w.flags.watchingOnly { if w.flags.watchingOnly {
return nil, ErrWalletIsWatchingOnly return nil, ErrWalletIsWatchingOnly
} }
// First, must check that the key being imported will not result // First, must check that the key being imported will not result
// in a duplicate address. // in a duplicate address.
pkh := btcutil.Hash160(pubkeyFromPrivkey(privkey, compressed)) pkh := btcutil.Hash160(wif.SerializePubKey())
if _, ok := w.addrMap[addressKey(pkh)]; ok { if _, ok := w.addrMap[addressKey(pkh)]; ok {
return nil, ErrDuplicate return nil, ErrDuplicate
} }
@ -1353,7 +1354,8 @@ func (w *Wallet) ImportPrivateKey(privkey []byte, compressed bool, bs *BlockStam
} }
// Create new address with this private key. // Create new address with this private key.
btcaddr, err := newBtcAddress(w, privkey, nil, bs, compressed) privKey := wif.PrivKey.Serialize()
btcaddr, err := newBtcAddress(w, privKey, nil, bs, wif.CompressPubKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -2067,8 +2069,8 @@ type PubKeyAddress interface {
// It can fail if the wallet is watching only, the wallet is locked, // It can fail if the wallet is watching only, the wallet is locked,
// or the address doesn't have any keys. // or the address doesn't have any keys.
PrivKey() (*ecdsa.PrivateKey, error) PrivKey() (*ecdsa.PrivateKey, error)
// ExportPrivKey exports the private key in WIF format as a string. // ExportPrivKey exports the WIF private key.
ExportPrivKey() (string, error) ExportPrivKey() (*btcutil.WIF, error)
} }
// newBtcAddress initializes and returns a new address. privkey must // newBtcAddress initializes and returns a new address. privkey must
@ -2523,16 +2525,14 @@ func (a *btcAddress) PrivKey() (*ecdsa.PrivateKey, error) {
}, nil }, nil
} }
// ExportPrivKey exports the private key in WIF format as a string. Implementing // ExportPrivKey exports the private key as a WIF for encoding as a string
// PubKeyAddress. // in the Wallet Import Formt.
func (a *btcAddress) ExportPrivKey() (string, error) { func (a *btcAddress) ExportPrivKey() (*btcutil.WIF, error) {
pk, err := a.PrivKey() pk, err := a.PrivKey()
if err != nil { if err != nil {
return "", err return nil, err
} }
return btcutil.NewWIF((*btcec.PrivateKey)(pk), a.wallet.Net(), a.Compressed())
return btcutil.EncodePrivateKey(pad(32, pk.D.Bytes()),
a.wallet.Net(), a.Compressed())
} }
// watchingCopy creates a copy of an address without a private key. // watchingCopy creates a copy of an address without a private key.

View file

@ -714,7 +714,12 @@ func TestWatchingWalletExport(t *testing.T) {
t.Errorf("Nonsensical func ExportWatchingWallet returned no or incorrect error: %v", err) t.Errorf("Nonsensical func ExportWatchingWallet returned no or incorrect error: %v", err)
return return
} }
if _, err := ww.ImportPrivateKey(make([]byte, 32), true, createdAt); err != ErrWalletIsWatchingOnly { pk, _ := btcec.PrivKeyFromBytes(btcec.S256(), make([]byte, 32))
wif, err := btcutil.NewWIF(pk, btcwire.MainNet, true)
if err != nil {
t.Fatal(err)
}
if _, err := ww.ImportPrivateKey(wif, createdAt); err != ErrWalletIsWatchingOnly {
t.Errorf("Nonsensical func ImportPrivateKey returned no or incorrect error: %v", err) t.Errorf("Nonsensical func ImportPrivateKey returned no or incorrect error: %v", err)
return return
} }
@ -754,9 +759,13 @@ func TestImportPrivateKey(t *testing.T) {
} }
// import priv key // import priv key
wif, err := btcutil.NewWIF((*btcec.PrivateKey)(pk), btcwire.MainNet, false)
if err != nil {
t.Fatal(err)
}
importHeight := int32(50) importHeight := int32(50)
importedAt := &BlockStamp{Height: importHeight} importedAt := &BlockStamp{Height: importHeight}
address, err := w.ImportPrivateKey(pad(32, pk.D.Bytes()), false, importedAt) address, err := w.ImportPrivateKey(wif, importedAt)
if err != nil { if err != nil {
t.Error("importing private key: " + err.Error()) t.Error("importing private key: " + err.Error())
return return