Skip to content

Commit

Permalink
remove FillAllInputs from docs
Browse files Browse the repository at this point in the history
  • Loading branch information
David Case committed Nov 1, 2024
1 parent 8f0b622 commit d67001d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 296 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,22 @@ import (
func main() {
tx := transaction.NewTransaction()

_ = tx.AddInputFrom(
unlockingScriptTemplate, _ := p2pkh.Unlock(priv, nil)
if err := tx.AddInputFrom(
"11b476ad8e0a48fcd40807a111a050af51114877e09283bfa7f3505081a1819d",
0,
"76a914eb0bd5edba389198e73f8efabddfc61666969ff788ac6a0568656c6c6f",
"76a9144bca0c466925b875875a8e1355698bdcc0b2d45d88ac",
1500,
)
unlockingScriptTemplate,
); err!= nil {
log.Fatal(err.Error())
}

_ = tx.PayToAddress("1AdZmoAQUw4XCsCihukoHMvNWXcsd8jDN6", 1000)

decodedWif, _ := wif.DecodeWIF("KzH8frNSgsKtmPQ2oMFnwD3DK347PY3YJUzE1dCKNKLaWSfHaXGC")
priv, _ := ec.PrivateKeyFromWif("KznvCNc6Yf4iztSThoMH6oHWzH9EgjfodKxmeuUGPq5DEX5maspS")

if err := tx.FillAllInputs(context.Background(), &unlocker.Getter{PrivateKey: decodedWif.PrivKey}); err != nil {
if err := tx.Sign(); err != nil {
log.Fatal(err.Error())
}
log.Printf("tx: %s\n", tx)
Expand Down
74 changes: 33 additions & 41 deletions docs/examples/create_simple_tx/create_simple_tx.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,44 +25,35 @@ import (
// https://goplay.tools/snippet/bnsS-pA56ob
func main() {
// Create a new transaction
tx := transaction.NewTransaction()

// Add the inputs
err := tx.AddInputFrom(
// Previous transaction ID (hex)
"11b476ad8e0a48fcd40807a111a050af51114877e09283bfa7f3505081a1819d",
// Previous transaction output index
0,
// Previous transaction script (hex)
"76a9144bca0c466925b875875a8e1355698bdcc0b2d45d88ac",
// Previous transaction output value in satoshis
1500,
)

if err!= nil {
log.Fatal(err.Error())
}

// Add the outputs
_ = tx.PayToAddress(
// Destination address
"1NRoySJ9Lvby6DuE2UQYnyT67AASwNZxGb",
// Value in satoshis
1000,
)

// Fill all inputs with the given private key
decodedWif, _ := wif.DecodeWIF("KznvCNc6Yf4iztSThoMH6oHWzH9EgjfodKxmeuUGPq5DEX5maspS")

// Sign the transaction
if err := tx.FillAllInputs(
// The default context which is empty but can be
// used to control cancellations and timeouts.
context.Background(),
&unlocker.Getter{PrivateKey: decodedWif.PrivKey}); err != nil {
log.Fatal(err.Error())
}
log.Printf("tx: %s\n", tx)
tx := transaction.NewTransaction()

// Add the inputs
unlockingScriptTemplate, _ := p2pkh.Unlock(priv, nil)
if err := tx.AddInputFrom(
"11b476ad8e0a48fcd40807a111a050af51114877e09283bfa7f3505081a1819d",
0,
"76a9144bca0c466925b875875a8e1355698bdcc0b2d45d88ac",
1500,
unlockingScriptTemplate,
); err!= nil {
log.Fatal(err.Error())
}

// Add the outputs
_ = tx.PayToAddress(
// Destination address
"1NRoySJ9Lvby6DuE2UQYnyT67AASwNZxGb",
// Value in satoshis
1000,
)

priv, _ := ec.PrivateKeyFromWif("KznvCNc6Yf4iztSThoMH6oHWzH9EgjfodKxmeuUGPq5DEX5maspS")

// Sign the transaction
if err := tx.Sign(); err != nil {
log.Fatal(err.Error())
}
log.Printf("tx: %s\n", tx)
}

```
Expand All @@ -81,19 +72,20 @@ Main Function:
- The output index (vout) in the referenced transaction.
- A script (locking script) representing the locking conditions under which the output can be spent.
- The number of satoshis from the output that is being spent.
- UnlockingScriptTemplate used to sign input

`tx.PayToAddress(...)` adds an output to the transaction, specifying:

- The recipient's Bitcoin SV address.
- The amount of satoshis to send to that address.

`wif.DecodeWIF(...)` decodes a WIF-encoded private key. This is necessary for signing the transaction inputs.
`ec.PrivateKeyFromWif(...)` decodes a WIF-encoded private key. This is necessary for signing the transaction inputs.

`tx.FillAllInputs(...)` attempts to sign all inputs of the transaction using the private key provided. This is essential for validating the transaction on the network.
`tx.Sign(...)` attempts to sign all inputs of the transaction using the script templates provided. This is essential for validating the transaction on the network.

The context passed `(context.Background())` is the default context which is empty but can be used to control cancellations and timeouts.
Error Handling and Logging:

If `tx.FillAllInputs(...)` returns an error, the program logs the error and terminates using `log.Fatal(...)`.
If `tx.Sign(...)` returns an error, the program logs the error and terminates using `log.Fatal(...)`.

If no error occurs, it logs the serialized form of the transaction, which is ready to be broadcasted to the network.
250 changes: 0 additions & 250 deletions transaction/template/p2pkh/p2pkh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,253 +128,3 @@ func TestLocalUnlocker_ValidSignature(t *testing.T) {
})
}
}

// type mockUnlockerGetter struct {
// t *testing.T
// unlockerFunc func(ctx context.Context, lockingScript *script.Script) (transaction.ScriptTemplate, error)
// }

// func (m *mockUnlockerGetter) Unlocker(ctx context.Context, lockingScript *script.Script) (transaction.ScriptTemplate, error) {
// require.NotNil(m.t, m.unlockerFunc, "unlockerFunc not set in this test")
// return m.unlockerFunc(ctx, lockingScript)
// }

// type mockUnlocker struct {
// t *testing.T
// script string
// }

// func (m *mockUnlocker) UnlockingScript(ctx context.Context, tx *transaction.Transaction, params transaction.UnlockParams) (*script.Script, error) {
// uscript, err := script.NewFromASM(m.script)
// require.NoError(m.t, err)

// return uscript, nil
// }

// func TestLocalUnlocker_NonSignature(t *testing.T) {
// t.Parallel()
// tests := map[string]struct {
// tx *transaction.Transaction
// unlockerFunc func(ctx context.Context, lockingScript *script.Script) (transaction.Unlocker, error)
// expUnlockingScripts []string
// }{
// "simple script": {
// tx: func() *transaction.Transaction {
// tx := transaction.NewTransaction()
// require.NoError(t, tx.AddInputFrom("45be95d2f2c64e99518ffbbce03fb15a7758f20ee5eecf0df07938d977add71d", 0, "52529387", 15564838601))
// return tx
// }(),
// unlockerFunc: func(ctx context.Context, lockingScript *script.Script) (transaction.Unlocker, error) {
// asm, err := lockingScript.ToASM()
// require.NoError(t, err)

// unlocker, ok := map[string]*mockUnlocker{
// "OP_2 OP_2 OP_ADD OP_EQUAL": {t: t, script: "OP_4"},
// }[asm]

// require.True(t, ok)
// require.NotNil(t, unlocker)

// return unlocker, nil
// },
// expUnlockingScripts: []string{"OP_4"},
// },
// "multiple inputs unlocked": {
// tx: func() *transaction.Transaction {
// tx := transaction.NewTransaction()
// require.NoError(t, tx.AddInputFrom("45be95d2f2c64e99518ffbbce03fb15a7758f20ee5eecf0df07938d977add71d", 0, "52529487", 15564838601))
// require.NoError(t, tx.AddInputFrom("45be95d2f2c64e99518ffbbce03fb15a7758f20ee5eecf0df07938d977add71d", 0, "52589587", 15564838601))
// require.NoError(t, tx.AddInputFrom("45be95d2f2c64e99518ffbbce03fb15a7758f20ee5eecf0df07938d977add71d", 0, "5a559687", 15564838601))
// return tx
// }(),
// unlockerFunc: func(ctx context.Context, lockingScript *script.Script) (transaction.ScriptTemplate, error) {
// asm, err := lockingScript.ToASM()
// require.NoError(t, err)

// unlocker, ok := map[string]*mockUnlocker{
// "OP_2 OP_2 OP_SUB OP_EQUAL": {t: t, script: "OP_FALSE"},
// "OP_2 OP_8 OP_MUL OP_EQUAL": {t: t, script: "OP_16"},
// "OP_10 OP_5 OP_DIV OP_EQUAL": {t: t, script: "OP_2"},
// }[asm]

// require.True(t, ok)
// require.NotNil(t, unlocker)

// return unlocker, nil
// },
// expUnlockingScripts: []string{"OP_FALSE", "OP_16", "OP_2"},
// },
// }

// for name, test := range tests {
// t.Run(name, func(t *testing.T) {
// tx := test.tx
// require.Equal(t, len(tx.Inputs), len(test.expUnlockingScripts))

// ug := &mockUnlockerGetter{
// t: t,
// unlockerFunc: test.unlockerFunc,
// }
// require.NoError(t, tx.FillAllInputs(context.Background(), ug))
// for i, script := range test.expUnlockingScripts {
// asm, err := tx.Inputs[i].UnlockingScript.ToASM()
// require.NoError(t, err)

// require.Equal(t, script, asm)
// }
// })
// }
// }

//
// func TestBareMultiSigValidation(t *testing.T) {
// txHex := "0100000001cfb38c76cadeb5b96c3863d9e298fe96e24e594b75f69c37aa709f45b76d1b25000000009200483045022100d83dc84d3ea3fb36b006f6887e1e16811c59fe9a9b79b84142874a90d5b834160220052967be98c26270de0082b0fecab5a40d5bc48d5034b6cdfc2b8e47210e1469414730440220099ffa89363f9a05f23a4fa318ddbefeeeec4b41f6abde7083a3be6696ed904902201722110a488df3780a260ba09b7de6363bfce7f6beec9819e9b9f47f6e978d8141ffffffff01a8840100000000001976a91432b996f742e774b0241be9007f831558ba06d20b88ac00000000"
// tx, err := transaction.NewTransactionFromHex(txHex)
// if err != nil {
// t.Error(err)
// return
// }
//
// // txid := tx.GetTxID()
// // fmt.Println(txid)
//
// var sigs = make([]*ec.Signature, 2)
// var sigHashTypes = make([]uint32, 2)
// var publicKeys = make([]*ec.PublicKey, 3)
//
// sigScript := tx.Inputs[0].UnlockingScript
//
// sig0Bytes := []byte(*sigScript)[2:73]
// sig0HashType, _ := binary.Uvarint([]byte(*sigScript)[73:74])
// sig1Bytes := []byte(*sigScript)[75:145]
// sig1HashType, _ := binary.Uvarint([]byte(*sigScript)[145:146])
//
// pk0, _ := hex.DecodeString("023ff15e2676e03b2c0af30fc17b7fb354bbfa9f549812da945194d3407dc0969b")
// pk1, _ := hex.DecodeString("039281958c651c013f5b3b007c78be231eeb37f130b925ceff63dc3ac8886f22a3")
// pk2, _ := hex.DecodeString("03ac76121ffc9db556b0ce1da978021bd6cb4a5f9553c14f785e15f0e202139e3e")
//
// publicKeys[0], err = ec.ParsePubKey(pk0, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// publicKeys[1], err = ec.ParsePubKey(pk1, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// publicKeys[2], err = ec.ParsePubKey(pk2, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
//
// sigs[0], err = ec.ParseDERSignature(sig0Bytes, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// sigs[1], err = ec.ParseDERSignature(sig1Bytes, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// sigHashTypes[0] = uint32(sig0HashType)
// sigHashTypes[1] = uint32(sig1HashType)
//
// var previousTxSatoshis uint64 = 99728
// var SourceTxScript, _ = script.NewFromHex("5221023ff15e2676e03b2c0af30fc17b7fb354bbfa9f549812da945194d3407dc0969b21039281958c651c013f5b3b007c78be231eeb37f130b925ceff63dc3ac8886f22a32103ac76121ffc9db556b0ce1da978021bd6cb4a5f9553c14f785e15f0e202139e3e53ae")
// var prevIndex uint32
// var outIndex uint32
//
// for i, sig := range sigs {
// sighash := signature.GetSighashForInputValidation(tx, sigHashTypes[i], outIndex, prevIndex, previousTxSatoshis, SourceTxScript)
// h, err := hex.DecodeString(sighash)
// if err != nil {
// t.Error(err)
// return
// }
// for j, pk := range publicKeys {
// valid := sig.Verify(util.ReverseBytes(h), pk)
// t.Logf("signature %d against pulbic key %d => %v\n", i, j, valid)
// }
//
// }
//
// }
//
// func TestP2SHMultiSigValidation(t *testing.T) { // NOT working properly!
// txHex := "0100000001d0219010e1f74ec8dd264a63ef01b5c72aab49a74c9bffd464c7f7f2b193b34700000000fdfd0000483045022100c2ffae14c7cfae5c1b45776f4b2d497b0d10a9e3be55b1386c555f90acd022af022025d5d1d33429fabd60c41763f9cda5c4b64adbddbd90023febc005be431b97b641473044022013f65e41abd6be856e7c7dd7527edc65231e027c42e8db7358759fc9ccd77b7d02206e024137ee54d2fac9f1dce858a85cb03fb7ba93b8e015d82e8a959b631f91ac414c695221021db57ae3de17143cb6c314fb206b56956e8ed45e2f1cbad3947411228b8d17f1210308b00cf7dfbb64604475e8b18e8450ac6ec04655cfa5c6d4d8a0f3f141ee419421030c7f9342ff6583599db8ee8b52383cadb4cf6fee3650c1ad8f66158a4ff0ebd953aefeffffff01b70f0000000000001976a91415067448220971206e6b4d90733d70fe9610631688ac56750900"
// tx, err := transaction.NewTransactionFromHex(txHex)
// if err != nil {
// t.Error(err)
// return
// }
//
// // txid := tx.GetTxID()
// // fmt.Println(txid)
//
// var sigs = make([]*ec.Signature, 2)
// var sigHashTypes = make([]uint32, 2)
// var publicKeys = make([]*ec.PublicKey, 3)
//
// sigScript := tx.Inputs[0].UnlockingScript
//
// sig0Bytes := []byte(*sigScript)[2:73]
// sig0HashType, _ := binary.Uvarint([]byte(*sigScript)[73:74])
// sig1Bytes := []byte(*sigScript)[75:145]
// sig1HashType, _ := binary.Uvarint([]byte(*sigScript)[145:146])
//
// pk0, _ := hex.DecodeString("021db57ae3de17143cb6c314fb206b56956e8ed45e2f1cbad3947411228b8d17f1")
// pk1, _ := hex.DecodeString("0308b00cf7dfbb64604475e8b18e8450ac6ec04655cfa5c6d4d8a0f3f141ee4194")
// pk2, _ := hex.DecodeString("030c7f9342ff6583599db8ee8b52383cadb4cf6fee3650c1ad8f66158a4ff0ebd9")
//
// publicKeys[0], err = ec.ParsePubKey(pk0, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// publicKeys[1], err = ec.ParsePubKey(pk1, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// publicKeys[2], err = ec.ParsePubKey(pk2, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
//
// sigs[0], err = ec.ParseDERSignature(sig0Bytes, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// sigs[1], err = ec.ParseDERSignature(sig1Bytes, ec.S256())
// if err != nil {
// t.Error(err)
// return
// }
// sigHashTypes[0] = uint32(sig0HashType)
// sigHashTypes[1] = uint32(sig1HashType)
//
// var previousTxSatoshis uint64 = 8785040
// var SourceTxScript, _ = script.NewFromHex("5221021db57ae3de17143cb6c314fb206b56956e8ed45e2f1cbad3947411228b8d17f1210308b00cf7dfbb64604475e8b18e8450ac6ec04655cfa5c6d4d8a0f3f141ee419421030c7f9342ff6583599db8ee8b52383cadb4cf6fee3650c1ad8f66158a4ff0ebd953ae")
// var prevIndex uint32 = 1
// var outIndex uint32 = 0
//
// for i, sig := range sigs {
// sighash := signature.GetSighashForInputValidation(tx, sigHashTypes[i], outIndex, prevIndex, previousTxSatoshis, SourceTxScript)
// h, err := hex.DecodeString(sighash)
// if err != nil {
// t.Error(err)
// return
// }
// for j, pk := range publicKeys {
// valid := sig.Verify(util.ReverseBytes(h), pk)
// t.Logf("signature %d against pulbic key %d => %v\n", i, j, valid)
// }
//
// }
//
// }

0 comments on commit d67001d

Please sign in to comment.