Add support for compressed pubkeys (used by default).
Wallets that include compressed pubkeys are no longer compatible with armory, however, imported wallets from armory (using uncompressed pubkeys) are still valid.
This commit is contained in:
parent
18fb993d0b
commit
f3408bad91
3 changed files with 163 additions and 79 deletions
|
@ -226,12 +226,16 @@ func (w *BtcWallet) txToPairs(pairs map[string]uint64, fee uint64, minconf int)
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get address key: %v", err)
|
||||
}
|
||||
ai, err := w.GetAddressInfo(addrstr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get address info: %v", err)
|
||||
}
|
||||
|
||||
// TODO(jrick): we want compressed pubkeys. Switch wallet to
|
||||
// generate addresses from the compressed key. This will break
|
||||
// armory wallet compat but oh well.
|
||||
sigscript, err := btcscript.SignatureScript(msgtx, i,
|
||||
ip.Subscript, btcscript.SigHashAll, privkey, false)
|
||||
ip.Subscript, btcscript.SigHashAll, privkey, ai.Compressed)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot create sigscript: %s", err)
|
||||
}
|
||||
|
|
234
wallet/wallet.go
234
wallet/wallet.go
|
@ -31,7 +31,6 @@ import (
|
|||
"github.com/conformal/btcec"
|
||||
"github.com/conformal/btcutil"
|
||||
"github.com/conformal/btcwire"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
|
@ -39,8 +38,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var _ = spew.Dump
|
||||
|
||||
const (
|
||||
// Length in bytes of KDF output.
|
||||
kdfOutputBytes = 32
|
||||
|
@ -128,20 +125,20 @@ func calcSha512(buf []byte) []byte {
|
|||
return calcHash(buf, sha512.New())
|
||||
}
|
||||
|
||||
// First byte in uncompressed pubKey field.
|
||||
const pubkeyUncompressed = 0x4
|
||||
|
||||
// pubkeyFromPrivkey creates a 65-byte encoded pubkey based on a
|
||||
// 32-byte privkey.
|
||||
//
|
||||
// TODO(jrick): this must be changed to a compressed pubkey.
|
||||
func pubkeyFromPrivkey(privkey []byte) (pubkey []byte) {
|
||||
// pubkeyFromPrivkey creates an encoded pubkey based on a
|
||||
// 32-byte privkey. The returned pubkey is 33 bytes if compressed,
|
||||
// or 65 bytes if uncompressed.
|
||||
func pubkeyFromPrivkey(privkey []byte, compress bool) (pubkey []byte) {
|
||||
x, y := btcec.S256().ScalarBaseMult(privkey)
|
||||
pub := (*btcec.PublicKey)(&ecdsa.PublicKey{
|
||||
Curve: btcec.S256(),
|
||||
X: x,
|
||||
Y: y,
|
||||
})
|
||||
|
||||
if compress {
|
||||
return pub.SerializeCompressed()
|
||||
}
|
||||
return pub.SerializeUncompressed()
|
||||
}
|
||||
|
||||
|
@ -195,22 +192,21 @@ func Key(passphrase []byte, params *kdfParameters) []byte {
|
|||
return masterKey
|
||||
}
|
||||
|
||||
// leftPad returns a new slice of length size. The contents of input are right
|
||||
// aligned in the new slice.
|
||||
func leftPad(input []byte, size int) (out []byte) {
|
||||
n := len(input)
|
||||
if n > size {
|
||||
n = size
|
||||
func pad(size int, b []byte) []byte {
|
||||
// Prevent a possible panic if the input exceeds the expected size.
|
||||
if len(b) > size {
|
||||
size = len(b)
|
||||
}
|
||||
out = make([]byte, size)
|
||||
copy(out[len(out)-n:], input)
|
||||
return
|
||||
|
||||
p := make([]byte, size)
|
||||
copy(p[size-len(b):], b)
|
||||
return p
|
||||
}
|
||||
|
||||
// ChainedPrivKey deterministically generates a new private key using a
|
||||
// previous address and chaincode. privkey and chaincode must be 32
|
||||
// bytes long, and pubkey may either be 65 bytes or nil (in which case it
|
||||
// is generated by the privkey).
|
||||
// bytes long, and pubkey may either be 33 bytes, 65 bytes or nil (in
|
||||
// which case it is generated by the privkey).
|
||||
func ChainedPrivKey(privkey, pubkey, chaincode []byte) ([]byte, error) {
|
||||
if len(privkey) != 32 {
|
||||
return nil, fmt.Errorf("invalid privkey length %d (must be 32)",
|
||||
|
@ -221,8 +217,8 @@ func ChainedPrivKey(privkey, pubkey, chaincode []byte) ([]byte, error) {
|
|||
len(chaincode))
|
||||
}
|
||||
if pubkey == nil {
|
||||
pubkey = pubkeyFromPrivkey(privkey)
|
||||
} else if len(pubkey) != 65 {
|
||||
pubkey = pubkeyFromPrivkey(privkey, true)
|
||||
} else if !(len(pubkey) == 65 || len(pubkey) == 33) {
|
||||
return nil, fmt.Errorf("invalid pubkey length %d", len(pubkey))
|
||||
}
|
||||
|
||||
|
@ -243,7 +239,7 @@ func ChainedPrivKey(privkey, pubkey, chaincode []byte) ([]byte, error) {
|
|||
|
||||
t := new(big.Int).Mul(chainXor, privint)
|
||||
b := t.Mod(t, btcec.S256().N).Bytes()
|
||||
return leftPad(b, 32), nil
|
||||
return pad(32, b), nil
|
||||
}
|
||||
|
||||
type varEntries []io.WriterTo
|
||||
|
@ -320,6 +316,10 @@ func (v *varEntries) ReadFrom(r io.Reader) (n int64, err error) {
|
|||
}
|
||||
}
|
||||
|
||||
type addressHashKey string
|
||||
type transactionHashKey string
|
||||
type comment []byte
|
||||
|
||||
// Wallet represents an btcd/Armory wallet in memory. It
|
||||
// implements the io.ReaderFrom and io.WriterTo interfaces to read
|
||||
// from and write to any type of byte streams, including files.
|
||||
|
@ -341,16 +341,16 @@ type Wallet struct {
|
|||
syncedBlockHeight int32
|
||||
syncedBlockHash btcwire.ShaHash
|
||||
|
||||
addrMap map[[ripemd160.Size]byte]*btcAddress
|
||||
addrCommentMap map[[ripemd160.Size]byte]*[]byte
|
||||
txCommentMap map[[sha256.Size]byte]*[]byte
|
||||
addrMap map[addressHashKey]*btcAddress
|
||||
addrCommentMap map[addressHashKey]comment
|
||||
txCommentMap map[transactionHashKey]comment
|
||||
|
||||
// These are not serialized
|
||||
key struct {
|
||||
sync.Mutex
|
||||
secret []byte
|
||||
}
|
||||
chainIdxMap map[int64]*[ripemd160.Size]byte
|
||||
chainIdxMap map[int64]addressHashKey
|
||||
lastChainIdx int64
|
||||
}
|
||||
|
||||
|
@ -409,22 +409,22 @@ func NewWallet(name, desc string, passphrase []byte, net btcwire.BitcoinNet, cre
|
|||
keyGenerator: *root,
|
||||
syncedBlockHeight: createdAt.Height,
|
||||
syncedBlockHash: createdAt.Hash,
|
||||
addrMap: make(map[[ripemd160.Size]byte]*btcAddress),
|
||||
addrCommentMap: make(map[[ripemd160.Size]byte]*[]byte),
|
||||
txCommentMap: make(map[[sha256.Size]byte]*[]byte),
|
||||
chainIdxMap: make(map[int64]*[ripemd160.Size]byte),
|
||||
addrMap: make(map[addressHashKey]*btcAddress),
|
||||
addrCommentMap: make(map[addressHashKey]comment),
|
||||
txCommentMap: make(map[transactionHashKey]comment),
|
||||
chainIdxMap: make(map[int64]addressHashKey),
|
||||
lastChainIdx: pregenerated - 1,
|
||||
}
|
||||
|
||||
// Add root address to maps.
|
||||
w.addrMap[w.keyGenerator.pubKeyHash] = &w.keyGenerator
|
||||
w.chainIdxMap[w.keyGenerator.chainIndex] = &w.keyGenerator.pubKeyHash
|
||||
w.addrMap[addressHashKey(w.keyGenerator.pubKeyHash[:])] = &w.keyGenerator
|
||||
w.chainIdxMap[w.keyGenerator.chainIndex] = addressHashKey(w.keyGenerator.pubKeyHash[:])
|
||||
|
||||
// Pre-generate 100 encrypted addresses and add to maps.
|
||||
addr := &w.keyGenerator
|
||||
cc := addr.chaincode[:]
|
||||
for i := 0; i < pregenerated; i++ {
|
||||
privkey, err := ChainedPrivKey(addr.privKeyCT, addr.pubKey[:], cc)
|
||||
privkey, err := ChainedPrivKey(addr.privKeyCT, addr.pubKey, cc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -435,9 +435,9 @@ func NewWallet(name, desc string, passphrase []byte, net btcwire.BitcoinNet, cre
|
|||
if err = newaddr.encrypt(aeskey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w.addrMap[newaddr.pubKeyHash] = newaddr
|
||||
w.addrMap[addressHashKey(newaddr.pubKeyHash[:])] = newaddr
|
||||
newaddr.chainIndex = addr.chainIndex + 1
|
||||
w.chainIdxMap[newaddr.chainIndex] = &newaddr.pubKeyHash
|
||||
w.chainIdxMap[newaddr.chainIndex] = addressHashKey(newaddr.pubKeyHash[:])
|
||||
copy(newaddr.chaincode[:], cc) // armory does this.. but why?
|
||||
addr = newaddr
|
||||
}
|
||||
|
@ -458,10 +458,10 @@ func (w *Wallet) Name() string {
|
|||
func (w *Wallet) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
var read int64
|
||||
|
||||
w.addrMap = make(map[[ripemd160.Size]byte]*btcAddress)
|
||||
w.addrCommentMap = make(map[[ripemd160.Size]byte]*[]byte)
|
||||
w.chainIdxMap = make(map[int64]*[ripemd160.Size]byte)
|
||||
w.txCommentMap = make(map[[sha256.Size]byte]*[]byte)
|
||||
w.addrMap = make(map[addressHashKey]*btcAddress)
|
||||
w.addrCommentMap = make(map[addressHashKey]comment)
|
||||
w.chainIdxMap = make(map[int64]addressHashKey)
|
||||
w.txCommentMap = make(map[transactionHashKey]comment)
|
||||
|
||||
var id [8]byte
|
||||
var appendedEntries varEntries
|
||||
|
@ -505,8 +505,8 @@ func (w *Wallet) ReadFrom(r io.Reader) (n int64, err error) {
|
|||
}
|
||||
|
||||
// Add root address to address map
|
||||
w.addrMap[w.keyGenerator.pubKeyHash] = &w.keyGenerator
|
||||
w.chainIdxMap[w.keyGenerator.chainIndex] = &w.keyGenerator.pubKeyHash
|
||||
w.addrMap[addressHashKey(w.keyGenerator.pubKeyHash[:])] = &w.keyGenerator
|
||||
w.chainIdxMap[w.keyGenerator.chainIndex] = addressHashKey(w.keyGenerator.pubKeyHash[:])
|
||||
|
||||
// Fill unserializied fields.
|
||||
wts := ([]io.WriterTo)(appendedEntries)
|
||||
|
@ -514,17 +514,17 @@ func (w *Wallet) ReadFrom(r io.Reader) (n int64, err error) {
|
|||
switch wt.(type) {
|
||||
case *addrEntry:
|
||||
e := wt.(*addrEntry)
|
||||
w.addrMap[e.pubKeyHash160] = &e.addr
|
||||
w.chainIdxMap[e.addr.chainIndex] = &e.pubKeyHash160
|
||||
w.addrMap[addressHashKey(e.pubKeyHash160[:])] = &e.addr
|
||||
w.chainIdxMap[e.addr.chainIndex] = addressHashKey(e.pubKeyHash160[:])
|
||||
if w.lastChainIdx < e.addr.chainIndex {
|
||||
w.lastChainIdx = e.addr.chainIndex
|
||||
}
|
||||
case *addrCommentEntry:
|
||||
e := wt.(*addrCommentEntry)
|
||||
w.addrCommentMap[e.pubKeyHash160] = &e.comment
|
||||
w.addrCommentMap[addressHashKey(e.pubKeyHash160[:])] = comment(e.comment)
|
||||
case *txCommentEntry:
|
||||
e := wt.(*txCommentEntry)
|
||||
w.txCommentMap[e.txHash] = &e.comment
|
||||
w.txCommentMap[transactionHashKey(e.txHash[:])] = comment(e.comment)
|
||||
default:
|
||||
return n, errors.New("unknown appended entry")
|
||||
}
|
||||
|
@ -539,25 +539,25 @@ func (w *Wallet) WriteTo(wtr io.Writer) (n int64, err error) {
|
|||
wts := make([]io.WriterTo, len(w.addrMap)-1)
|
||||
for hash, addr := range w.addrMap {
|
||||
if addr.chainIndex != -1 { // ignore root address
|
||||
e := &addrEntry{
|
||||
pubKeyHash160: hash,
|
||||
addr: *addr,
|
||||
e := addrEntry{
|
||||
addr: *addr,
|
||||
}
|
||||
wts[addr.chainIndex] = e
|
||||
copy(e.pubKeyHash160[:], []byte(hash))
|
||||
wts[addr.chainIndex] = &e
|
||||
}
|
||||
}
|
||||
for hash, comment := range w.addrCommentMap {
|
||||
e := &addrCommentEntry{
|
||||
pubKeyHash160: hash,
|
||||
comment: *comment,
|
||||
comment: []byte(comment),
|
||||
}
|
||||
copy(e.pubKeyHash160[:], []byte(hash))
|
||||
wts = append(wts, e)
|
||||
}
|
||||
for hash, comment := range w.txCommentMap {
|
||||
e := &txCommentEntry{
|
||||
txHash: hash,
|
||||
comment: *comment,
|
||||
comment: []byte(comment),
|
||||
}
|
||||
copy(e.txHash[:], []byte(hash))
|
||||
wts = append(wts, e)
|
||||
}
|
||||
appendedEntries := varEntries(wts)
|
||||
|
@ -663,7 +663,7 @@ func (w *Wallet) NextUnusedAddress() (string, error) {
|
|||
if err != nil {
|
||||
return "", errors.New("cannot find generated address")
|
||||
}
|
||||
addr := w.addrMap[*new160]
|
||||
addr := w.addrMap[new160]
|
||||
if addr == nil {
|
||||
return "", errors.New("cannot find generated address")
|
||||
}
|
||||
|
@ -687,10 +687,7 @@ func (w *Wallet) GetAddressKey(addr string) (key *ecdsa.PrivateKey, err error) {
|
|||
return nil, errors.New("wallet and address networks mismatch")
|
||||
}
|
||||
|
||||
addrHash := new([ripemd160.Size]byte)
|
||||
copy(addrHash[:], addr160)
|
||||
|
||||
btcaddr, ok := w.addrMap[*addrHash]
|
||||
btcaddr, ok := w.addrMap[addressHashKey(addr160)]
|
||||
if !ok {
|
||||
return nil, errors.New("address not in wallet")
|
||||
}
|
||||
|
@ -702,7 +699,7 @@ func (w *Wallet) GetAddressKey(addr string) (key *ecdsa.PrivateKey, err error) {
|
|||
return nil, errors.New("no private key for address")
|
||||
}
|
||||
|
||||
pubkey, err := btcec.ParsePubKey(btcaddr.pubKey[:], btcec.S256())
|
||||
pubkey, err := btcec.ParsePubKey(btcaddr.pubKey, btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -719,6 +716,26 @@ func (w *Wallet) GetAddressKey(addr string) (key *ecdsa.PrivateKey, err error) {
|
|||
return key, nil
|
||||
}
|
||||
|
||||
func (w *Wallet) GetAddressInfo(addr string) (*AddressInfo, error) {
|
||||
addr160, net, err := btcutil.DecodeAddress(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch {
|
||||
case net == btcutil.MainNetAddr && w.net != btcwire.MainNet:
|
||||
fallthrough
|
||||
case net == btcutil.TestNetAddr && w.net != btcwire.TestNet:
|
||||
return nil, errors.New("wallet and address networks mismatch")
|
||||
}
|
||||
|
||||
btcaddr, ok := w.addrMap[addressHashKey(addr160)]
|
||||
if !ok {
|
||||
return nil, errors.New("address not in wallet")
|
||||
}
|
||||
|
||||
return btcaddr.info(w.net)
|
||||
}
|
||||
|
||||
// Net returns the bitcoin network identifier for this wallet.
|
||||
func (w *Wallet) Net() btcwire.BitcoinNet {
|
||||
return w.net
|
||||
|
@ -747,9 +764,9 @@ func (w *Wallet) CreatedAt() int32 {
|
|||
return w.keyGenerator.firstBlock
|
||||
}
|
||||
|
||||
func (w *Wallet) addr160ForIdx(idx int64) (*[ripemd160.Size]byte, error) {
|
||||
func (w *Wallet) addr160ForIdx(idx int64) (addressHashKey, error) {
|
||||
if idx > w.lastChainIdx {
|
||||
return nil, errors.New("chain index out of range")
|
||||
return "", errors.New("chain index out of range")
|
||||
}
|
||||
return w.chainIdxMap[idx], nil
|
||||
}
|
||||
|
@ -759,6 +776,7 @@ func (w *Wallet) addr160ForIdx(idx int64) (*[ripemd160.Size]byte, error) {
|
|||
type AddressInfo struct {
|
||||
Address string
|
||||
FirstBlock int32
|
||||
Compressed bool
|
||||
}
|
||||
|
||||
// GetActiveAddresses returns all wallet addresses that have been
|
||||
|
@ -771,7 +789,7 @@ func (w *Wallet) GetActiveAddresses() []*AddressInfo {
|
|||
if err != nil {
|
||||
return addrs
|
||||
}
|
||||
addr := w.addrMap[*addr160]
|
||||
addr := w.addrMap[addr160]
|
||||
info, err := addr.info(w.Net())
|
||||
if err == nil {
|
||||
addrs = append(addrs, info)
|
||||
|
@ -805,9 +823,11 @@ func (wf *walletFlags) WriteTo(w io.Writer) (n int64, err error) {
|
|||
}
|
||||
|
||||
type addrFlags struct {
|
||||
hasPrivKey bool
|
||||
hasPubKey bool
|
||||
encrypted bool
|
||||
hasPrivKey bool
|
||||
hasPubKey bool
|
||||
encrypted bool
|
||||
createPrivKeyNextUnlock bool // unimplemented in btcwallet
|
||||
compressed bool
|
||||
}
|
||||
|
||||
func (af *addrFlags) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
|
@ -829,6 +849,12 @@ func (af *addrFlags) ReadFrom(r io.Reader) (n int64, err error) {
|
|||
return n, errors.New("address flag specifies unencrypted address")
|
||||
}
|
||||
af.encrypted = true
|
||||
if b[0]&(1<<3) != 0 {
|
||||
af.createPrivKeyNextUnlock = true
|
||||
}
|
||||
if b[0]&(1<<4) != 0 {
|
||||
af.compressed = true
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
@ -846,6 +872,12 @@ func (af *addrFlags) WriteTo(w io.Writer) (n int64, err error) {
|
|||
return n, errors.New("address must be encrypted")
|
||||
}
|
||||
b[0] |= 1 << 2
|
||||
if af.createPrivKeyNextUnlock {
|
||||
b[0] |= 1 << 3
|
||||
}
|
||||
if af.compressed {
|
||||
b[0] |= 1 << 4
|
||||
}
|
||||
|
||||
return binaryWrite(w, binary.LittleEndian, b)
|
||||
}
|
||||
|
@ -858,7 +890,7 @@ type btcAddress struct {
|
|||
chainDepth int64 // currently unused (will use when extending a locked wallet)
|
||||
initVector [16]byte
|
||||
privKey [32]byte
|
||||
pubKey [65]byte
|
||||
pubKey publicKey
|
||||
firstSeen int64
|
||||
lastSeen int64
|
||||
firstBlock int32
|
||||
|
@ -866,6 +898,54 @@ type btcAddress struct {
|
|||
privKeyCT []byte // non-nil if unlocked.
|
||||
}
|
||||
|
||||
const (
|
||||
pubkeyCompressed byte = 0x2
|
||||
pubkeyUncompressed byte = 0x4
|
||||
)
|
||||
|
||||
type publicKey []byte
|
||||
|
||||
func (k *publicKey) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
var read int64
|
||||
var format byte
|
||||
read, err = binaryRead(r, binary.LittleEndian, &format)
|
||||
if err != nil {
|
||||
return n + read, err
|
||||
}
|
||||
n += read
|
||||
|
||||
// Remove the oddness from the format
|
||||
noodd := format
|
||||
noodd &= ^byte(0x1)
|
||||
|
||||
var s []byte
|
||||
switch noodd {
|
||||
case pubkeyUncompressed:
|
||||
// Read the remaining 64 bytes.
|
||||
s = make([]byte, 64)
|
||||
|
||||
case pubkeyCompressed:
|
||||
// Read the remaining 32 bytes.
|
||||
s = make([]byte, 32)
|
||||
|
||||
default:
|
||||
return n, errors.New("unrecognized pubkey format")
|
||||
}
|
||||
|
||||
read, err = binaryRead(r, binary.LittleEndian, &s)
|
||||
if err != nil {
|
||||
return n + read, err
|
||||
}
|
||||
n += read
|
||||
|
||||
*k = append([]byte{format}, s...)
|
||||
return
|
||||
}
|
||||
|
||||
func (k *publicKey) WriteTo(w io.Writer) (n int64, err error) {
|
||||
return binaryWrite(w, binary.LittleEndian, []byte(*k))
|
||||
}
|
||||
|
||||
// newBtcAddress initializes and returns a new address. privkey must
|
||||
// be 32 bytes. iv must be 16 bytes, or nil (in which case it is
|
||||
// randomly generated).
|
||||
|
@ -885,14 +965,14 @@ func newBtcAddress(privkey, iv []byte, bs *BlockStamp) (addr *btcAddress, err er
|
|||
flags: addrFlags{
|
||||
hasPrivKey: true,
|
||||
hasPubKey: true,
|
||||
compressed: true,
|
||||
},
|
||||
firstSeen: time.Now().Unix(),
|
||||
firstBlock: bs.Height,
|
||||
}
|
||||
copy(addr.initVector[:], iv)
|
||||
pub := pubkeyFromPrivkey(privkey)
|
||||
copy(addr.pubKey[:], pub)
|
||||
copy(addr.pubKeyHash[:], calcHash160(pub))
|
||||
addr.pubKey = pubkeyFromPrivkey(privkey, true)
|
||||
copy(addr.pubKeyHash[:], calcHash160(addr.pubKey))
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
@ -969,7 +1049,7 @@ func (a *btcAddress) ReadFrom(r io.Reader) (n int64, err error) {
|
|||
{a.chaincode[:], chkChaincode},
|
||||
{a.initVector[:], chkInitVector},
|
||||
{a.privKey[:], chkPrivKey},
|
||||
{a.pubKey[:], chkPubKey},
|
||||
{a.pubKey, chkPubKey},
|
||||
}
|
||||
for i := range checks {
|
||||
if err = verifyAndFix(checks[i].data, checks[i].chk); err != nil {
|
||||
|
@ -997,7 +1077,7 @@ func (a *btcAddress) WriteTo(w io.Writer) (n int64, err error) {
|
|||
&a.privKey,
|
||||
walletHash(a.privKey[:]),
|
||||
&a.pubKey,
|
||||
walletHash(a.pubKey[:]),
|
||||
walletHash(a.pubKey),
|
||||
&a.firstSeen,
|
||||
&a.lastSeen,
|
||||
&a.firstBlock,
|
||||
|
@ -1067,7 +1147,7 @@ func (a *btcAddress) unlock(key []byte) error {
|
|||
ct := make([]byte, 32)
|
||||
aesDecrypter.XORKeyStream(ct, a.privKey[:])
|
||||
|
||||
pubKey, err := btcec.ParsePubKey(a.pubKey[:], btcec.S256())
|
||||
pubKey, err := btcec.ParsePubKey(a.pubKey, btcec.S256())
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot parse pubkey: %s", err)
|
||||
}
|
||||
|
@ -1102,6 +1182,7 @@ func (a *btcAddress) info(net btcwire.BitcoinNet) (*AddressInfo, error) {
|
|||
return &AddressInfo{
|
||||
Address: address,
|
||||
FirstBlock: a.firstBlock,
|
||||
Compressed: a.flags.compressed,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -1369,8 +1450,7 @@ func (e *txCommentEntry) ReadFrom(r io.Reader) (n int64, err error) {
|
|||
return n + read, err
|
||||
}
|
||||
|
||||
type deletedEntry struct {
|
||||
}
|
||||
type deletedEntry struct{}
|
||||
|
||||
func (e *deletedEntry) ReadFrom(r io.Reader) (n int64, err error) {
|
||||
var read int64
|
||||
|
|
|
@ -36,7 +36,7 @@ func TestBtcAddressSerializer(t *testing.T) {
|
|||
key := Key([]byte("banana"), kdfp)
|
||||
privKey := make([]byte, 32)
|
||||
rand.Read(privKey)
|
||||
addr, err := newBtcAddress(privKey, nil)
|
||||
addr, err := newBtcAddress(privKey, nil, &BlockStamp{})
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
return
|
||||
|
|
Loading…
Reference in a new issue