Skip to content

Commit

Permalink
Enhancement: Tx Unlocker (#67)
Browse files Browse the repository at this point in the history
* added generic tx unlocker interface

* made unlocker a general signature script unlocker

* fixed linter

* Unlocker.Unlock return the data used to build the unlocking script

* reverted back to the unlocker just returning an error

* fix doc string comment

* change switch statement to if/else

* fixed test names and doc comments
  • Loading branch information
tigh-latte authored Oct 15, 2021
1 parent 2f85c3e commit fc06c54
Show file tree
Hide file tree
Showing 17 changed files with 367 additions and 330 deletions.
4 changes: 3 additions & 1 deletion bscript/script.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const (
ScriptTypePubKey = "pubkey"
ScriptTypePubKeyHash = "pubkeyhash"
ScriptTypeNonStandard = "nonstandard"
ScriptTypeEmpty = "empty"
ScriptTypeSecureHash = "securehash"
ScriptTypeMultiSig = "multisig"
ScriptTypeNullData = "nulldata"
)
Expand Down Expand Up @@ -349,7 +351,7 @@ func (s *Script) PublicKeyHash() ([]byte, error) {
// ScriptType returns the type of script this is as a string.
func (s *Script) ScriptType() string {
if len(*s) == 0 {
return ScriptTypeNonStandard
return ScriptTypeEmpty
}
if s.IsP2PKH() {
return ScriptTypePubKeyHash
Expand Down
2 changes: 1 addition & 1 deletion examples/create_tx/create_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func main() {

decodedWif, _ := wif.DecodeWIF("KznvCNc6Yf4iztSThoMH6oHWzH9EgjfodKxmeuUGPq5DEX5maspS")

if err := tx.SignAll(context.Background(), &bt.LocalSignerGetter{PrivateKey: decodedWif.PrivKey}); err != nil {
if err := tx.UnlockAll(context.Background(), &bt.LocalUnlockerGetter{PrivateKey: decodedWif.PrivKey}); err != nil {
log.Fatal(err.Error())
}
log.Printf("tx: %s\n", tx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func main() {

decodedWif, _ := wif.DecodeWIF("L3VJH2hcRGYYG6YrbWGmsxQC1zyYixA82YjgEyrEUWDs4ALgk8Vu")

err := tx.SignAll(context.Background(), &bt.LocalSignerGetter{PrivateKey: decodedWif.PrivKey})
err := tx.UnlockAll(context.Background(), &bt.LocalUnlockerGetter{PrivateKey: decodedWif.PrivKey})
if err != nil {
log.Fatal(err.Error())
}
Expand Down
56 changes: 0 additions & 56 deletions localsigner.go

This file was deleted.

60 changes: 60 additions & 0 deletions localunlocker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package bt

import (
"context"
"errors"

"github.com/libsv/go-bk/bec"
"github.com/libsv/go-bt/v2/bscript"
"github.com/libsv/go-bt/v2/sighash"
)

// LocalUnlockerGetter implements the UnlockerGetter interface. It unlocks a Tx locally,
// using a bec PrivateKey.
type LocalUnlockerGetter struct {
PrivateKey *bec.PrivateKey
}

// Unlocker builds a new *bt.LocalUnlocker with the same private key
// as the calling *bt.LocalUnlockerGetter.
func (lg *LocalUnlockerGetter) Unlocker(ctx context.Context, lockingScript *bscript.Script) (Unlocker, error) {
return &LocalUnlocker{PrivateKey: lg.PrivateKey}, nil
}

// LocalUnlocker implements the unlocker interface. It is used to unlock a tx locally using a
// bec Private Key.
type LocalUnlocker struct {
PrivateKey *bec.PrivateKey
}

// Unlock a transaction at a given input using the PrivateKey passed in through the LocalUnlocker
// struct.
// Unlock generates, applies, and returns an ECDSA signature for the provided hash digest using the private key
// as well as the public key corresponding to the private key used. The produced
// signature is deterministic (same message and same key yield the same signature) and
// canonical in accordance with RFC6979 and BIP0062.
func (lu *LocalUnlocker) Unlock(ctx context.Context, tx *Tx, idx uint32, shf sighash.Flag) error {
if shf == 0 {
shf = sighash.AllForkID
}

sh, err := tx.CalcInputSignatureHash(idx, shf)
if err != nil {
return err
}

sig, err := lu.PrivateKey.Sign(sh)
if err != nil {
return err
}

pubKey := lu.PrivateKey.PubKey().SerialiseCompressed()
signature := sig.Serialise()

switch tx.Inputs[idx].PreviousTxScript.ScriptType() {
case bscript.ScriptTypePubKeyHash:
return tx.ApplyP2PKHUnlockingScript(idx, pubKey, signature, shf)
}

return errors.New("currently only p2pkh supported")
}
Loading

0 comments on commit fc06c54

Please sign in to comment.