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

[Rough] Things to work on (Roadmap?) #1437

Open
junderw opened this issue Jul 19, 2019 · 11 comments
Open

[Rough] Things to work on (Roadmap?) #1437

junderw opened this issue Jul 19, 2019 · 11 comments

Comments

@junderw
Copy link
Member

junderw commented Jul 19, 2019

  1. Dependency clean up - move bitcoinjs packages to mono-repo style, and try to reduce the number of non-bitcoinjs/cryptocoinjs dependencies.
  2. Wallet example project - Create a nice Wallet library that is simple and abstract enough to take the concepts and fit their usecase... thinking of a Wallet class, a PsbtCreator class, and UtxoGetter class. The PsbtCreator class will use a UtxoGetter object to help create etc... just ideas
  3. Async Hardware Wallet library - Now that PSBT is merged, implementing a versatile Async HD based signing class will be great... we send in a PSBT to get signed, and it will pass it along once HW wallets support it, or we will parse the info out and send it to the HW interface.

Any other ideas for future projects are welcome.

@tarun1475
Copy link

Hi ,
I am willing to develop a wallet example project and have an experience of using bitcoinjs lib except psbt functions which are recently added..
Tell me the next steps.

@junderw
Copy link
Member Author

junderw commented Aug 1, 2019

@tarun1475

Sure.

  1. Create a new repo under your account.
  2. Create an issue here on bitcoinjs-lib and call it something like "Create Wallet example project" and in the issue body post a link to your repo.
  3. Create the repo. Any questions you need, ask in the issue you created in 2.

As for advice:

  1. I was thinking maybe there would be a Wallet class, the constructor would accept a bip32 object. Then a static method could do a fromBIP39 where we can generate the wallet from BIP39... The Wallet object imo shouldn't hold the phrase, but it should hold the root bip32 node.
  2. The Wallet class should differentiate if the bip32 node it was given has private key or not. (via isNeutered()) and if not, any send methods (ie. sendMany sendCoin etc) should throw an error.
  3. There should be a few other classes, UtxoGetter, which had methods of getting Utxos for a scriptPubkey (or address).. PsbtCreator which should contain a UtxoGetter allowing it to create the Psbt to sign. This can be done without private keys.
  4. In general, the base implementation should use Bitcoin Core where possible...

Once you get an issue up and running you can ask some more questions there.

Thanks.

@tarun1475
Copy link

Sounds great.

I have few more questions i will ask in the issue then.
Thanks.

@dakk
Copy link

dakk commented Sep 2, 2019

Regarding "Async Hardware Wallet library", I'm interested in implementing it for the Ledger HW wallet since I'm already using ledger nano with psbt in my project.
The main problem is that LedgerJS's sign function needs the whole transaction for every input being signed (not just for non witness inputs) so atm it's impossible to sign a segwit input only with data contained in pbst transaction.

(I asked them if they planned to support bip174 LedgerHQ/ledgerjs#399)

@junderw
Copy link
Member Author

junderw commented Sep 2, 2019

I added support for nonWitnessUtxo with segwit. (it just ignores the extra info, since the witnessUtxo is contained within the nonWitnessUtxo)

So while not exactly the intended spec, you can use nonWitnessUtxo for all inputs in this library, and the segwit detection is done by matching scripts.

Most other PSBT implementations don't do this though. So they should eventually support it.

@dakk
Copy link

dakk commented Sep 3, 2019

Great, even if it is just a patch waiting for ledgerjs implementing it. Another thing I need is a way to extract the unsigned transaction hex like I did with

txb.buildIncomplete().toHex()

since ledger.signP2SH needs serialized transaction outputs: atm i'm doing as follow:

const outshex = btc.serializeTransactionOutputs(btc.splitTransaction((txb as any).__CACHE.__TX.toHex(), true)).toString('hex');

which is not a clean way. Maybe could be useful an additional extractTransactionIncomplete which ignores non-finalized inputs?

@junderw
Copy link
Member Author

junderw commented Sep 3, 2019

hmmm.... tbh, I think the whole point of PSBT is that we have a format to encode Partially Signed Bitcoin Transactions...

So having an extract incomplete method seems antithetical to the idea of PSBT.

Your hack is OK for now. Let's wait until Ledger supports PSBT to fix it. :-D

@dakk
Copy link

dakk commented Sep 3, 2019

yea, I agree with you, let's wait :)
I post here the code I'm using to sign p2wsh and p2sh-p2wsh with the ledger, maybe could be useful for other users while waiting:

TransportU2F.create().then(transport => {
	const btc = new Btc(transport);

	/* Download utxo transaction raw */
	this.rawTransactions(options.utxos.map(utxo => utxo.tx)).then(transactions => {
		/* Create inputs and serialized outputs */
		const inputs = options.utxos.map(utxo => [
			btc.splitTransaction(transactions[utxo.tx], bitcoinjs.Transaction.fromHex(transactions[utxo.tx]).hasWitnesses()),
			utxo.n,
			walletScripts.p2wsh.redeem.output.toString('hex'),
		]);
		const paths = inputs.map(i => this.signPath);
		const txb = bitcoinjs.Psbt.fromHex(txhex, { network: this.config.network });
		const outshex = btc.serializeTransactionOutputs(btc.splitTransaction((txb as any).__CACHE.__TX.toHex(), true)).toString('hex');

		btc.signP2SHTransaction(inputs, paths, outshex, 0/*tx.locktime*/, 1 /*SIGHASH_ALL*/, segwit, 2).then(signatures => {
			/* Inject signatures */
			for (let j = 0; j < txb.inputCount; j++) {
				txb.signInput(j, {
					network: this.config.network,
					publicKey: toByteArray(publickey),
					sign: (hash) => bitcoinjs.script.signature.decode(toByteArray(signatures[j])).signature
				} as bitcoinjs.ECPairInterface);
			}

			/* Build the transaction */
			resolve(txb.toHex());
		});
	});
});

And this is the code for retrieving the pubkey:

	private getPublicKeyFromPath(path: string) {
		return new Promise((resolve, reject) => {
			TransportU2F.create().then(transport => {
				const btc = new Btc(transport);
				btc.getWalletPublicKey(path, { verify: false, format: 'legacy' }).then(result => {
					const comppk = compressPublicKey(result.publicKey);
					resolve(comppk);
				}).catch(err => {
					reject(err);
				});
			}).catch(err => {
				reject(err);
			});
		});
	};

@junderw
Copy link
Member Author

junderw commented Sep 5, 2019

Very cool.

I would like to see the bigger project. Not sure where publickey is coming from etc.

@dakk
Copy link

dakk commented Sep 6, 2019

@junderw I put the getpubkey function in the previous message; anyway for further details the frontend wallet part of our platform is opensource: https://github.com/helperbit/helperbit-wallet

@jasonandjay
Copy link
Member

@junderw
maybe we can merge this with #1326

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

No branches or pull requests

4 participants