Replace p2pkh with p2pk (#1650)

* Replace p2pkh with p2pk

* Fix tests

* Fix comments and variable names

* Add README.md for genkeypair

* Rename pubkey->publicKey

* Rename p2pkh to p2pk

* Use util.PublicKeySize where needed

* Remove redundant pointer

* Fix comment

* Rename pubKey->publicKey
This commit is contained in:
Ori Newman 2021-04-05 14:35:34 +03:00 committed by GitHub
parent d01a213f3d
commit 6afc06ce58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 302 additions and 300 deletions

9
cmd/genkeypair/README.md Normal file
View File

@ -0,0 +1,9 @@
genkeypair
========
A tool for generating private-key-address pairs.
Note: This tool prints unencrypted private keys and is not recommended for day
to day use, and is intended mainly for tests.
In order to manage your funds it's recommended to use [kaspawallet](../kaspawallet)

26
cmd/genkeypair/config.go Normal file
View File

@ -0,0 +1,26 @@
package main
import (
"github.com/jessevdk/go-flags"
"github.com/kaspanet/kaspad/infrastructure/config"
)
type configFlags struct {
config.NetworkFlags
}
func parseConfig() (*configFlags, error) {
cfg := &configFlags{}
parser := flags.NewParser(cfg, flags.PrintErrors|flags.HelpFlag)
_, err := parser.Parse()
if err != nil {
return nil, err
}
err = cfg.ResolveNetwork(parser)
if err != nil {
return nil, err
}
return cfg, nil
}

27
cmd/genkeypair/main.go Normal file
View File

@ -0,0 +1,27 @@
package main
import (
"fmt"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
"github.com/kaspanet/kaspad/util"
)
func main() {
cfg, err := parseConfig()
if err != nil {
panic(err)
}
privateKey, publicKey, err := libkaspawallet.CreateKeyPair()
if err != nil {
panic(err)
}
addr, err := util.NewAddressPublicKey(publicKey, cfg.NetParams().Prefix)
if err != nil {
panic(err)
}
fmt.Printf("Private key: %x\n", privateKey)
fmt.Printf("Address: %s\n", addr)
}

View File

@ -26,9 +26,9 @@ func CreateKeyPair() ([]byte, []byte, error) {
}
func addressFromPublicKey(params *dagconfig.Params, publicKeySerialized []byte) (util.Address, error) {
addr, err := util.NewAddressPubKeyHashFromPublicKey(publicKeySerialized[:], params.Prefix)
addr, err := util.NewAddressPublicKey(publicKeySerialized[:], params.Prefix)
if err != nil {
return nil, errors.Wrap(err, "Failed to generate p2pkh address")
return nil, errors.Wrap(err, "Failed to generate p2pk address")
}
return addr, nil

View File

@ -254,7 +254,7 @@ func extractTransaction(psTx *serialization.PartiallySignedTransaction) (*extern
psTx.Tx.Inputs[i].SignatureScript = sigScript
} else {
if len(input.PubKeySignaturePairs) > 1 {
return nil, errors.Errorf("Cannot sign on P2PKH when len(input.PubKeySignaturePairs) > 1")
return nil, errors.Errorf("Cannot sign on P2PK when len(input.PubKeySignaturePairs) > 1")
}
if input.PubKeySignaturePairs[0].Signature == nil {
@ -263,7 +263,6 @@ func extractTransaction(psTx *serialization.PartiallySignedTransaction) (*extern
sigScript, err := txscript.NewScriptBuilder().
AddData(input.PubKeySignaturePairs[0].Signature).
AddData(input.PubKeySignaturePairs[0].PubKey).
Script()
if err != nil {
return nil, err

View File

@ -156,7 +156,7 @@ func TestMultisig(t *testing.T) {
})
}
func TestP2PKH(t *testing.T) {
func TestP2PK(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.BlockCoinbaseMaturity = 0
tc, teardown, err := consensus.NewFactory().NewTestConsensus(params, false, "TestMultisig")
@ -181,7 +181,7 @@ func TestP2PKH(t *testing.T) {
t.Fatalf("Address: %+v", err)
}
if _, ok := address.(*util.AddressPubKeyHash); !ok {
if _, ok := address.(*util.AddressPublicKey); !ok {
t.Fatalf("The address is of unexpected type")
}

View File

@ -58,9 +58,9 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
if err != nil {
t.Fatalf("Failed to serialize public key: %v", err)
}
addr, err := util.NewAddressPubKeyHashFromPublicKey(publicKeySerialized[:], params.Prefix)
addr, err := util.NewAddressPublicKey(publicKeySerialized[:], params.Prefix)
if err != nil {
t.Fatalf("Failed to generate p2pkh address: %v", err)
t.Fatalf("Failed to generate p2pk address: %v", err)
}
scriptPublicKey, err := txscript.PayToAddrScript(addr)
if err != nil {
@ -261,9 +261,9 @@ func TestSigningTwoInputs(t *testing.T) {
if err != nil {
t.Fatalf("Failed to serialize public key: %v", err)
}
addr, err := util.NewAddressPubKeyHashFromPublicKey(publicKeySerialized[:], params.Prefix)
addr, err := util.NewAddressPublicKey(publicKeySerialized[:], params.Prefix)
if err != nil {
t.Fatalf("Failed to generate p2pkh address: %v", err)
t.Fatalf("Failed to generate p2pk address: %v", err)
}
scriptPublicKey, err := txscript.PayToAddrScript(addr)

View File

@ -108,86 +108,86 @@ func TestCalculateSignatureHash(t *testing.T) {
// sigHashAll
{name: "native-all-0", tx: nativeTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "c899a5ea7414f0bbfd77e50674f46da34ce8722b928d4362a4b4b727c69c6499"},
expectedSignatureHash: "3e4a8effa6903dea5f762754ec410d732114ec2907e5bcbae7b6dd8d3f309a10"},
{name: "native-all-0-modify-input-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyInput(1), // should change the hash
expectedSignatureHash: "faf3b9db2e07b1c14b2df02002d3e40f1e430f177ac5cd3354c84dad8fbe72ce"},
expectedSignatureHash: "0bd2947383101f9708d94d5799626c69c1b8472d2de66523c90c4a674e99cc51"},
{name: "native-all-0-modify-output-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifyOutput(1), // should change the hash
expectedSignatureHash: "3a557c5b873aab72dcb81649642e1d7a63b75dcdcc74e19d340964a9e0eac76c"},
expectedSignatureHash: "ae69aa1372e958f069bf52d2628ead7ee789f195340b615ff0bcb6f01a995810"},
{name: "native-all-0-modify-sequence-1", tx: nativeTx, hashType: all, inputIndex: 0,
modificationFunction: modifySequence(1), // should change the hash
expectedSignatureHash: "2dd5fe8f9fa4bf551ea2f080a26e07b2462083e12d3b2ed01cb9369a61920665"},
expectedSignatureHash: "51295575e7efc1fe1c2e741ade49089e3d780d15d26e9a0b18b3d90e35caf795"},
{name: "native-all-anyonecanpay-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "19fe2e0db681017f318fda705a39bbbad9c1085514cfbcff6fac01e1725f758b"},
expectedSignatureHash: "0a13d3cab42a6cf3a7ef96f7b28c9bb0d98c209a3032ff85a6bfa7dac520f2c2"},
{name: "native-all-anyonecanpay-0-modify-input-0", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(0), // should change the hash
expectedSignatureHash: "5b21d492560a1c794595f769b3ae3c151775b9cfc4029d17c53f1856e1005da4"},
expectedSignatureHash: "aeaa56f5bc99daea0be5ed4b047808ce0123a81ac89c6089b72fa7199f5cd1c6"},
{name: "native-all-anyonecanpay-0-modify-input-1", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyInput(1), // shouldn't change the hash
expectedSignatureHash: "19fe2e0db681017f318fda705a39bbbad9c1085514cfbcff6fac01e1725f758b"},
expectedSignatureHash: "0a13d3cab42a6cf3a7ef96f7b28c9bb0d98c209a3032ff85a6bfa7dac520f2c2"},
{name: "native-all-anyonecanpay-0-modify-sequence", tx: nativeTx, hashType: allAnyoneCanPay, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "19fe2e0db681017f318fda705a39bbbad9c1085514cfbcff6fac01e1725f758b"},
expectedSignatureHash: "0a13d3cab42a6cf3a7ef96f7b28c9bb0d98c209a3032ff85a6bfa7dac520f2c2"},
// sigHashNone
{name: "native-none-0", tx: nativeTx, hashType: none, inputIndex: 0,
expectedSignatureHash: "fafabaabf6349fee4e18626b4eff015472f2317576a8f4bf7b0eea1df6f3e32b"},
expectedSignatureHash: "da53f7c726b55357adb1b644265fe7b9b7897cadde91a942d6127195c2ce99dc"},
{name: "native-none-0-modify-output-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "fafabaabf6349fee4e18626b4eff015472f2317576a8f4bf7b0eea1df6f3e32b"},
expectedSignatureHash: "da53f7c726b55357adb1b644265fe7b9b7897cadde91a942d6127195c2ce99dc"},
{name: "native-none-0-modify-sequence-0", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "daee0700e0ed4ab9f50de24d83e0bfce62999474ec8ceeb537ea35980662b601"},
expectedSignatureHash: "72c07c152a3792fb863d2de219ab4e863fe6779dc970a5c3958e26b3a3b9f139"},
{name: "native-none-0-modify-sequence-1", tx: nativeTx, hashType: none, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "fafabaabf6349fee4e18626b4eff015472f2317576a8f4bf7b0eea1df6f3e32b"},
expectedSignatureHash: "da53f7c726b55357adb1b644265fe7b9b7897cadde91a942d6127195c2ce99dc"},
{name: "native-none-anyonecanpay-0", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "4e5c2d895f9711dc89c19d49ba478e9c8f4be0d82c9bd6b60d0361eb9b5296bc"},
expectedSignatureHash: "18eb79df328a516708f792cadfc4bf2be21b6add35fb6637a20347d532b1dce1"},
{name: "native-none-anyonecanpay-0-modify-amount-spent", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyAmountSpent(0), // should change the hash
expectedSignatureHash: "9ce2f75eafc85b8e19133942c3143d14b61f2e7cc479fbc6d2fca026e50897f1"},
expectedSignatureHash: "674a8e6effa0bbfdb3df3ca45a7b17ab695cc0f9b3e0519e5bff165de13604e2"},
{name: "native-none-anyonecanpay-0-modify-script-public-key", tx: nativeTx, hashType: noneAnyoneCanPay, inputIndex: 0,
modificationFunction: modifyScriptPublicKey(0), // should change the hash
expectedSignatureHash: "c6c364190520fe6c0419c2f45e25bf084356333b03ac7aaec28251126398bda3"},
expectedSignatureHash: "7a879d339c9b948c5264f1c0b8463f551221b2dcd575623f178cbbfcf7e01987"},
// sigHashSingle
{name: "native-single-0", tx: nativeTx, hashType: single, inputIndex: 0,
expectedSignatureHash: "6ff01d5d7cd82e24bc9ca0edec8bd6931ffb5aa1d303f07ca05dc89757343a92"},
expectedSignatureHash: "99c0a4a381fed9dbd651450d6ca969a6e8cdd941e9d73be086a1ba6c90fb630f"},
{name: "native-single-0-modify-output-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(0), // should change the hash
expectedSignatureHash: "d62af956aea369365bacc7e7f1aac106836994f1648311e82dd38da822c8771e"},
expectedSignatureHash: "92189a32391ca50a454d1853efed55acb1c49993911a1201df9891c866c483ee"},
{name: "native-single-0-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "6ff01d5d7cd82e24bc9ca0edec8bd6931ffb5aa1d303f07ca05dc89757343a92"},
expectedSignatureHash: "99c0a4a381fed9dbd651450d6ca969a6e8cdd941e9d73be086a1ba6c90fb630f"},
{name: "native-single-0-modify-sequence-0", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(0), // should change the hash
expectedSignatureHash: "46692229d45bf2ceacb18960faba29753e325c0ade26ecf94495b91daacb828d"},
expectedSignatureHash: "765e2289df98b3a5269f112d4b36d57fe32c74d42e04a3046c6a3c8dd78a4121"},
{name: "native-single-0-modify-sequence-1", tx: nativeTx, hashType: single, inputIndex: 0,
modificationFunction: modifySequence(1), // shouldn't change the hash
expectedSignatureHash: "6ff01d5d7cd82e24bc9ca0edec8bd6931ffb5aa1d303f07ca05dc89757343a92"},
expectedSignatureHash: "99c0a4a381fed9dbd651450d6ca969a6e8cdd941e9d73be086a1ba6c90fb630f"},
{name: "native-single-2-no-corresponding-output", tx: nativeTx, hashType: single, inputIndex: 2,
expectedSignatureHash: "d3cc385082a7f272ec2c8aae7f3a96ab2f49a4a4e1ed44d61af34058a7721281"},
expectedSignatureHash: "43de18c04d7fde81f49a40228d8730b4ceb0c66c77841c22622f59554769dd13"},
{name: "native-single-2-no-corresponding-output-modify-output-1", tx: nativeTx, hashType: single, inputIndex: 2,
modificationFunction: modifyOutput(1), // shouldn't change the hash
expectedSignatureHash: "d3cc385082a7f272ec2c8aae7f3a96ab2f49a4a4e1ed44d61af34058a7721281"},
expectedSignatureHash: "43de18c04d7fde81f49a40228d8730b4ceb0c66c77841c22622f59554769dd13"},
{name: "native-single-anyonecanpay-0", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 0,
expectedSignatureHash: "408fcfd8ceca135c0f54569ccf8ac727e1aa6b5a15f87ccca765f1d5808aa4ea"},
expectedSignatureHash: "2e270f86fd68f780a5aa8d250364ab6786d990040268e5d561d09dde365dfab7"},
{name: "native-single-anyonecanpay-2-no-corresponding-output", tx: nativeTx, hashType: singleAnyoneCanPay, inputIndex: 2,
expectedSignatureHash: "685fac0d0b9dd3c5556f266714c4f7f93475d49fa12befb18e8297bc062aeaba"},
expectedSignatureHash: "afc05dd6b4a530cc3a4d7d23126548bd1f31c793e9282cbbfa27ff5566219501"},
// subnetwork transaction
{name: "subnetwork-all-0", tx: subnetworkTx, hashType: all, inputIndex: 0,
expectedSignatureHash: "0e8b1433b761a220a61c0dc1f0fda909d49cef120d98d9f87344fef52dac0d8b"},
expectedSignatureHash: "5a67423ee048e067b94e2d4fc2960f62eceff6aa8b6c5ad71e3b7b7e5ff6bad7"},
{name: "subnetwork-all-modify-payload", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyPayload, // should change the hash
expectedSignatureHash: "087315acb9193eaa14929dbe3d0ace80238aebe13eab3bf8db6c0a0d7ddb782e"},
expectedSignatureHash: "0d3bc5914da8dc8df081945fea1255359f380ca9baa8b31dfb3657c1e3c6038a"},
{name: "subnetwork-all-modify-gas", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifyGas, // should change the hash
expectedSignatureHash: "07a90408ef45864ae8354b07a74cf826a4621391425ba417470a6e680af4ce70"},
expectedSignatureHash: "70abe9f947d0a0f5d735f9a063db8af41fe5902940f2693a1782119063097094"},
{name: "subnetwork-all-subnetwork-id", tx: subnetworkTx, hashType: all, inputIndex: 0,
modificationFunction: modifySubnetworkID, // should change the hash
expectedSignatureHash: "4ca44c2e35729ae5efe831a77027f1a58a41dbdd853459c26cbfe7d6c88783fb"},
expectedSignatureHash: "571a0b7ea905b7a6ff7ab825b72d23f911bac0bfaa7c4c97a4887a3d090925d4"},
}
for _, test := range tests {

View File

@ -1,10 +1,9 @@
package hashes
import (
"hash"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/pkg/errors"
"hash"
)
// HashWriter is used to incrementally hash data without concatenating all of the data to a single buffer

View File

@ -15,7 +15,7 @@ although it is still fairly powerful.
## Examples
* [Standard Pay-to-pubkey-hash Script](http://godoc.org/github.com/kaspanet/kaspad/txscript#example-PayToAddrScript)
* [Standard Pay-to-pubkey Script](http://godoc.org/github.com/kaspanet/kaspad/txscript#example-PayToAddrScript)
Demonstrates creating a script which pays to a kaspa address. It also
prints the created script hex and uses the DisasmString function to display
the disassembled script.

View File

@ -22,7 +22,7 @@ func ExamplePayToAddrScript() {
// which is useful to ensure the accuracy of the address and determine
// the address type. It is also required for the upcoming call to
// PayToAddrScript.
addressStr := "kaspa:qqfgqp8l9l90zwetj84k2jcac2m8falvvyy8xjtnhdac2m8falvvyvc9fuvqt"
addressStr := "kaspa:qqj9fg59mptxkr9j0y53j5mwurcmda5mtza9n6v9pm9uj8h0wgk6uma5pvumr"
address, err := util.DecodeAddress(addressStr, util.Bech32PrefixKaspa)
if err != nil {
fmt.Println(err)
@ -45,15 +45,15 @@ func ExamplePayToAddrScript() {
fmt.Println("Script Disassembly:", disasm)
// Output:
// Script Hex: 76aa20128004ff2fcaf13b2b91eb654b1dc2b674f7ec6108734973bb7b856ce9efd8c288ac
// Script Disassembly: OP_DUP OP_BLAKE2B 128004ff2fcaf13b2b91eb654b1dc2b674f7ec6108734973bb7b856ce9efd8c2 OP_EQUALVERIFY OP_CHECKSIG
// Script Hex: 202454a285d8566b0cb2792919536ee0f1b6f69b58ba59e9850ecbc91eef722daeac
// Script Disassembly: 2454a285d8566b0cb2792919536ee0f1b6f69b58ba59e9850ecbc91eef722dae OP_CHECKSIG
}
// This example demonstrates extracting information from a standard public key
// script.
func ExampleExtractScriptPubKeyAddress() {
// Start with a standard pay-to-pubkey-hash script.
scriptHex := "76aa20128004ff2fcaf13b2b91eb65128004ff2fcaf13b2b91eb654b1dc2b674f7ec6188ac"
// Start with a standard pay-to-pubkey script.
scriptHex := "2089ac24ea10bb751af4939623ccc5e550d96842b64e8fca0f63e94b4373fd555eac"
script, err := hex.DecodeString(scriptHex)
if err != nil {
fmt.Println(err)
@ -74,6 +74,6 @@ func ExampleExtractScriptPubKeyAddress() {
fmt.Println("Address:", address)
// Output:
// Script Class: pubkeyhash
// Address: kaspa:qqfgqp8l9l90zwetj84k2y5qqnljljh38v4er6m9fvwu9dn57lkxztu8quj75
// Script Class: pubkey
// Address: kaspa:qzy6cf82zzah2xh5jwtz8nx9u4gdj6zzke8gljs0v055ksmnl424u6fv7ajrs
}

View File

@ -48,16 +48,7 @@ func SignatureScript(tx *externalapi.DomainTransaction, idx int, hashType consen
return nil, err
}
pk, err := privKey.SchnorrPublicKey()
if err != nil {
return nil, err
}
pkData, err := pk.Serialize()
if err != nil {
return nil, err
}
return NewScriptBuilder().AddData(sig).AddData(pkData[:]).Script()
return NewScriptBuilder().AddData(sig).Script()
}
func sign(dagParams *dagconfig.Params, tx *externalapi.DomainTransaction, idx int,
@ -71,7 +62,7 @@ func sign(dagParams *dagconfig.Params, tx *externalapi.DomainTransaction, idx in
}
switch class {
case PubKeyHashTy:
case PubKeyTy:
// look up key for address
key, err := kdb.GetKey(address)
if err != nil {

View File

@ -143,7 +143,7 @@ func TestSignTxOutput(t *testing.T) {
if err != nil {
t.Fatal(err)
}
// Pay to Pubkey Hash (merging with correct)
// Pay to Pubkey (merging with correct)
for _, hashType := range hashTypes {
for _, input := range tx.Inputs {
input.UTXOEntry = utxo.NewUTXOEntry(500, scriptPubKey, false, 100)
@ -180,14 +180,14 @@ func TestSignTxOutput(t *testing.T) {
err = checkScripts(msg, tx, i, sigScript, scriptPubKey)
if err != nil {
t.Errorf("twice signed script invalid for "+
t.Fatalf("twice signed script invalid for "+
"%s: %v", msg, err)
break
}
}
}
// Pay to Pubkey Hash (compressed)
// Pay to Pubkey
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
@ -213,8 +213,7 @@ func TestSignTxOutput(t *testing.T) {
break
}
address, err := util.NewAddressPubKeyHash(
util.HashBlake2b(serializedPubKey[:]), util.Bech32PrefixKaspaTest)
address, err := util.NewAddressPublicKey(serializedPubKey[:], util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
@ -238,7 +237,7 @@ func TestSignTxOutput(t *testing.T) {
}
}
// Pay to Pubkey Hash with duplicate merge
// Pay to Pubkey with duplicate merge
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
@ -264,8 +263,7 @@ func TestSignTxOutput(t *testing.T) {
break
}
address, err := util.NewAddressPubKeyHash(
util.HashBlake2b(serializedPubKey[:]), util.Bech32PrefixKaspaTest)
address, err := util.NewAddressPublicKey(serializedPubKey[:], util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
@ -316,7 +314,7 @@ func TestSignTxOutput(t *testing.T) {
// As before, but with p2sh now.
// Pay to Pubkey Hash
// Pay to Pubkey
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
@ -342,8 +340,7 @@ func TestSignTxOutput(t *testing.T) {
break
}
address, err := util.NewAddressPubKeyHash(
util.HashBlake2b(serializedPubKey[:]), util.Bech32PrefixKaspaTest)
address, err := util.NewAddressPublicKey(serializedPubKey[:], util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
@ -381,7 +378,7 @@ func TestSignTxOutput(t *testing.T) {
}
}
// Pay to Pubkey Hash (compressed) with duplicate merge
// Pay to Pubkey with duplicate merge
for _, hashType := range hashTypes {
for i := range tx.Inputs {
msg := fmt.Sprintf("%d:%d", hashType, i)
@ -407,8 +404,7 @@ func TestSignTxOutput(t *testing.T) {
break
}
address, err := util.NewAddressPubKeyHash(
util.HashBlake2b(serializedPubKey[:]), util.Bech32PrefixKaspaTest)
address, err := util.NewAddressPublicKey(serializedPubKey[:], util.Bech32PrefixKaspaTest)
if err != nil {
t.Errorf("failed to make address for %s: %v",
msg, err)
@ -474,7 +470,7 @@ func TestSignTxOutput(t *testing.T) {
}
func generateKeys() (keyPair *secp256k1.SchnorrKeyPair, scriptPublicKey *externalapi.ScriptPublicKey,
addressPubKeyHash *util.AddressPubKeyHash, err error) {
addressPubKeyHash *util.AddressPublicKey, err error) {
key, err := secp256k1.GenerateSchnorrKeyPair()
if err != nil {
@ -490,8 +486,7 @@ func generateKeys() (keyPair *secp256k1.SchnorrKeyPair, scriptPublicKey *externa
if err != nil {
return nil, nil, nil, errors.Errorf("failed to serialize a pubkey for %s: %s", pubKey, err)
}
address, err := util.NewAddressPubKeyHash(
util.HashBlake2b(serializedPubKey[:]), util.Bech32PrefixKaspaTest)
address, err := util.NewAddressPublicKey(serializedPubKey[:], util.Bech32PrefixKaspaTest)
if err != nil {
return nil, nil, nil, errors.Errorf("failed to make address for %s: %s", serializedPubKey, err)
}
@ -534,12 +529,10 @@ var (
oldCompressedScriptPubKey = &externalapi.ScriptPublicKey{[]byte{0x76, 0xa9, 0x14, 0x27, 0x4d, 0x9f, 0x7f,
0x61, 0x7e, 0x7c, 0x7a, 0x1c, 0x1f, 0xb2, 0x75, 0x79, 0x10,
0x43, 0x65, 0x68, 0x27, 0x9d, 0x86, 0x88, 0xac}, 0}
p2pkhScriptPubKey = &externalapi.ScriptPublicKey{[]byte{0x76, 0xaa, 0x20,
0x51, 0x9c, 0x25, 0xca, 0x95, 0xa0, 0xd8, 0xcd,
0xf5, 0xb8, 0x3f, 0x96, 0xa1, 0x5e, 0x8c, 0x1a,
0xae, 0x33, 0xeb, 0x50, 0xc8, 0x66, 0xc9, 0xd0,
0xa5, 0xce, 0x3e, 0x5f, 0x6b, 0x3b, 0x38, 0x8d,
0x88, 0xac}, 0}
p2pkScriptPubKey = &externalapi.ScriptPublicKey{[]byte{0x20, 0xb2, 0x52, 0xf0, 0x49, 0x85, 0x78, 0x03, 0x03,
0xc8, 0x7d, 0xce, 0x51, 0x7f, 0xa8, 0x69, 0x0b,
0x91, 0x95, 0xf4, 0xf3, 0x5c, 0x26, 0x73, 0x05,
0x05, 0xa2, 0xee, 0xbc, 0x09, 0x38, 0x34, 0x3a, 0xac}, 0}
shortScriptPubKey = &externalapi.ScriptPublicKey{[]byte{0x76, 0xa9, 0x14, 0xd1, 0x7c, 0xb5,
0xeb, 0xa4, 0x02, 0xcb, 0x68, 0xe0, 0x69, 0x56, 0xbf, 0x32,
0x53, 0x90, 0x0e, 0x0a, 0x88, 0xac}, 0}
@ -638,7 +631,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -654,7 +647,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -663,7 +656,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal + fee,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -679,7 +672,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -695,7 +688,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -711,7 +704,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -727,7 +720,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: false,
inputValidates: false,
@ -743,7 +736,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: false,
inputValidates: false,
@ -759,7 +752,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -768,7 +761,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal + fee,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -784,7 +777,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,
@ -793,7 +786,7 @@ var sigScriptTests = []tstSigScript{
{
txout: &externalapi.DomainTransactionOutput{
Value: coinbaseVal + fee,
ScriptPublicKey: p2pkhScriptPubKey,
ScriptPublicKey: p2pkScriptPubKey,
},
sigscriptGenerates: true,
inputValidates: true,

View File

@ -21,7 +21,7 @@ type ScriptClass byte
// Classes of script payment known about in the blockDAG.
const (
NonStandardTy ScriptClass = iota // None of the recognized forms.
PubKeyHashTy // Pay pubkey hash.
PubKeyTy // Pay to pubkey.
ScriptHashTy // Pay to script hash.
)
@ -29,7 +29,7 @@ const (
// script class.
var scriptClassToName = []string{
NonStandardTy: "nonstandard",
PubKeyHashTy: "pubkeyhash",
PubKeyTy: "pubkey",
ScriptHashTy: "scripthash",
}
@ -43,23 +43,20 @@ func (t ScriptClass) String() string {
return scriptClassToName[t]
}
// isPubkeyHash returns true if the script passed is a pay-to-pubkey-hash
// isPayToPubkey returns true if the script passed is a pay-to-pubkey
// transaction, false otherwise.
func isPubkeyHash(pops []parsedOpcode) bool {
return len(pops) == 5 &&
pops[0].opcode.value == OpDup &&
pops[1].opcode.value == OpBlake2b &&
pops[2].opcode.value == OpData32 &&
pops[3].opcode.value == OpEqualVerify &&
pops[4].opcode.value == OpCheckSig
func isPayToPubkey(pops []parsedOpcode) bool {
return len(pops) == 2 &&
pops[0].opcode.value == OpData32 &&
pops[1].opcode.value == OpCheckSig
}
// scriptType returns the type of the script being inspected from the known
// standard types.
func typeOfScript(pops []parsedOpcode) ScriptClass {
if isPubkeyHash(pops) {
return PubKeyHashTy
if isPayToPubkey(pops) {
return PubKeyTy
} else if isScriptHash(pops) {
return ScriptHashTy
}
@ -85,8 +82,8 @@ func GetScriptClass(script []byte) ScriptClass {
func expectedInputs(pops []parsedOpcode, class ScriptClass) int {
switch class {
case PubKeyHashTy:
return 2
case PubKeyTy:
return 1
case ScriptHashTy:
// Not including script. That is handled by the caller.
@ -169,12 +166,13 @@ func CalcScriptInfo(sigScript, scriptPubKey []byte, isP2SH bool) (*ScriptInfo, e
return si, nil
}
// payToPubKeyHashScript creates a new script to pay a transaction
// output to a 20-byte pubkey hash. It is expected that the input is a valid
// payToPubKeyScript creates a new script to pay a transaction
// output to a 32-byte pubkey. It is expected that the input is a valid
// hash.
func payToPubKeyHashScript(pubKeyHash []byte) ([]byte, error) {
return NewScriptBuilder().AddOp(OpDup).AddOp(OpBlake2b).
AddData(pubKeyHash).AddOp(OpEqualVerify).AddOp(OpCheckSig).
func payToPubKeyScript(pubKey []byte) ([]byte, error) {
return NewScriptBuilder().
AddData(pubKey).
AddOp(OpCheckSig).
Script()
}
@ -190,12 +188,12 @@ func payToScriptHashScript(scriptHash []byte) ([]byte, error) {
func PayToAddrScript(addr util.Address) (*externalapi.ScriptPublicKey, error) {
const nilAddrErrStr = "unable to generate payment script for nil address"
switch addr := addr.(type) {
case *util.AddressPubKeyHash:
case *util.AddressPublicKey:
if addr == nil {
return nil, scriptError(ErrUnsupportedAddress,
nilAddrErrStr)
}
script, err := payToPubKeyHashScript(addr.ScriptAddress())
script, err := payToPubKeyScript(addr.ScriptAddress())
if err != nil {
return nil, err
}
@ -276,12 +274,12 @@ func ExtractScriptPubKeyAddress(scriptPubKey *externalapi.ScriptPublicKey, dagPa
scriptClass := typeOfScript(pops)
switch scriptClass {
case PubKeyHashTy:
// A pay-to-pubkey-hash script is of the form:
// OP_DUP OP_BLAKE2B <hash> OP_EQUALVERIFY OP_CHECKSIG
// Therefore the pubkey hash is the 3rd item on the stack.
// If the pubkey hash is invalid for some reason, return a nil address.
addr, err := util.NewAddressPubKeyHash(pops[2].data,
case PubKeyTy:
// A pay-to-pubkey script is of the form:
// <pubkey> OP_CHECKSIG
// Therefore the pubkey is the first item on the stack.
// If the pubkey is invalid for some reason, return a nil address.
addr, err := util.NewAddressPublicKey(pops[0].data,
dagParams.Prefix)
if err != nil {
return scriptClass, nil, nil

View File

@ -28,14 +28,14 @@ func mustParseShortForm(script string, version uint16) []byte {
return s
}
// newAddressPubKeyHash returns a new util.AddressPubKeyHash from the
// provided hash. It panics if an error occurs. This is only used in the tests
// newAddressPublicKey returns a new util.AddressPublicKey from the
// provided public key. It panics if an error occurs. This is only used in the tests
// as a helper since the only way it can fail is if there is an error in the
// test source code.
func newAddressPubKeyHash(pkHash []byte) util.Address {
addr, err := util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixKaspa)
func newAddressPublicKey(publicKey []byte) util.Address {
addr, err := util.NewAddressPublicKey(publicKey, util.Bech32PrefixKaspa)
if err != nil {
panic("invalid public key hash in test source")
panic("invalid public key in test source")
}
return addr
@ -67,15 +67,13 @@ func TestExtractScriptPubKeyAddrs(t *testing.T) {
class ScriptClass
}{
{
name: "standard p2pkh",
name: "standard p2pk",
script: &externalapi.ScriptPublicKey{
Script: hexToBytes("76aa20ad06dd6ddee55cbca9a9e3713bd" +
"7587509a30564ad06dd6ddee55cbca9a9e37188ac"),
Script: hexToBytes("202454a285d8566b0cb2792919536ee0f1b6f69b58ba59e9850ecbc91eef722daeac"),
Version: 0,
},
addr: newAddressPubKeyHash(hexToBytes("ad06dd6ddee5" +
"5cbca9a9e3713bd7587509a30564ad06dd6ddee55cbca9a9e371")),
class: PubKeyHashTy,
addr: newAddressPublicKey(hexToBytes("2454a285d8566b0cb2792919536ee0f1b6f69b58ba59e9850ecbc91eef722dae")),
class: PubKeyTy,
},
{
name: "standard p2sh",
@ -216,8 +214,8 @@ func TestCalcScriptInfo(t *testing.T) {
{
// Invented scripts, the hashes do not match
name: "p2sh standard script",
sigScript: "1 81 DATA_37 DUP BLAKE2B DATA_32 0x010203" +
"0405060708090a0b0c0d0e0f1011121314fe441065b6532231de2fac56 EQUALVERIFY " +
sigScript: "1 81 DATA_34 DATA_32 0x010203" +
"0405060708090a0b0c0d0e0f1011121314fe441065b6532231de2fac56 " +
"CHECKSIG",
scriptPubKey: "BLAKE2B DATA_32 0xfe441065b6532231de2fac56" +
"3152205ec4f59c74fe441065b6532231de2fac56 EQUAL",
@ -225,7 +223,7 @@ func TestCalcScriptInfo(t *testing.T) {
scriptInfo: ScriptInfo{
ScriptPubKeyClass: ScriptHashTy,
NumInputs: 3,
ExpectedInputs: 3, // nonstandard p2sh.
ExpectedInputs: 2, // nonstandard p2sh.
SigOps: 1,
},
},
@ -303,10 +301,10 @@ func (b *bogusAddress) Prefix() util.Bech32Prefix {
func TestPayToAddrScript(t *testing.T) {
t.Parallel()
p2pkhMain, err := util.NewAddressPubKeyHash(hexToBytes("e34cce70c86"+
p2pkMain, err := util.NewAddressPublicKey(hexToBytes("e34cce70c86"+
"373273efcc54ce7d2a491bb4a0e84e34cce70c86373273efcc54c"), util.Bech32PrefixKaspa)
if err != nil {
t.Fatalf("Unable to create public key hash address: %v", err)
t.Fatalf("Unable to create public key address: %v", err)
}
p2shMain, err := util.NewAddressScriptHashFromHash(hexToBytes("e8c300"+
@ -325,11 +323,11 @@ func TestPayToAddrScript(t *testing.T) {
expectedVersion uint16
err error
}{
// pay-to-pubkey-hash address on mainnet
// pay-to-pubkey address on mainnet
{
p2pkhMain,
"DUP BLAKE2B DATA_32 0xe34cce70c86373273efcc54ce7d2a4" +
"91bb4a0e84e34cce70c86373273efcc54c EQUALVERIFY CHECKSIG",
p2pkMain,
"DATA_32 0xe34cce70c86373273efcc54ce7d2a4" +
"91bb4a0e84e34cce70c86373273efcc54c CHECKSIG",
0,
nil,
},
@ -343,7 +341,7 @@ func TestPayToAddrScript(t *testing.T) {
},
// Supported address types with nil pointers.
{(*util.AddressPubKeyHash)(nil), "", 0, errUnsupportedAddress},
{(*util.AddressPublicKey)(nil), "", 0, errUnsupportedAddress},
{(*util.AddressScriptHash)(nil), "", 0, errUnsupportedAddress},
// Unsupported address type.
@ -393,16 +391,14 @@ var scriptClassTests = []struct {
// p2pk
{
name: "Pay Pubkey",
script: "DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" +
"97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e16" +
"0bfa9b8b64f9d4c03f999b8643f656b412a3 CHECKSIG",
class: NonStandardTy,
script: "DATA_32 0x89ac24ea10bb751af4939623ccc5e550d96842b64e8fca0f63e94b4373fd555e CHECKSIG",
class: PubKeyTy,
},
{
name: "Pay PubkeyHash",
script: "DUP BLAKE2B DATA_32 0x660d4ef3a743e3e696ad990364e55543e3e696ad990364e555e555" +
"c271ad504b EQUALVERIFY CHECKSIG",
class: PubKeyHashTy,
class: NonStandardTy,
},
// mutlisig
{
@ -513,9 +509,9 @@ func TestStringifyClass(t *testing.T) {
stringed: "nonstandard",
},
{
name: "pubkeyhash",
class: PubKeyHashTy,
stringed: "pubkeyhash",
name: "pubkey",
class: PubKeyTy,
stringed: "pubkey",
},
{
name: "scripthash",

View File

@ -38,8 +38,8 @@ func main() {
// later...
// Create and print new payment address, specific to the active network.
pubKeyHash := make([]byte, 20)
addr, err := util.NewAddressPubKeyHash(pubKeyHash, dagParams)
pubKey := make([]byte, 32)
addr, err := util.NewAddressPubKey(pubKey, dagParams)
if err != nil {
log.Fatal(err)
}

View File

@ -46,8 +46,8 @@ variable (either directly, or hidden in a library call).
// later...
// Create and print new payment address, specific to the active network.
pubKeyHash := make([]byte, 20)
addr, err := util.NewAddressPubKeyHash(pubKeyHash, dagParams)
pubKey := make([]byte, 32)
addr, err := util.NewAddressPubKey(pubKey, dagParams)
if err != nil {
log.Fatal(err)
}

View File

@ -127,43 +127,18 @@ func isDust(txOut *consensusexternalapi.DomainTransactionOutput, minRelayTxFee u
// input script to redeem it. Since there is no input script
// to redeem it yet, use the minimum size of a typical input script.
//
// Pay-to-pubkey-hash bytes breakdown:
//
// Output to hash (34 bytes):
// 8 value, 1 script len, 25 script [1 OP_DUP, 1 OP_HASH_160,
// 1 OP_DATA_20, 20 hash, 1 OP_EQUALVERIFY, 1 OP_CHECKSIG]
//
// Input with compressed pubkey (148 bytes):
// 36 prev outpoint, 1 script len, 107 script [1 OP_DATA_72, 72 sig,
// 1 OP_DATA_33, 33 compressed pubkey], 4 sequence
//
// Input with uncompressed pubkey (180 bytes):
// 36 prev outpoint, 1 script len, 139 script [1 OP_DATA_72, 72 sig,
// 1 OP_DATA_65, 65 compressed pubkey], 4 sequence
//
// Pay-to-pubkey bytes breakdown:
//
// Output to compressed pubkey (44 bytes):
// 8 value, 1 script len, 35 script [1 OP_DATA_33,
// 33 compressed pubkey, 1 OP_CHECKSIG]
// Output to pubkey (43 bytes):
// 8 value, 1 script len, 34 script [1 OP_DATA_32,
// 32 pubkey, 1 OP_CHECKSIG]
//
// Output to uncompressed pubkey (76 bytes):
// 8 value, 1 script len, 67 script [1 OP_DATA_65, 65 pubkey,
// 1 OP_CHECKSIG]
// Input (105 bytes):
// 36 prev outpoint, 1 script len, 64 script [1 OP_DATA_64,
// 64 sig], 4 sequence
//
// Input (114 bytes):
// 36 prev outpoint, 1 script len, 73 script [1 OP_DATA_72,
// 72 sig], 4 sequence
//
// Theoretically this could examine the script type of the output script
// and use a different size for the typical input script size for
// pay-to-pubkey vs pay-to-pubkey-hash inputs per the above breakdowns,
// but the only combination which is less than the value chosen is
// a pay-to-pubkey script with a compressed pubkey, which is not very
// common.
//
// The most common scripts are pay-to-pubkey-hash, and as per the above
// breakdown, the minimum size of a p2pkh input script is 148 bytes. So
// The most common scripts are pay-to-pubkey, and as per the above
// breakdown, the minimum size of a p2pk input script is 148 bytes. So
// that figure is used.
totalSize := estimatedsize.TransactionOutputEstimatedSerializedSize(txOut) + 148
@ -172,7 +147,7 @@ func isDust(txOut *consensusexternalapi.DomainTransactionOutput, minRelayTxFee u
// minFreeTxRelayFee is in sompi/KB, so multiply by 1000 to
// convert to bytes.
//
// Using the typical values for a pay-to-pubkey-hash transaction from
// Using the typical values for a pay-to-pubkey transaction from
// the breakdown above and the default minimum free transaction relay
// fee of 1000, this equates to values less than 546 sompi being
// considered dust.

View File

@ -179,9 +179,9 @@ func TestCheckTransactionStandard(t *testing.T) {
Sequence: constants.MaxTxInSequenceNum,
}
addrHash := [32]byte{0x01}
addr, err := util.NewAddressPubKeyHash(addrHash[:], util.Bech32PrefixKaspaTest)
addr, err := util.NewAddressPublicKey(addrHash[:], util.Bech32PrefixKaspaTest)
if err != nil {
t.Fatalf("NewAddressPubKeyHash: unexpected error: %v", err)
t.Fatalf("NewAddressPublicKey: unexpected error: %v", err)
}
dummyScriptPublicKey, err := txscript.PayToAddrScript(addr)
if err != nil {
@ -200,7 +200,7 @@ func TestCheckTransactionStandard(t *testing.T) {
code RejectCode
}{
{
name: "Typical pay-to-pubkey-hash transaction",
name: "Typical pay-to-pubkey transaction",
tx: consensusexternalapi.DomainTransaction{Version: 0, Inputs: []*consensusexternalapi.DomainTransactionInput{&dummyTxIn}, Outputs: []*consensusexternalapi.DomainTransactionOutput{&dummyTxOut}},
height: 300000,
isStandard: true,

View File

@ -15,7 +15,6 @@ import (
"github.com/kaspanet/kaspad/util"
"github.com/kaspanet/kaspad/util/panics"
"github.com/pkg/errors"
"golang.org/x/crypto/blake2b"
)
const (
@ -178,8 +177,8 @@ func useDirOrCreateTemp(dataDir, tempName string) (string, error) {
}
func mineOnTips(client *rpc.Client) (appmessage.RejectReason, error) {
fakePublicKeyHash := make([]byte, blake2b.Size256)
addr, err := util.NewAddressPubKeyHash(fakePublicKeyHash, activeConfig().NetParams().Prefix)
fakePublicKey := make([]byte, util.PublicKeySize)
addr, err := util.NewAddressPublicKey(fakePublicKey, activeConfig().NetParams().Prefix)
if err != nil {
return appmessage.RejectReasonNone, err
}

View File

@ -97,7 +97,7 @@ func generateAddress() (util.Address, error) {
return nil, err
}
return util.NewAddressPubKeyHashFromPublicKey(pubKeySerialized[:], activeConfig().ActiveNetParams.Prefix)
return util.NewAddressPublicKey(pubKeySerialized[:], activeConfig().ActiveNetParams.Prefix)
}
func areTipsAreEqual(resultA, resultB *appmessage.GetBlockDAGInfoResponseMessage) bool {

View File

@ -18,14 +18,14 @@ const (
rpcAddress2 = "127.0.0.1:12346"
rpcAddress3 = "127.0.0.1:12347"
miningAddress1 = "kaspasim:qr79e37hxdgkn4xjjmfxvqvayc5gsmsql2660d08u9ej9vnc8lzcywr265u64"
miningAddress1PrivateKey = "0ec5d7308f65717f3f0c3e4d962d73056c1c255a16593b3989589281b51ad5bc"
miningAddress1 = "kaspasim:qqqqnc0pxg7qw3qkc7l6sge8kfhsvvyt7mkw8uamtndqup27ftnd6c769gn66"
miningAddress1PrivateKey = "0d81045b0deb2af36a25403c2154c87aa82d89dd337b575bae27ce7f5de53cee"
miningAddress2 = "kaspasim:qpvr825ypd2fzq779yl83zvte2r4wlgxwra625rgthk9jj96d4cxgsegwryhg"
miningAddress2PrivateKey = "2a2e99d4a5c3e6d4add69e7baf66b9c7a2f17e74fad86cbd36a3a6815cecc10e"
miningAddress2 = "kaspasim:qqqqnc0pxg7qw3qkc7l6sge8kfhsvvyt7mkw8uamtndqup27ftnd6c769gn66"
miningAddress2PrivateKey = "0d81045b0deb2af36a25403c2154c87aa82d89dd337b575bae27ce7f5de53cee"
miningAddress3 = "kaspasim:qpvr825ypd2fzq779yl83zvte2r4wlgxwra625rgthk9jj96d4cxgsegwryhg"
miningAddress3PrivateKey = "2a2e99d4a5c3e6d4add69e7baf66b9c7a2f17e74fad86cbd36a3a6815cecc10e"
miningAddress3 = "kaspasim:qqq754f2gdcjcnykwuwwr60c82rh5u6mxxe7yqxljnrxz9fu0h95kduq9ezng"
miningAddress3PrivateKey = "f6c8f31fd359cbb97007034780bc4021f6ad01c6bc10499b79849efd4cc7ca39"
defaultTimeout = 10 * time.Second
)

View File

@ -20,8 +20,8 @@ var (
)
const (
// PubKeyHash addresses always have the version byte set to 0.
pubKeyHashAddrID = 0x00
// PubKey addresses always have the version byte set to 0.
pubKeyAddrID = 0x00
// ScriptHash addresses always have the version byte set to 8.
scriptHashAddrID = 0x08
@ -79,16 +79,16 @@ func (prefix Bech32Prefix) String() string {
}
// encodeAddress returns a human-readable payment address given a network prefix
// and a blake2b hash which encodes the kaspa network and address type. It is used
// in both pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address
// and a payload which encodes the kaspa network and address type. It is used
// in both pay-to-pubkey (P2PK) and pay-to-script-hash (P2SH) address
// encoding.
func encodeAddress(prefix Bech32Prefix, hash256 []byte, version byte) string {
return bech32.Encode(prefix.String(), hash256[:blake2b.Size256], version)
func encodeAddress(prefix Bech32Prefix, payload []byte, version byte) string {
return bech32.Encode(prefix.String(), payload, version)
}
// Address is an interface type for any type of destination a transaction
// output may spend to. This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash
// (P2PKH), and pay-to-script-hash (P2SH). Address is designed to be generic
// output may spend to. This includes pay-to-pubkey (P2PK)
// and pay-to-script-hash (P2SH). Address is designed to be generic
// enough that other kinds of addresses may be added in the future without
// changing the decoding and encoding API.
type Address interface {
@ -98,7 +98,7 @@ type Address interface {
// Please note that String differs subtly from EncodeAddress: String
// will return the value as a string without any conversion, while
// EncodeAddress may convert destination types (for example,
// converting pubkeys to P2PKH addresses) before encoding as a
// converting pubkeys to P2PK addresses) before encoding as a
// payment address string.
String() string
@ -139,95 +139,79 @@ func DecodeAddress(addr string, expectedPrefix Bech32Prefix) (Address, error) {
prefix)
}
// Switch on decoded length to determine the type.
switch len(decoded) {
case blake2b.Size256: // P2PKH or P2SH
switch version {
case pubKeyHashAddrID:
return newAddressPubKeyHash(prefix, decoded)
case pubKeyAddrID:
return newAddressPubKey(prefix, decoded)
case scriptHashAddrID:
return newAddressScriptHashFromHash(prefix, decoded)
default:
return nil, ErrUnknownAddressType
}
default:
return nil, errors.New("decoded address is of unknown size")
}
}
// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH)
// PublicKeySize is the public key size for a schnorr public key
const PublicKeySize = 32
// AddressPublicKey is an Address for a pay-to-pubkey (P2PK)
// transaction.
type AddressPubKeyHash struct {
type AddressPublicKey struct {
prefix Bech32Prefix
hash [blake2b.Size256]byte
publicKey [PublicKeySize]byte
}
// NewAddressPubKeyHashFromPublicKey returns a new AddressPubKeyHash from given public key
func NewAddressPubKeyHashFromPublicKey(publicKey []byte, prefix Bech32Prefix) (*AddressPubKeyHash, error) {
pkHash := HashBlake2b(publicKey)
return newAddressPubKeyHash(prefix, pkHash)
}
// NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash mustbe 20
// NewAddressPublicKey returns a new AddressPublicKey. publicKey must be 32
// bytes.
func NewAddressPubKeyHash(pkHash []byte, prefix Bech32Prefix) (*AddressPubKeyHash, error) {
return newAddressPubKeyHash(prefix, pkHash)
func NewAddressPublicKey(publicKey []byte, prefix Bech32Prefix) (*AddressPublicKey, error) {
return newAddressPubKey(prefix, publicKey)
}
// newAddressPubKeyHash is the internal API to create a pubkey hash address
// newAddressPubKey is the internal API to create a pubkey address
// with a known leading identifier byte for a network, rather than looking
// it up through its parameters. This is useful when creating a new address
// structure from a string encoding where the identifier byte is already
// known.
func newAddressPubKeyHash(prefix Bech32Prefix, pkHash []byte) (*AddressPubKeyHash, error) {
// Check for a valid pubkey hash length.
if len(pkHash) != blake2b.Size256 {
return nil, errors.Errorf("pkHash must be %d bytes", blake2b.Size256)
func newAddressPubKey(prefix Bech32Prefix, publicKey []byte) (*AddressPublicKey, error) {
// Check for a valid pubkey length.
if len(publicKey) != PublicKeySize {
return nil, errors.Errorf("publicKey must be %d bytes", PublicKeySize)
}
addr := &AddressPubKeyHash{prefix: prefix}
copy(addr.hash[:], pkHash)
addr := &AddressPublicKey{prefix: prefix}
copy(addr.publicKey[:], publicKey)
return addr, nil
}
// EncodeAddress returns the string encoding of a pay-to-pubkey-hash
// EncodeAddress returns the string encoding of a pay-to-pubkey
// address. Part of the Address interface.
func (a *AddressPubKeyHash) EncodeAddress() string {
return encodeAddress(a.prefix, a.hash[:], pubKeyHashAddrID)
func (a *AddressPublicKey) EncodeAddress() string {
return encodeAddress(a.prefix, a.publicKey[:], pubKeyAddrID)
}
// ScriptAddress returns the bytes to be included in a txout script to pay
// to a pubkey hash. Part of the Address interface.
func (a *AddressPubKeyHash) ScriptAddress() []byte {
return a.hash[:]
// to a pubkey. Part of the Address interface.
func (a *AddressPublicKey) ScriptAddress() []byte {
return a.publicKey[:]
}
// IsForPrefix returns whether or not the pay-to-pubkey-hash address is associated
// IsForPrefix returns whether or not the pay-to-pubkey address is associated
// with the passed kaspa network.
func (a *AddressPubKeyHash) IsForPrefix(prefix Bech32Prefix) bool {
func (a *AddressPublicKey) IsForPrefix(prefix Bech32Prefix) bool {
return a.prefix == prefix
}
// Prefix returns the prefix for this address
func (a *AddressPubKeyHash) Prefix() Bech32Prefix {
func (a *AddressPublicKey) Prefix() Bech32Prefix {
return a.prefix
}
// String returns a human-readable string for the pay-to-pubkey-hash address.
// String returns a human-readable string for the pay-to-pubkey address.
// This is equivalent to calling EncodeAddress, but is provided so the type can
// be used as a fmt.Stringer.
func (a *AddressPubKeyHash) String() string {
func (a *AddressPublicKey) String() string {
return a.EncodeAddress()
}
// HashBlake2b returns the underlying array of the pubkey hash. This can be useful
// when an array is more appropiate than a slice (for example, when used as map
// keys).
func (a *AddressPubKeyHash) HashBlake2b() *[blake2b.Size256]byte {
return &a.hash
}
// AddressScriptHash is an Address for a pay-to-script-hash (P2SH)
// AddressScriptHash is an Address for a pay-to-script-publicKey (P2SH)
// transaction.
type AddressScriptHash struct {
prefix Bech32Prefix

View File

@ -26,99 +26,99 @@ func TestAddresses(t *testing.T) {
passedPrefix util.Bech32Prefix
expectedPrefix util.Bech32Prefix
}{
// Positive P2PKH tests.
// Positive P2PK tests.
{
name: "mainnet p2pkh",
name: "mainnet p2pk",
addr: "kaspa:qr35ennsep3hxfe7lnz5ee7j5jgmkjswsn35ennsep3hxfe7ln35cdv0dy335",
encoded: "kaspa:qr35ennsep3hxfe7lnz5ee7j5jgmkjswsn35ennsep3hxfe7ln35cdv0dy335",
valid: true,
result: util.TstAddressPubKeyHash(
result: util.TstAddressPubKey(
util.Bech32PrefixKaspa,
[blake2b.Size256]byte{
[util.PublicKeySize]byte{
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84,
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xe3, 0x4c,
}),
f: func() (util.Address, error) {
pkHash := []byte{
publicKey := []byte{
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xc5, 0x4c, 0xe7, 0xd2, 0xa4, 0x91, 0xbb, 0x4a, 0x0e, 0x84,
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xe3, 0x4c}
return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixKaspa)
return util.NewAddressPublicKey(publicKey, util.Bech32PrefixKaspa)
},
passedPrefix: util.Bech32PrefixUnknown,
expectedPrefix: util.Bech32PrefixKaspa,
},
{
name: "mainnet p2pkh 2",
name: "mainnet p2pk 2",
addr: "kaspa:qq80qvqs0lfxuzmt7sz3909ze6camq9d4t35ennsep3hxfe7ln35cvfqgz3z8",
encoded: "kaspa:qq80qvqs0lfxuzmt7sz3909ze6camq9d4t35ennsep3hxfe7ln35cvfqgz3z8",
valid: true,
result: util.TstAddressPubKeyHash(
result: util.TstAddressPubKey(
util.Bech32PrefixKaspa,
[blake2b.Size256]byte{
[util.PublicKeySize]byte{
0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4,
0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa,
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xe3, 0x4c,
}),
f: func() (util.Address, error) {
pkHash := []byte{
publicKey := []byte{
0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b, 0xf4,
0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad, 0xaa,
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xe3, 0x4c,
}
return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixKaspa)
return util.NewAddressPublicKey(publicKey, util.Bech32PrefixKaspa)
},
passedPrefix: util.Bech32PrefixKaspa,
expectedPrefix: util.Bech32PrefixKaspa,
},
{
name: "testnet p2pkh",
name: "testnet p2pk",
addr: "kaspatest:qputx94qseratdmjs0j395mq8u03er0x3l35ennsep3hxfe7ln35ckquw528z",
encoded: "kaspatest:qputx94qseratdmjs0j395mq8u03er0x3l35ennsep3hxfe7ln35ckquw528z",
valid: true,
result: util.TstAddressPubKeyHash(
result: util.TstAddressPubKey(
util.Bech32PrefixKaspaTest,
[blake2b.Size256]byte{
[util.PublicKeySize]byte{
0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83,
0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f,
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xe3, 0x4c,
}),
f: func() (util.Address, error) {
pkHash := []byte{
publicKey := []byte{
0x78, 0xb3, 0x16, 0xa0, 0x86, 0x47, 0xd5, 0xb7, 0x72, 0x83,
0xe5, 0x12, 0xd3, 0x60, 0x3f, 0x1f, 0x1c, 0x8d, 0xe6, 0x8f,
0xe3, 0x4c, 0xce, 0x70, 0xc8, 0x63, 0x73, 0x27, 0x3e, 0xfc,
0xe3, 0x4c,
}
return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixKaspaTest)
return util.NewAddressPublicKey(publicKey, util.Bech32PrefixKaspaTest)
},
passedPrefix: util.Bech32PrefixKaspaTest,
expectedPrefix: util.Bech32PrefixKaspaTest,
},
// Negative P2PKH tests.
// Negative P2PK tests.
{
name: "p2pkh wrong hash length",
name: "p2pk wrong public key length",
addr: "",
valid: false,
f: func() (util.Address, error) {
pkHash := []byte{
publicKey := []byte{
0x00, 0x0e, 0xf0, 0x30, 0x10, 0x7f, 0xd2, 0x6e, 0x0b, 0x6b,
0xf4, 0x05, 0x12, 0xbc, 0xa2, 0xce, 0xb1, 0xdd, 0x80, 0xad,
0xaa}
return util.NewAddressPubKeyHash(pkHash, util.Bech32PrefixKaspa)
return util.NewAddressPublicKey(publicKey, util.Bech32PrefixKaspa)
},
passedPrefix: util.Bech32PrefixKaspa,
expectedPrefix: util.Bech32PrefixKaspa,
},
{
name: "p2pkh bad checksum",
name: "p2pk bad checksum",
addr: "kaspa:qr35ennsep3hxfe7lnz5ee7j5jgmkjswss74as46gx",
valid: false,
passedPrefix: util.Bech32PrefixKaspa,
@ -270,23 +270,22 @@ func TestAddresses(t *testing.T) {
// Perform type-specific calculations.
var saddr []byte
switch decoded.(type) {
case *util.AddressPubKeyHash:
saddr = util.TstAddressSAddr(encoded)
case *util.AddressPublicKey:
saddr = util.TstAddressSAddrP2PK(encoded)
case *util.AddressScriptHash:
saddr = util.TstAddressSAddr(encoded)
saddr = util.TstAddressSAddrP2SH(encoded)
}
// Check script address, as well as the HashBlake2b method for P2PKH and
// P2SH addresses.
// Check script address, as well as the HashBlake2b method for P2SH addresses.
if !bytes.Equal(saddr, decoded.ScriptAddress()) {
t.Errorf("%v: script addresses do not match:\n%x != \n%x",
test.name, saddr, decoded.ScriptAddress())
return
}
switch a := decoded.(type) {
case *util.AddressPubKeyHash:
if h := a.HashBlake2b()[:]; !bytes.Equal(saddr, h) {
case *util.AddressPublicKey:
if h := a.ScriptAddress()[:]; !bytes.Equal(saddr, h) {
t.Errorf("%v: hashes do not match:\n%x != \n%x",
test.name, saddr, h)
return
@ -357,7 +356,7 @@ func TestDecodeAddressErrorConditions(t *testing.T) {
{
"kaspasim:raskzcg58mth0an",
util.Bech32PrefixKaspaSim,
"decoded address is of unknown size",
"unknown address type",
},
{
"kaspatest:qqq65mvpxcmajeq44n2n8vfn6u9f8l4zsy0xez0tzw",

View File

@ -18,14 +18,14 @@ expensive hashing operations.
Address Overview
The Address interface provides an abstraction for a kaspa address. While the
most common type is a pay-to-pubkey-hash, kaspa already supports others and
most common type is a pay-to-pubkey, kaspa already supports others and
may well support more in the future. This package currently provides
implementations for the pay-to-pubkey-hash, and pay-to-script-hash address
implementations for the pay-to-pubkey, and pay-to-script-hash address
types.
To decode/encode an address:
addrString := "kaspa:qqfgqp8l9l90zwetj84k2jcac2m8falvvyy8xjtnhd"
addrString := "kaspa:qqj9fg59mptxkr9j0y53j5mwurcmda5mtza9n6v9pm9uj8h0wgk6uma5pvumr"
defaultPrefix := util.Bech32PrefixKaspa
addr, err := util.DecodeAddress(addrString, defaultPrefix)
if err != nil {

View File

@ -22,10 +22,10 @@ func TstAppDataDir(goos, appName string, roaming bool) string {
return appDir(goos, appName, roaming)
}
func TstAddressPubKeyHash(prefix Bech32Prefix, hash [blake2b.Size256]byte) *AddressPubKeyHash {
return &AddressPubKeyHash{
func TstAddressPubKey(prefix Bech32Prefix, hash [PublicKeySize]byte) *AddressPublicKey {
return &AddressPublicKey{
prefix: prefix,
hash: hash,
publicKey: hash,
}
}
@ -40,8 +40,15 @@ func TstAddressScriptHash(prefix Bech32Prefix, hash [blake2b.Size256]byte) *Addr
}
// TstAddressSAddr returns the expected script address bytes for
// P2PKH and P2SH kaspa addresses.
func TstAddressSAddr(addr string) []byte {
// P2PK kaspa addresses.
func TstAddressSAddrP2PK(addr string) []byte {
_, decoded, _, _ := bech32.Decode(addr)
return decoded[:PublicKeySize]
}
// TstAddressSAddrP2SH returns the expected script address bytes for
// P2SH kaspa addresses.
func TstAddressSAddrP2SH(addr string) []byte {
_, decoded, _, _ := bech32.Decode(addr)
return decoded[:blake2b.Size256]
}