Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import external watch-only addresses #204

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

tuxcanfly
Copy link
Contributor

Added RPC commands to import external watch-only addresses both with and without pubkeys. WIP on finishing test coverage and docs.

Refs #192

@tuxcanfly tuxcanfly force-pushed the import-address branch 3 times, most recently from 1a1eb59 to 7f91bd7 Compare March 7, 2015 13:00
@@ -549,14 +581,14 @@ func putNumAccounts(tx walletdb.Tx, numAccounts uint32) error {
// the common parts.
func deserializeAddressRow(addressID, serializedAddress []byte) (*dbAddressRow, error) {
// The serialized address format is:
// <addrType><account><addedTime><syncStatus><rawdata>
// <addrType><account><addedTime><syncStatus><watchingOnly><rawdata>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a watching only flag as well as an adtWatching address type? It would be ideal to avoid changing this format because, if you do, you'll have to write upgrade code and modify every existing address in the database which I think we really don't want to do.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After thinking about it some more, I think having the extra field is more flexible. However, at the moment there is some redundancy with the adtWatching type that doesn't quite feel right.

If we look at it from the perspective of what a user will need to do for watching-only purposes:

  • Import BIP0032 public key chains
  • Import "loose" public keys (those which are not a part of BIP0032 key chain)
  • Import the hash160 associated with a pay-to-script-hash

Considering that, the first case is an adtChain with a watching-only flag, the second is an adtImport with a watching-only flag, and the third is an adtScript with a watching-only flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to only use the watchingOnly flag and removed adtWatching type. Importing "loose" public keys and P2SH hashes works using the importpubkey and importaddress commands. Now working on importing public key chains.

Now working on importing BIP0032 public key chains.

internal bool
compressed bool
used bool
publicAddress
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the purpose of splitting this out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought it might be logical to separate the structs for loose vs keychain addrs for future e.g if we wanted to add a method specific to loose addrs.

@davecgh
Copy link
Member

davecgh commented Mar 23, 2015

Since the format of existing addresses in the db is being changed here, the db version needs to be bumped and it needs upgrade code to handle the new serialization. You should be able to do it without requiring the private passphrase by specifically targetting the new field offset.

@tuxcanfly tuxcanfly force-pushed the import-address branch 3 times, most recently from 348af4d to c634317 Compare March 23, 2015 18:52
@tuxcanfly
Copy link
Contributor Author

Yeah, we will need a upgrade to initialize the watchingOnly field, I guess it can be inferred by checking that pubkey is not nil.

@tuxcanfly tuxcanfly force-pushed the import-address branch 2 times, most recently from 3a3c1eb to b0e29ec Compare March 24, 2015 14:00
@tuxcanfly
Copy link
Contributor Author

@davecgh Added upgrade path, addressed items reviewed above. Tested that we support importing pubkeys, p2pkh and p2sh addresses now.

@tuxcanfly tuxcanfly force-pushed the import-address branch 3 times, most recently from 0d839f6 to 4f843cb Compare March 25, 2015 16:12
@@ -902,35 +927,48 @@ func deserializeImportedAddress(row *dbAddressRow) (*dbImportedAddressRow, error
dbAddressRow: *row,
}

pubLen := binary.LittleEndian.Uint32(row.rawData[0:4])
pkHashLen := binary.LittleEndian.Uint32(row.rawData[0:4])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please stick with the existing offset approach. There is less chance of error when updating the code with that approach.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reminder to take care of this. I don't particularly care for offset variables, but to be consistent with the rest of the package, it should create the offset var first, and then slice between [offset:offset+fieldlen].

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are superior to 4+4+8+len(thing)+x+y+len(z.foo). And then each field has to repeat that from the last, etc.

EDIT: The recent conversation from the ppcd folks having to deal with all those magic offsets everywhere is a prime example of how they help as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With variable-sized data I agree

@tuxcanfly tuxcanfly force-pushed the import-address branch 3 times, most recently from 8ea8bed to 8847744 Compare May 1, 2015 20:07
@@ -62,11 +65,11 @@ type ManagedPubKeyAddress interface {
ManagedAddress

// PubKey returns the public key associated with the address.
PubKey() *btcec.PublicKey
PubKey() (*btcec.PublicKey, error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should change the signature not to introduce an error (for the not-exists case) but to return the public key and a boolean for whether the pubkey is compressed or not. Since watching addresses can be imported without the pubkey, not having the pubkey exist is now a totally valid state, and the caller must determine whether not existing is an error or not.

For the not-exists case, we would either need another (a second) bool return, or return a nil pubkey. I'm leaning towards the additional return to avoid situations where the caller forgets to check for the nil case, since the Go type system isn't strong enough to enforce this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, we already have a db field called compressed on managedAddress which we are using for determining whether the pubkey is compressed or not. If we change the signature we might want to remove that field to avoid ambiguity.

Also, the PubKey signature is consistent with PrivKey which returns ErrWatchingOnly when private key is not available.

}

var compressed bool
switch n := len(pubKeyBytes); n {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole switch can be removed. The correct length is checked by ParsePubKey below. All you would need to pass to ImportPubKey is the bool len(pubKeyBytes) == btcec.PubKeyBytesLenCompressed.

I kind of think that the btcec type should save whether the pubkey was compressed or not, but oh well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, removed the swtich and simplified this.

@tuxcanfly tuxcanfly force-pushed the import-address branch 2 times, most recently from 1019144 to 7b3e16f Compare May 5, 2015 19:07
@tuxcanfly
Copy link
Contributor Author

OK, updated PubKey to return compressed as well as ok. Refactored related methods accordingly.

@tuxcanfly tuxcanfly force-pushed the import-address branch 2 times, most recently from c1be9db to e670502 Compare May 14, 2015 08:12
@jrick
Copy link
Member

jrick commented May 14, 2015

The changed methods need better documentation to describe what all the return values are. Either the interface definition can use named returns to document the values, or comments should be added to describe what each bool means.

@tuxcanfly
Copy link
Contributor Author

Thanks, using named returns in the interface and also updated docs about the return values.

In 6ee1f9b, Manager.Address was updated to convert PK addr to PKH addr
so that the db is always keyed by script hash. This commit fixes
ImportAddress to use the same key while fetching the addr from the db.
@ghost
Copy link

ghost commented Aug 27, 2016

What's the status on this? The corresponding PRs btcsuite/btcd#279 and btcsuite/btcjson#41 were merged a long time ago.

Did #192 "supersede" this PR?

@jrick
Copy link
Member

jrick commented Aug 29, 2016

There are several conflicts preventing this from being merged. There will be even more conflicts if decred/dcrwallet#315 is backported to btcwallet.

We're also moving away from the idea of importing keys into a HD wallet, both to simplify our code and to make the entire wallet recoverable from just the seed. Would need a discussion about if we still even want this feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants