比特币地址生成算法之P2PKH

 功能代码如下:

import (
	"encoding/hex"
	"errors"
	"github.com/btcsuite/btcutil/base58"
	"github.com/decred/dcrd/dcrec/secp256k1"
)

func NewP2PKH(rawPrivKey []byte, netType string, isCompress bool) (string, error) {
	//先检测函数参数的有效性
	var mapNet = map[string]byte{"testnet":0x6F, "main":0x00}
	if _, ok := mapNet[netType]; !ok {
		return "",errors.New("net type invalid")
	}

	var (
		privKey *secp256k1.PrivateKey
		err error
		pubKey []byte
		hash160 []byte
		hash160WithPrefix []byte
		address []byte
		hash256 [32]byte
	)

	//1. 用私钥生成公钥
	privKey = secp256k1.PrivKeyFromBytes(rawPrivKey)

	//2. 计算公钥
	if isCompress {
		pubKey, _ = hex.DecodeString(NewCompressPubKey(privKey.PubKey().X().Bytes(), privKey.PubKey().Y().Bytes()))
	} else {
		pubKey,_ = hex.DecodeString(NewUncompressPubKey(privKey.PubKey().X().Bytes(), privKey.PubKey().Y().Bytes()))
	}

	//3. 计算公钥的sha256哈希值
	//4. 计算上一步结果的ripemd160哈希值
	if hash160, err = Ripemd160AfterSha256(pubKey); err != nil {
		return "", err
	}

	//5. 取上一步结果,前面加入地址网络前缀
	hash160WithPrefix = append([]byte{mapNet[netType]}, hash160...)

	//6. 取上一步结果,计算SHA256哈希值
	//7. 取上一步结果,在计算SHA256哈希值
	hash256 = Sha256AfterSha256(hash160WithPrefix)

	//8. 取上一步结果的前四个字节,放在第五步结果后面,作为校验
	address = append(hash160WithPrefix, hash256[0:4]...)

	//9. 用base58编码上一步结果
	return base58.Encode(address),nil
}

下面是测试代码:

func TestNewP2PKH(t *testing.T) {
	t.Run("test compressed public key to address", func(t *testing.T) {
		var testcases = []struct{
			originalPrivKey string
			netType string
			address string
		} {
			{
				"a4f228d49910e8ecb53ba6f23f33fbfd2bad442e902ea20b8cf89c473237bf9f",
				"main",
				"127NVqnjf8gB9BFAW2dnQeM6wqmy1gbGtv",
			},
		}
		var err error
		var address string

		for _, oneCase := range testcases {
			privKey,_ := hex.DecodeString(oneCase.originalPrivKey)
			if address,err = NewP2PKH(privKey, oneCase.netType, true);err != nil {
				t.Error(err)
				return
			}
			if address != oneCase.address {
				t.Error("genereate compressed address error")
				t.Error("want: ", oneCase.address)
				t.Error("got:  ", address)
				return
			}
		}
	})
}

工具网站:

下面这个网站可以看到一步一步怎么计算得到最终结果的。BTW,这网站要才能看。

http://gobittest.appspot.com/Address

(全文完)

你可能感兴趣的:(比特币技术研究)