diff --git a/go.mod b/go.mod
index 9f03d3a..1bc6da7 100644
--- a/go.mod
+++ b/go.mod
@@ -3,12 +3,15 @@ module github.com/libsv/go-dpp
go 1.17
require (
- github.com/libsv/go-bc v0.1.11
+ github.com/libsv/go-bc v0.1.20
github.com/libsv/go-bk v0.1.6
- github.com/libsv/go-bt/v2 v2.1.0-beta.4
+ github.com/libsv/go-bt/v2 v2.2.5
github.com/matryer/is v1.4.0
github.com/pkg/errors v0.9.1
github.com/theflyingcodr/govalidator v0.1.3
)
-require golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
+require (
+ github.com/libsv/go-p2p v0.1.3 // indirect
+ golang.org/x/crypto v0.13.0 // indirect
+)
diff --git a/go.sum b/go.sum
index 82f2f76..7d4bcaa 100644
--- a/go.sum
+++ b/go.sum
@@ -1,43 +1,95 @@
-github.com/bitcoinsv/bsvd v0.0.0-20190609155523-4c29707f7173/go.mod h1:BZ1UcC9+tmcDEcdVXgpt13hMczwJxWzpAn68wNs7zRA=
-github.com/bitcoinsv/bsvutil v0.0.0-20181216182056-1d77cf353ea9/go.mod h1:p44KuNKUH5BC8uX4ONEODaHUR4+ibC8todEAOGQEJAM=
+github.com/cbeuw/connutil v0.0.0-20200411215123-966bfaa51ee3/go.mod h1:6jR2SzckGv8hIIS9zWJ160mzGVVOYp4AXZMDtacL6LE=
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/libsv/go-bc v0.1.11 h1:putnzopVpWy5i+HaVSSXya7ot4mLHFOUU39JZUFfBmM=
-github.com/libsv/go-bc v0.1.11/go.mod h1:55OsjWtvaIEXy4w02icUi2lIdThuwqkAiSeF4GPU5tw=
-github.com/libsv/go-bk v0.1.5/go.mod h1:xbDkeFFpP0uyFaPLnP6TwaLpAsHaslZ0LftTdWlB6HI=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/libsv/go-bc v0.1.20 h1:NMH7knygmk8slZcBzoIYLut8DjRNgh8103Md3FzG+W0=
+github.com/libsv/go-bc v0.1.20/go.mod h1:l6epTfcakN8YKId/hrpUzlu1QeT3ODF1MI3DeYhG1O8=
github.com/libsv/go-bk v0.1.6 h1:c9CiT5+64HRDbzxPl1v/oiFmbvWZTuUYqywCf+MBs/c=
github.com/libsv/go-bk v0.1.6/go.mod h1:khJboDoH18FPUaZlzRFKzlVN84d4YfdmlDtdX4LAjQA=
-github.com/libsv/go-bt/v2 v2.1.0-beta.2/go.mod h1:u5g3GmVLffBV8sWvMqHR3JekC51OR9XYvmQp1h/XoiQ=
-github.com/libsv/go-bt/v2 v2.1.0-beta.4 h1:eLp2XKPRnVrcoiGpjK9fsiTK8OT103LNvZ7VUC4mH20=
-github.com/libsv/go-bt/v2 v2.1.0-beta.4/go.mod h1:KbBf6ugGNMtVwtCSUtlSAHoVhbAie4hu2VM97d1ZL8I=
+github.com/libsv/go-bt/v2 v2.2.5 h1:VoggBLMRW9NYoFujqe5bSYKqnw5y+fYfufgERSoubog=
+github.com/libsv/go-bt/v2 v2.2.5/go.mod h1:cV45+jDlPOLfhJLfpLmpQoWzrIvVth9Ao2ZO1f6CcqU=
+github.com/libsv/go-p2p v0.1.3 h1:70v/k7d6mtFPRP8tXYpAMGZNTxqSZAVTbYeTPuTbjTA=
+github.com/libsv/go-p2p v0.1.3/go.mod h1:5+VqOblMYadFH7pmm55PcfbbWcXib8cTh9CHIrrxtZg=
github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
+github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
+github.com/ordishs/go-utils v1.0.24/go.mod h1:k9G7Bbv2GwoOn9fwZx70yM5jwwIymkv+90FUKLudtyc=
+github.com/ordishs/gocore v1.0.33/go.mod h1:Nm48yxIUBuKvVXwLC8bB8aQDNUsBpaoVRTtcmjKlhrQ=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/theflyingcodr/govalidator v0.1.3 h1:eU8P2xZrU2s1FjbtoVW6yDgXG+g2xDM9p3eNPLFKmSk=
github.com/theflyingcodr/govalidator v0.1.3/go.mod h1:E6v0mkRcAVMTa7pC8VkUOtoE8WQ9zQ4/fOwrvtwhOM0=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
-golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck=
+golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/vendor/github.com/libsv/go-bc/.goreleaser.yml b/vendor/github.com/libsv/go-bc/.goreleaser.yml
index 989c429..896c561 100644
--- a/vendor/github.com/libsv/go-bc/.goreleaser.yml
+++ b/vendor/github.com/libsv/go-bc/.goreleaser.yml
@@ -23,12 +23,13 @@ build:
- windows
- darwin
archives:
- - replacements:
- darwin: Darwin
- linux: Linux
- windows: Windows
- 386: i386
- amd64: x86_64
+ - name_template: >-
+ {{- .ProjectName }}_
+ {{- title .Os }}_
+ {{- if eq .Arch "amd64" }}x86_64
+ {{- else if eq .Arch "386" }}i386
+ {{- else }}{{ .Arch }}{{ end }}
+ {{- if .Arm }}v{{ .Arm }}{{ end -}}
checksum:
name_template: 'checksums.txt'
# ---------------------------
diff --git a/vendor/github.com/libsv/go-bc/README.md b/vendor/github.com/libsv/go-bc/README.md
index 81d2a5b..c1275b5 100644
--- a/vendor/github.com/libsv/go-bc/README.md
+++ b/vendor/github.com/libsv/go-bc/README.md
@@ -3,7 +3,7 @@
> The go-to Bitcoin Block Chain (BC) GoLang library
[![Release](https://img.shields.io/github/release-pre/libsv/go-bc.svg?logo=github&style=flat&v=1)](https://github.com/libsv/go-bc/releases)
-[![Build Status](https://img.shields.io/github/workflow/status/libsv/go-bc/run-go-tests?logo=github&v=3)](https://github.com/libsv/go-bc/actions)
+[![Build Status](https://img.shields.io/github/actions/workflow/status/libsv/go-bc/run-tests.yml?logo=github&v=3)](https://github.com/libsv/go-bc/actions)
[![Report](https://goreportcard.com/badge/github.com/libsv/go-bc?style=flat&v=1)](https://goreportcard.com/report/github.com/libsv/go-bc)
[![codecov](https://codecov.io/gh/libsv/go-bc/branch/master/graph/badge.svg?v=1)](https://codecov.io/gh/libsv/go-bc)
[![Go](https://img.shields.io/github/go-mod/go-version/libsv/go-bc?v=1)](https://golang.org/)
diff --git a/vendor/github.com/libsv/go-bc/block.go b/vendor/github.com/libsv/go-bc/block.go
index ce117b9..d52e6e1 100644
--- a/vendor/github.com/libsv/go-bc/block.go
+++ b/vendor/github.com/libsv/go-bc/block.go
@@ -1,3 +1,4 @@
+// Package bc is a bitcoin blockchain library bc = block chain.
package bc
import (
diff --git a/vendor/github.com/libsv/go-bc/blockheader.go b/vendor/github.com/libsv/go-bc/blockheader.go
index 469f1cd..0086c76 100644
--- a/vendor/github.com/libsv/go-bc/blockheader.go
+++ b/vendor/github.com/libsv/go-bc/blockheader.go
@@ -24,12 +24,12 @@ Nonce 32-bit number (starts at 0) 4
// A BlockHeader in the Bitcoin blockchain.
type BlockHeader struct {
- Version uint32
- Time uint32
- Nonce uint32
- HashPrevBlock []byte
- HashMerkleRoot []byte
- Bits []byte
+ Version uint32 `json:"version"`
+ Time uint32 `json:"time"`
+ Nonce uint32 `json:"nonce"`
+ HashPrevBlock []byte `json:"hashPrevBlock"`
+ HashMerkleRoot []byte `json:"merkleRoot"`
+ Bits []byte `json:"bits"`
}
type bhJSON struct {
diff --git a/vendor/github.com/libsv/go-bc/bump.go b/vendor/github.com/libsv/go-bc/bump.go
new file mode 100644
index 0000000..38ff6d9
--- /dev/null
+++ b/vendor/github.com/libsv/go-bc/bump.go
@@ -0,0 +1,251 @@
+package bc
+
+import (
+ "encoding/hex"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math"
+ "sort"
+
+ "github.com/libsv/go-bt/v2"
+ "github.com/libsv/go-p2p/chaincfg/chainhash"
+)
+
+// BUMP data model json format according to BRC-74.
+type BUMP struct {
+ BlockHeight uint64 `json:"blockHeight"`
+ Path [][]leaf `json:"path"`
+}
+
+// It should be written such that the internal bytes are kept for calculations.
+// and the JSON is generated from the internal struct to an external format.
+// leaf represents a leaf in the Merkle tree.
+type leaf struct {
+ Offset *uint64 `json:"offset,omitempty"`
+ Hash *string `json:"hash,omitempty"`
+ Txid *bool `json:"txid,omitempty"`
+ Duplicate *bool `json:"duplicate,omitempty"`
+}
+
+// NewBUMPFromBytes creates a new BUMP from a byte slice.
+func NewBUMPFromBytes(bytes []byte) (*BUMP, error) {
+ bump := &BUMP{}
+
+ // first bytes are the block height.
+ var skip int
+ index, size := bt.NewVarIntFromBytes(bytes[skip:])
+ skip += size
+ bump.BlockHeight = uint64(index)
+
+ // Next byte is the tree height.
+ treeHeight := uint(bytes[skip])
+ skip++
+
+ // We expect tree height levels.
+ bump.Path = make([][]leaf, treeHeight)
+
+ for lv := uint(0); lv < treeHeight; lv++ {
+ // For each level we parse a bunch of nLeaves.
+ n, size := bt.NewVarIntFromBytes(bytes[skip:])
+ skip += size
+ nLeavesAtThisHeight := uint64(n)
+ bump.Path[lv] = make([]leaf, nLeavesAtThisHeight)
+ for lf := uint64(0); lf < nLeavesAtThisHeight; lf++ {
+ // For each leaf we parse the offset, hash, txid and duplicate.
+ offset, size := bt.NewVarIntFromBytes(bytes[skip:])
+ skip += size
+ var l leaf
+ o := uint64(offset)
+ l.Offset = &o
+ flags := bytes[skip]
+ skip++
+ dup := flags&1 > 0
+ txid := flags&2 > 0
+ if dup {
+ l.Duplicate = &dup
+ }
+ if txid {
+ l.Txid = &txid
+ }
+ h := StringFromBytesReverse(bytes[skip : skip+32])
+ l.Hash = &h
+ skip += 32
+ bump.Path[lv][lf] = l
+ }
+ }
+
+ // Sort each of the levels by the offset for consistency.
+ for _, level := range bump.Path {
+ sort.Slice(level, func(i, j int) bool {
+ return *level[i].Offset < *level[j].Offset
+ })
+ }
+
+ return bump, nil
+}
+
+// NewBUMPFromStr creates a BUMP from hex string.
+func NewBUMPFromStr(str string) (*BUMP, error) {
+ bytes, err := hex.DecodeString(str)
+ if err != nil {
+ return nil, err
+ }
+ return NewBUMPFromBytes(bytes)
+}
+
+// NewBUMPFromJSON creates a BUMP from a JSON string.
+func NewBUMPFromJSON(jsonStr string) (*BUMP, error) {
+ bump := &BUMP{}
+ err := json.Unmarshal([]byte(jsonStr), bump)
+ if err != nil {
+ return nil, err
+ }
+ return bump, nil
+}
+
+// Bytes encodes a BUMP as a slice of bytes. BUMP Binary Format according to BRC-74 https://brc.dev/74
+func (bump *BUMP) Bytes() ([]byte, error) {
+ bytes := []byte{}
+ bytes = append(bytes, bt.VarInt(bump.BlockHeight).Bytes()...)
+ treeHeight := len(bump.Path)
+ bytes = append(bytes, byte(treeHeight))
+ for level := 0; level < treeHeight; level++ {
+ nLeaves := len(bump.Path[level])
+ bytes = append(bytes, bt.VarInt(nLeaves).Bytes()...)
+ for _, leaf := range bump.Path[level] {
+ bytes = append(bytes, bt.VarInt(*leaf.Offset).Bytes()...)
+ flags := byte(0)
+ if leaf.Duplicate != nil {
+ flags |= 1
+ }
+ if leaf.Txid != nil {
+ flags |= 2
+ }
+ bytes = append(bytes, flags)
+ if (flags & 1) == 0 {
+ bytes = append(bytes, BytesFromStringReverse(*leaf.Hash)...)
+ }
+ }
+ }
+ return bytes, nil
+}
+
+func (bump *BUMP) String() (string, error) {
+ bytes, err := bump.Bytes()
+ if err != nil {
+ return "", err
+ }
+ return hex.EncodeToString(bytes), nil
+}
+
+// CalculateRootGivenTxid calculates the root of the Merkle tree given a txid.
+func (bump *BUMP) CalculateRootGivenTxid(txid string) (string, error) {
+ if len(bump.Path) < 2 {
+ return txid, nil
+ }
+ // Find the index of the txid at the lowest level of the Merkle tree
+ var index uint64
+ txidFound := false
+ for _, l := range bump.Path[0] {
+ if *l.Hash == txid {
+ txidFound = true
+ index = *l.Offset
+ break
+ }
+ }
+ if !txidFound {
+ return "", errors.New("The BUMP does not contain the txid: " + txid)
+ }
+
+ // Calculate the root using the index as a way to determine which direction to concatenate.
+ workingHash := BytesFromStringReverse(txid)
+ for height, leaves := range bump.Path {
+ offset := (index >> height) ^ 1
+ var leafAtThisLevel leaf
+ offsetFound := false
+ for _, l := range leaves {
+ if *l.Offset == offset {
+ offsetFound = true
+ leafAtThisLevel = l
+ break
+ }
+ }
+ if !offsetFound {
+ return "", fmt.Errorf("We do not have a hash for this index at height: %v", height)
+ }
+
+ var digest []byte
+ if leafAtThisLevel.Duplicate != nil {
+ digest = append(workingHash, workingHash...)
+ } else {
+ leafBytes := BytesFromStringReverse(*leafAtThisLevel.Hash)
+ if (offset % 2) != 0 {
+ digest = append(workingHash, leafBytes...)
+ } else {
+ digest = append(leafBytes, workingHash...)
+ }
+ }
+ workingHash = Sha256Sha256(digest)
+ }
+ return StringFromBytesReverse(workingHash), nil
+}
+
+// NewBUMPFromMerkleTreeAndIndex with merkle tree we calculate the merkle path for a given transaction.
+func NewBUMPFromMerkleTreeAndIndex(blockHeight uint64, merkleTree []*chainhash.Hash, txIndex uint64) (*BUMP, error) {
+ bump := &BUMP{
+ BlockHeight: blockHeight,
+ Path: [][]leaf{},
+ }
+ t := true
+
+ numOfTxids := (len(merkleTree) + 1) / 2
+ treeHeight := int(math.Log2(float64(numOfTxids)))
+ numOfHashes := numOfTxids
+
+ if len(merkleTree) == 0 {
+ return nil, errors.New("merkle tree is empty")
+ }
+
+ offsets := make([]uint64, treeHeight)
+ for i := 0; i < treeHeight; i++ {
+ if txIndex>>uint64(i)&1 == 0 {
+ offsets[i] = txIndex>>uint64(i) + 1
+ } else {
+ offsets[i] = txIndex>>uint64(i) - 1
+ }
+ }
+
+ // if we have only one transaction in the block there is no merkle path to calculate
+ if len(merkleTree) != 1 {
+ // if our hash index is odd the next hash of the path is the previous element in the array otherwise the next element.
+ levelOffset := 0
+ for height := 0; height < treeHeight; height++ {
+ leaves := []leaf{}
+ bump.Path = append(bump.Path, leaves)
+ for offset := 0; offset < numOfHashes; offset++ {
+ o := uint64(offset)
+ thisLeaf := leaf{Offset: &o}
+ hash := merkleTree[levelOffset+offset]
+ if hash.IsEqual(&chainhash.Hash{}) {
+ thisLeaf.Duplicate = &t
+ } else {
+ sh := hash.String()
+ thisLeaf.Hash = &sh
+ if height == 0 {
+ thisLeaf.Txid = &t
+ }
+ }
+ bump.Path[height] = append(bump.Path[height], thisLeaf)
+ }
+ levelOffset += numOfHashes
+ numOfHashes >>= 1
+ }
+ } else {
+ sh := merkleTree[0].String()
+ o := uint64(0)
+ bump.Path = [][]leaf{{leaf{Hash: &sh, Offset: &o, Txid: &t}}}
+ }
+
+ return bump, nil
+}
diff --git a/vendor/github.com/libsv/go-bc/endian.go b/vendor/github.com/libsv/go-bc/endian.go
new file mode 100644
index 0000000..78155d3
--- /dev/null
+++ b/vendor/github.com/libsv/go-bc/endian.go
@@ -0,0 +1,28 @@
+package bc
+
+import (
+ "crypto/sha256"
+ "encoding/hex"
+
+ "github.com/libsv/go-bt/v2"
+)
+
+// BytesFromStringReverse decodes a hex string into a byte slice and reverses it.
+func BytesFromStringReverse(s string) []byte {
+ bytes, _ := hex.DecodeString(s)
+ rev := bt.ReverseBytes(bytes)
+ return rev
+}
+
+// StringFromBytesReverse reverses a byte slice and encodes it as a hex string.
+func StringFromBytesReverse(h []byte) string {
+ rev := bt.ReverseBytes(h)
+ return hex.EncodeToString(rev)
+}
+
+// Sha256Sha256 calculates the double sha256 hash of a byte slice.
+func Sha256Sha256(digest []byte) []byte {
+ sha := sha256.Sum256(digest)
+ dsha := sha256.Sum256(sha[:])
+ return dsha[:]
+}
diff --git a/vendor/github.com/libsv/go-bc/mapicallback.go b/vendor/github.com/libsv/go-bc/mapicallback.go
index 3112fb2..fc5fa58 100644
--- a/vendor/github.com/libsv/go-bc/mapicallback.go
+++ b/vendor/github.com/libsv/go-bc/mapicallback.go
@@ -23,7 +23,6 @@ func NewMapiCallbackFromBytes(b []byte) (*MapiCallback, error) {
if err != nil {
return nil, err
}
- // TODO check signature is valid.
return &mapiCallback, nil
}
diff --git a/vendor/github.com/libsv/go-bc/merklepath.go b/vendor/github.com/libsv/go-bc/merklepath.go
new file mode 100644
index 0000000..32b889c
--- /dev/null
+++ b/vendor/github.com/libsv/go-bc/merklepath.go
@@ -0,0 +1,137 @@
+package bc
+
+import (
+ "encoding/hex"
+
+ "github.com/libsv/go-bt/v2"
+)
+
+// MerklePath data model json format according to BRC-58.
+type MerklePath struct {
+ Index uint64 `json:"index"`
+ Path []string `json:"path"`
+}
+
+// NewMerklePathFromBytes creates a new MerklePath from a byte slice.
+func NewMerklePathFromBytes(bytes []byte) (*MerklePath, error) {
+ mp := &MerklePath{}
+ mp.Path = make([]string, 0)
+
+ // start paring transaction index.
+ var offset int
+ index, size := bt.NewVarIntFromBytes(bytes[offset:])
+ offset += size
+ mp.Index = uint64(index)
+
+ // next value in the byte array is nLeaves (number of leaves in merkle path).
+ nLeaves, size := bt.NewVarIntFromBytes(bytes[offset:])
+ offset += size
+
+ // parse each leaf from the binary path
+ for k := 0; k < int(nLeaves); k++ {
+ leaf := bytes[offset : offset+32]
+ mp.Path = append(mp.Path, StringFromBytesReverse(leaf))
+ offset += 32
+ }
+
+ return mp, nil
+}
+
+// NewMerklePathFromStr creates a MerklePath from hex string.
+func NewMerklePathFromStr(str string) (*MerklePath, error) {
+ bytes, err := hex.DecodeString(str)
+ if err != nil {
+ return nil, err
+ }
+ return NewMerklePathFromBytes(bytes)
+}
+
+// Bytes encodes a MerklePath as a slice of bytes. MerklePath Binary Format according to BRC-71 https://brc.dev/71
+func (mp *MerklePath) Bytes() ([]byte, error) {
+ index := bt.VarInt(mp.Index)
+ nLeaves := bt.VarInt(len(mp.Path))
+
+ // first two arguments in merkle path bynary format are index of the transaction and number of leaves.
+ bytes := []byte{}
+ bytes = append(bytes, index.Bytes()...)
+ bytes = append(bytes, nLeaves.Bytes()...)
+
+ // now add each leaf into the binary path.
+ for _, leaf := range mp.Path {
+ // append leaf bytes into binary path, little endian.
+ bytes = append(bytes, BytesFromStringReverse(leaf)...)
+ }
+
+ return bytes, nil
+}
+
+// String encodes a MerklePath as a hex string.
+func (mp *MerklePath) String() (string, error) {
+ bytes, err := mp.Bytes()
+ if err != nil {
+ return "", err
+ }
+ return hex.EncodeToString(bytes), nil
+}
+
+// CalculateRoot calculates the merkle root from a transaction ID and a MerklePath.
+func (mp *MerklePath) CalculateRoot(txid string) (string, error) {
+ // start with txid
+ workingHash := BytesFromStringReverse(txid)
+ lsb := mp.Index
+ // hash with each path branch
+ for _, leaf := range mp.Path {
+ var digest []byte
+ leafBytes := BytesFromStringReverse(leaf)
+ // if the least significant bit is 1 then the working hash is on the right.
+ if lsb&1 > 0 {
+ digest = append(leafBytes, workingHash...)
+ } else {
+ digest = append(workingHash, leafBytes...)
+ }
+ workingHash = Sha256Sha256(digest)
+ lsb = lsb >> 1
+ }
+ return StringFromBytesReverse(workingHash), nil
+}
+
+// getPathElements traverses the tree and returns the path to Merkle root.
+func getPathElements(txIndex int, hashes []string) []string {
+ // if our hash index is odd the next hash of the path is the previous element in the array otherwise the next element.
+ var path []string
+ var hash string
+ if txIndex%2 == 0 {
+ hash = hashes[txIndex+1]
+ } else {
+ hash = hashes[txIndex-1]
+ }
+
+ // when generating path if the neighbour is empty we append itself
+ if hash == "" {
+ path = append(path, hashes[txIndex])
+ } else {
+ path = append(path, hash)
+ }
+
+ // If we reach the Merkle root hash stop path calculation.
+ if len(hashes) == 3 {
+ return path
+ }
+
+ return append(path, getPathElements(txIndex/2, hashes[(len(hashes)+1)/2:])...)
+}
+
+// GetTxMerklePath with merkle tree we calculate the merkle path for a given transaction.
+func GetTxMerklePath(txIndex int, merkleTree []string) *MerklePath {
+ merklePath := &MerklePath{
+ Index: uint64(txIndex),
+ Path: nil,
+ }
+
+ // if we have only one transaction in the block there is no merkle path to calculate
+ if len(merkleTree) != 1 {
+ merklePath.Path = getPathElements(txIndex, merkleTree)
+ }
+
+ return merklePath
+}
diff --git a/vendor/github.com/libsv/go-bc/merkleroot.go b/vendor/github.com/libsv/go-bc/merkleroot.go
index 8cf5f74..09bd8dc 100644
--- a/vendor/github.com/libsv/go-bc/merkleroot.go
+++ b/vendor/github.com/libsv/go-bc/merkleroot.go
@@ -7,6 +7,7 @@ import (
"github.com/libsv/go-bk/crypto"
"github.com/libsv/go-bt/v2"
+ "github.com/libsv/go-p2p/chaincfg/chainhash"
)
// TxsToTxIDs takes an array of transactions
@@ -67,7 +68,7 @@ func BuildMerkleRoot(txids []string) (string, error) {
//
// The above stored as a linear array is as follows:
//
-// [h1 h2 h3 h4 h12 h34 root]
+// [h1 h2 h3 h4 h12 h34 root]
//
// As the above shows, the merkle root is always the last element in the array.
//
@@ -128,6 +129,41 @@ func BuildMerkleTreeStore(txids []string) ([]string, error) {
return merkles, nil
}
+// BuildMerkleTreeStoreChainHash has the same functionality as BuildMerkleTreeStore but uses chainhash as a type to avoid string conversions.
+func BuildMerkleTreeStoreChainHash(txids []*chainhash.Hash) ([]*chainhash.Hash, error) {
+ // // Calculate how many entries are re?n array of that size.
+ nextPoT := nextPowerOfTwo(len(txids))
+ arraySize := nextPoT*2 - 1
+ merkles := make([]*chainhash.Hash, arraySize)
+
+ // Create the base transaction hashes and populate the array with them.
+ copy(merkles, txids)
+
+ // Start the array offset after the last transaction and adjusted to the
+ // next power of two.
+ offset := nextPoT
+ for i := 0; i < arraySize-1; i += 2 {
+ switch {
+ // When there is no left child node, the parent is nil ("") too.
+ case merkles[i].IsEqual(&chainhash.Hash{}):
+ merkles[offset] = &chainhash.Hash{}
+
+ // When there is no right child, the parent is generated by
+ // hashing the concatenation of the left child with itself.
+ case merkles[i+1].IsEqual(&chainhash.Hash{}):
+ merkles[offset] = MerkleTreeParentBytes(merkles[i], merkles[i])
+
+ // The normal case sets the parent node to the double sha256
+ // of the concatenation of the left and right children.
+ default:
+ merkles[offset] = MerkleTreeParentBytes(merkles[i], merkles[i+1])
+ }
+ offset++
+ }
+
+ return merkles, nil
+}
+
// nextPowerOfTwo returns the next highest power of two from a given number if
// it is not already a power of two. This is a helper function used during the
// calculation of a merkle tree.
diff --git a/vendor/github.com/libsv/go-bc/merkletreeparent.go b/vendor/github.com/libsv/go-bc/merkletreeparent.go
index beedc29..275f806 100644
--- a/vendor/github.com/libsv/go-bc/merkletreeparent.go
+++ b/vendor/github.com/libsv/go-bc/merkletreeparent.go
@@ -5,6 +5,7 @@ import (
"github.com/libsv/go-bk/crypto"
"github.com/libsv/go-bt/v2"
+ "github.com/libsv/go-p2p/chaincfg/chainhash"
)
// MerkleTreeParentStr returns the Merkle Tree parent of two Merkle
@@ -38,3 +39,16 @@ func MerkleTreeParent(leftNode, rightNode []byte) []byte {
// swap endianness at the end and convert to hex string
return bt.ReverseBytes(hash)
}
+
+// MerkleTreeParentBytes returns the Merkle Tree parent of two Merkle Tree children.
+// The expectation is that the bytes are not reversed.
+func MerkleTreeParentBytes(l *chainhash.Hash, r *chainhash.Hash) *chainhash.Hash {
+ lb := l.CloneBytes()
+ rb := r.CloneBytes()
+ concat := append(lb, rb...)
+ hash, err := chainhash.NewHash(crypto.Sha256d(concat))
+ if err != nil {
+ return &chainhash.Hash{}
+ }
+ return hash
+}
diff --git a/vendor/github.com/libsv/go-bt/v2/.golangci.yml b/vendor/github.com/libsv/go-bt/v2/.golangci.yml
index 895af4f..d4fc6e4 100644
--- a/vendor/github.com/libsv/go-bt/v2/.golangci.yml
+++ b/vendor/github.com/libsv/go-bt/v2/.golangci.yml
@@ -337,7 +337,7 @@ linters:
- dupl
- misspell
- dogsled
- - revive
+ # - revive
- prealloc
- exportloopref
- exhaustive
diff --git a/vendor/github.com/libsv/go-bt/v2/.goreleaser.yml b/vendor/github.com/libsv/go-bt/v2/.goreleaser.yml
index 7580a49..d36e768 100644
--- a/vendor/github.com/libsv/go-bt/v2/.goreleaser.yml
+++ b/vendor/github.com/libsv/go-bt/v2/.goreleaser.yml
@@ -23,5 +23,5 @@ build:
# Github Release
# ---------------------------
release:
- prerelease: true
+ # prerelease: true
name_template: "Release v{{.Version}}"
\ No newline at end of file
diff --git a/vendor/github.com/libsv/go-bt/v2/README.md b/vendor/github.com/libsv/go-bt/v2/README.md
index e815c8d..3de560e 100644
--- a/vendor/github.com/libsv/go-bt/v2/README.md
+++ b/vendor/github.com/libsv/go-bt/v2/README.md
@@ -34,7 +34,7 @@
**go-bt** requires a [supported release of Go](https://golang.org/doc/devel/release.html#policy).
```shell script
-go get -u github.com/libsv/go-bt
+go get -u github.com/libsv/go-bt/v2
```
diff --git a/vendor/github.com/libsv/go-bt/v2/bscript/address.go b/vendor/github.com/libsv/go-bt/v2/bscript/address.go
index 6b7455f..b530be8 100644
--- a/vendor/github.com/libsv/go-bt/v2/bscript/address.go
+++ b/vendor/github.com/libsv/go-bt/v2/bscript/address.go
@@ -1,3 +1,4 @@
+// Package bscript comment
package bscript
import (
@@ -83,7 +84,7 @@ func NewAddressFromPublicKeyHash(hash []byte, mainnet bool) (*Address, error) {
if !mainnet {
bb[0] = 111
}
- // nolint: makezero // we need to set up the array with 1
+ //nolint: makezero // we need to set up the array with 1
bb = append(bb, hash...)
return &Address{
@@ -105,7 +106,7 @@ func NewAddressFromPublicKey(pubKey *bec.PublicKey, mainnet bool) (*Address, err
if !mainnet {
bb[0] = 111
}
- // nolint: makezero // we need to set up the array with 1
+ //nolint: makezero // we need to set up the array with 1
bb = append(bb, hash...)
return &Address{
diff --git a/vendor/github.com/libsv/go-bt/v2/bscript/errors.go b/vendor/github.com/libsv/go-bt/v2/bscript/errors.go
index 0f2256e..87aada9 100644
--- a/vendor/github.com/libsv/go-bt/v2/bscript/errors.go
+++ b/vendor/github.com/libsv/go-bt/v2/bscript/errors.go
@@ -15,6 +15,11 @@ var (
ErrUnsupportedAddress = errors.New("address not supported")
)
+// Sentinel errors raised by inscriptions.
+var (
+ ErrP2PKHInscriptionNotFound = errors.New("no P2PKH inscription found")
+)
+
// Sentinel errors raised through encoding.
var (
ErrEncodingBadChar = errors.New("bad char")
diff --git a/vendor/github.com/libsv/go-bt/v2/bscript/inscriptions.go b/vendor/github.com/libsv/go-bt/v2/bscript/inscriptions.go
new file mode 100644
index 0000000..4a93a99
--- /dev/null
+++ b/vendor/github.com/libsv/go-bt/v2/bscript/inscriptions.go
@@ -0,0 +1,15 @@
+package bscript
+
+// InscriptionArgs contains the Ordinal inscription data.
+type InscriptionArgs struct {
+ LockingScriptPrefix *Script
+ Data []byte
+ ContentType string
+ EnrichedArgs *EnrichedInscriptionArgs
+}
+
+// EnrichedInscriptionArgs contains data needed for enriched inscription
+// functionality found here: https://docs.1satordinals.com/op_return.
+type EnrichedInscriptionArgs struct {
+ OpReturnData [][]byte
+}
diff --git a/vendor/github.com/libsv/go-bt/v2/bscript/script.go b/vendor/github.com/libsv/go-bt/v2/bscript/script.go
index 0ff6dad..216106e 100644
--- a/vendor/github.com/libsv/go-bt/v2/bscript/script.go
+++ b/vendor/github.com/libsv/go-bt/v2/bscript/script.go
@@ -6,6 +6,7 @@ import (
"encoding/binary"
"encoding/hex"
"fmt"
+ "math/bits"
"strings"
"github.com/libsv/go-bk/bec"
@@ -15,13 +16,14 @@ import (
// ScriptKey types.
const (
- ScriptTypePubKey = "pubkey"
- ScriptTypePubKeyHash = "pubkeyhash"
- ScriptTypeNonStandard = "nonstandard"
- ScriptTypeEmpty = "empty"
- ScriptTypeSecureHash = "securehash"
- ScriptTypeMultiSig = "multisig"
- ScriptTypeNullData = "nulldata"
+ // TODO: change to p2pk/p2pkh
+ ScriptTypePubKey = "pubkey"
+ ScriptTypePubKeyHash = "pubkeyhash"
+ ScriptTypeNonStandard = "nonstandard"
+ ScriptTypeEmpty = "empty"
+ ScriptTypeMultiSig = "multisig"
+ ScriptTypeNullData = "nulldata"
+ ScriptTypePubKeyHashInscription = "pubkeyhashinscription"
)
// Script type
@@ -233,13 +235,32 @@ func (s *Script) ToASM() (string, error) {
parts, err := DecodeParts(*s)
// if err != nil, we will append [error] to the ASM script below (as done in the node).
+ data := false
+ if len(*s) > 1 && ((*s)[0] == OpRETURN || ((*s)[0] == OpFALSE && (*s)[1] == OpRETURN)) {
+ data = true
+ }
+
var asm strings.Builder
+
for _, p := range parts {
asm.WriteRune(' ')
if len(p) == 1 {
- asm.WriteString(opCodeValues[p[0]])
+ if data && p[0] != 0x6a {
+ asm.WriteString(fmt.Sprintf("%d", p[0]))
+ } else {
+ asm.WriteString(opCodeValues[p[0]])
+ }
} else {
- asm.WriteString(hex.EncodeToString(p))
+ if data && len(p) <= 4 {
+ b := make([]byte, 0)
+ b = append(b, p...)
+ for i := 0; i < 4-len(p); i++ {
+ b = append(b, 0)
+ }
+ asm.WriteString(fmt.Sprintf("%d", binary.LittleEndian.Uint32(b)))
+ } else {
+ asm.WriteString(hex.EncodeToString(p))
+ }
}
}
@@ -301,6 +322,82 @@ func (s *Script) IsData() bool {
(len(b) > 1 && b[0] == OpFALSE && b[1] == OpRETURN)
}
+// IsInscribed returns true if this script includes an
+// inscription with any prepended script (not just p2pkh).
+func (s *Script) IsInscribed() bool {
+ isncPattern, _ := hex.DecodeString("0063036f7264")
+ return bytes.Contains(*s, isncPattern)
+}
+
+// IsP2PKHInscription checks if it's a standard
+// inscription with a P2PKH prefix script.
+func (s *Script) IsP2PKHInscription() bool {
+ p, err := DecodeParts(*s)
+ if err != nil {
+ return false
+ }
+
+ return isP2PKHInscriptionHelper(p)
+}
+
+// isP2PKHInscriptionHelper helper so that we don't need to call
+// `DecodeParts()` multiple times, such as in `ParseInscription()`
+func isP2PKHInscriptionHelper(parts [][]byte) bool {
+ if len(parts) < 13 {
+ return false
+ }
+ valid := parts[0][0] == OpDUP &&
+ parts[1][0] == OpHASH160 &&
+ parts[3][0] == OpEQUALVERIFY &&
+ parts[4][0] == OpCHECKSIG &&
+ parts[5][0] == OpFALSE &&
+ parts[6][0] == OpIF &&
+ parts[7][0] == 0x6f && parts[7][1] == 0x72 && parts[7][2] == 0x64 && // op_push "ord"
+ parts[8][0] == OpTRUE &&
+ parts[10][0] == OpFALSE &&
+ parts[12][0] == OpENDIF
+
+ if len(parts) > 13 {
+ return parts[13][0] == OpRETURN && valid
+ }
+ return valid
+}
+
+// ParseInscription parses the script to
+// return the inscription found. Will return
+// an error if the script doesn't contain
+// any inscriptions.
+func (s *Script) ParseInscription() (*InscriptionArgs, error) {
+ p, err := DecodeParts(*s)
+ if err != nil {
+ return nil, err
+ }
+
+ if !isP2PKHInscriptionHelper(p) {
+ return nil, ErrP2PKHInscriptionNotFound
+ }
+
+ // FIXME: make it dynamic based on order.
+ // right now if the content type and the content change order
+ // then this will fail. My understanding is that the content
+ // always needs to be last and the previous fields can be
+ // reordered - this is based on the original ordinals
+ // indexer: https://github.com/casey/ord
+ return &InscriptionArgs{
+ LockingScriptPrefix: s.Slice(0, 25),
+ Data: p[11],
+ ContentType: string(p[9]),
+ // EnrichedArgs: , // TODO:
+ }, nil
+}
+
+// Slice a script to get back a subset of that script.
+func (s *Script) Slice(start, end uint64) *Script {
+ ss := *s
+ sss := ss[start:end]
+ return &sss
+}
+
// IsMultiSigOut returns true if this is a multisig output script.
func (s *Script) IsMultiSigOut() bool {
parts, err := DecodeParts(*s)
@@ -336,7 +433,7 @@ func (s *Script) PublicKeyHash() ([]byte, error) {
return nil, ErrEmptyScript
}
- if (*s)[0] != OpDUP || (*s)[1] != OpHASH160 {
+ if (*s)[0] != OpDUP || len(*s) <= 2 || (*s)[1] != OpHASH160 {
return nil, ErrNotP2PKH
}
@@ -365,6 +462,9 @@ func (s *Script) ScriptType() string {
if s.IsData() {
return ScriptTypeNullData
}
+ if s.IsP2PKHInscription() {
+ return ScriptTypePubKeyHashInscription
+ }
return ScriptTypeNonStandard
}
@@ -408,8 +508,8 @@ func (s *Script) EqualsHex(h string) bool {
func MinPushSize(bb []byte) int {
l := len(bb)
- // data length is larger than max supported
- if l > 0xffffffff {
+ // data length is larger than max supported by the bitcoin protocol
+ if bits.UintSize == 64 && int64(l) > 0xffffffff {
return 0
}
diff --git a/vendor/github.com/libsv/go-bt/v2/errors.go b/vendor/github.com/libsv/go-bt/v2/errors.go
index 86f5100..2caa8dc 100644
--- a/vendor/github.com/libsv/go-bt/v2/errors.go
+++ b/vendor/github.com/libsv/go-bt/v2/errors.go
@@ -18,6 +18,10 @@ var (
var (
ErrInputNoExist = errors.New("specified input does not exist")
ErrInputTooShort = errors.New("input length too short")
+
+ // You should not be able to spend an input with 0 Satoshi value.
+ // Most likely the input Satoshi value is not provided.
+ ErrInputSatsZero = errors.New("input satoshi value is not provided")
)
// Sentinal errors reported by outputs.
@@ -46,7 +50,7 @@ var (
ErrUnknownFeeType = errors.New("unknown fee type")
)
-// Sentinel errors reported by Fund
+// Sentinel errors reported by Fund.
var (
// ErrNoUTXO signals the UTXOGetterFunc has reached the end of its input.
ErrNoUTXO = errors.New("no remaining utxos")
@@ -54,3 +58,19 @@ var (
// ErrInsufficientFunds insufficient funds provided for funding
ErrInsufficientFunds = errors.New("insufficient funds provided")
)
+
+// Sentinal errors reported by ordinal inscriptions.
+var (
+ ErrOutputsNotEmpty = errors.New("transaction outputs must be empty to avoid messing with Ordinal ordering scheme")
+)
+
+// Sentinal errors reported by PSBTs.
+var (
+ ErrDummyInput = errors.New("failed to add dummy input 0")
+ ErrInsufficientUTXOs = errors.New("need at least 2 utxos")
+ ErrInsufficientUTXOValue = errors.New("need at least 1 utxos which is > ordinal price")
+ ErrUTXOInputMismatch = errors.New("utxo and input mismatch")
+ ErrInvalidSellOffer = errors.New("invalid sell offer (partially signed tx)")
+ ErrEmptyScripts = errors.New("at least one of needed scripts is empty")
+ ErrInsufficientFees = errors.New("fee paid not enough with new locking script")
+)
diff --git a/vendor/github.com/libsv/go-bt/v2/fees.go b/vendor/github.com/libsv/go-bt/v2/fees.go
index 6c2f4a6..2afa6e4 100644
--- a/vendor/github.com/libsv/go-bt/v2/fees.go
+++ b/vendor/github.com/libsv/go-bt/v2/fees.go
@@ -294,11 +294,11 @@ func defaultStandardFee() *Fee {
FeeType: FeeTypeStandard,
MiningFee: FeeUnit{
Satoshis: 5,
- Bytes: 10,
+ Bytes: 100,
},
RelayFee: FeeUnit{
Satoshis: 5,
- Bytes: 10,
+ Bytes: 100,
},
}
}
@@ -310,11 +310,11 @@ func defaultDataFee() *Fee {
FeeType: FeeTypeData,
MiningFee: FeeUnit{
Satoshis: 5,
- Bytes: 10,
+ Bytes: 100,
},
RelayFee: FeeUnit{
Satoshis: 5,
- Bytes: 10,
+ Bytes: 100,
},
}
}
diff --git a/vendor/github.com/libsv/go-bt/v2/input.go b/vendor/github.com/libsv/go-bt/v2/input.go
index 93452bd..0601809 100644
--- a/vendor/github.com/libsv/go-bt/v2/input.go
+++ b/vendor/github.com/libsv/go-bt/v2/input.go
@@ -28,7 +28,6 @@ const DefaultSequenceNumber uint32 = 0xFFFFFFFF
// Input is a representation of a transaction input
//
// DO NOT CHANGE ORDER - Optimised for memory via maligned
-//
type Input struct {
previousTxID []byte
PreviousTxSatoshis uint64
@@ -40,6 +39,16 @@ type Input struct {
// ReadFrom reads from the `io.Reader` into the `bt.Input`.
func (i *Input) ReadFrom(r io.Reader) (int64, error) {
+ return i.readFrom(r, false)
+}
+
+// ReadFromExtended reads the `io.Reader` into the `bt.Input` when the reader is
+// consuming an extended format transaction.
+func (i *Input) ReadFromExtended(r io.Reader) (int64, error) {
+ return i.readFrom(r, true)
+}
+
+func (i *Input) readFrom(r io.Reader, extended bool) (int64, error) {
*i = Input{}
var bytesRead int64
@@ -83,6 +92,37 @@ func (i *Input) ReadFrom(r io.Reader) (int64, error) {
i.UnlockingScript = bscript.NewFromBytes(script)
i.SequenceNumber = binary.LittleEndian.Uint32(sequence)
+ if extended {
+ prevSatoshis := make([]byte, 8)
+ var prevTxLockingScript bscript.Script
+
+ n, err = io.ReadFull(r, prevSatoshis)
+ bytesRead += int64(n)
+ if err != nil {
+ return bytesRead, errors.Wrapf(err, "prevSatoshis(8): got %d bytes", n)
+ }
+
+ // Read in the prevTxLockingScript
+ var scriptLen VarInt
+ n64, err := scriptLen.ReadFrom(r)
+ bytesRead += n64
+ if err != nil {
+ return bytesRead, err
+ }
+
+ script := make([]byte, scriptLen)
+ n, err := io.ReadFull(r, script)
+ bytesRead += int64(n)
+ if err != nil {
+ return bytesRead, errors.Wrapf(err, "script(%d): got %d bytes", scriptLen.Length(), n)
+ }
+
+ prevTxLockingScript = *bscript.NewFromBytes(script)
+
+ i.PreviousTxSatoshis = binary.LittleEndian.Uint64(prevSatoshis)
+ i.PreviousTxScript = bscript.NewFromBytes(prevTxLockingScript)
+ }
+
return bytesRead, nil
}
diff --git a/vendor/github.com/libsv/go-bt/v2/inscriptions.go b/vendor/github.com/libsv/go-bt/v2/inscriptions.go
new file mode 100644
index 0000000..bbe20af
--- /dev/null
+++ b/vendor/github.com/libsv/go-bt/v2/inscriptions.go
@@ -0,0 +1,131 @@
+package bt
+
+import (
+ "github.com/libsv/go-bt/v2/bscript"
+)
+
+// OrdinalsPrefix contains 'ORD' the inscription protocol prefix.
+//
+// Check the docs here: https://docs.1satordinals.com/
+const OrdinalsPrefix = "ord"
+
+// Inscribe adds an output to the transaction with an inscription.
+func (tx *Tx) Inscribe(ia *bscript.InscriptionArgs) error {
+ s := *ia.LockingScriptPrefix // deep copy
+
+ // add Inscription data
+ // (Example: OP_FALSE
+ // OP_IF
+ // OP_PUSH
+ // "ord"
+ // OP_1
+ // OP_PUSH
+ // "text/plain;charset=utf-8"
+ // OP_0
+ // OP_PUSH
+ // "Hello, world!"
+ // OP_ENDIF
+ // )
+ // see: https://docs.ordinals.com/inscriptions.html
+ _ = s.AppendOpcodes(bscript.OpFALSE, bscript.OpIF)
+ err := s.AppendPushDataString(OrdinalsPrefix)
+ if err != nil {
+ return err
+ }
+ _ = s.AppendOpcodes(bscript.Op1)
+ err = s.AppendPushData([]byte(ia.ContentType))
+ if err != nil {
+ return err
+ }
+ _ = s.AppendOpcodes(bscript.Op0)
+ err = s.AppendPushData(ia.Data)
+ if err != nil {
+ return err
+ }
+ _ = s.AppendOpcodes(bscript.OpENDIF)
+
+ if ia.EnrichedArgs != nil {
+ if len(ia.EnrichedArgs.OpReturnData) > 0 {
+
+ // FIXME: import cycle
+ // // Sign with AIP
+ // _, outData, _, err := aip.SignOpReturnData(*signingKey, "BITCOIN_ECDSA", opReturn)
+ // if err != nil {
+ // return nil, err
+ // }
+
+ _ = s.AppendOpcodes(bscript.OpRETURN)
+ if err := s.AppendPushDataArray(ia.EnrichedArgs.OpReturnData); err != nil {
+ return err
+ }
+ }
+ }
+
+ tx.AddOutput(&Output{
+ Satoshis: 1,
+ LockingScript: &s,
+ })
+ return nil
+}
+
+// InscribeSpecificOrdinal gives you the functionality to choose
+// a specific ordinal from the inputs to inscribe.
+//
+// You need to provide the input and Satoshi range indices in order
+// to specify the ordinal you would like to inscribe, along with the
+// change addresses to be used for the rest of the Satoshis.
+//
+// One output will be created with the extra Satoshis and then another
+// output will be created with 1 Satoshi with the inscription in it.
+func (tx *Tx) InscribeSpecificOrdinal(ia *bscript.InscriptionArgs, inputIdx uint32, satoshiIdx uint64,
+ extraOutputScript *bscript.Script) error {
+ amount, err := rangeAbove(tx.Inputs, inputIdx, satoshiIdx)
+ if err != nil {
+ return err
+ }
+
+ if tx.OutputCount() > 0 {
+ return ErrOutputsNotEmpty
+ }
+
+ tx.AddOutput(&Output{
+ Satoshis: amount,
+ LockingScript: extraOutputScript,
+ })
+
+ err = tx.Inscribe(ia)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// This function returns the Satoshi amount needed for the output slot
+// above the ordinal required so that we can separate the out the ordinal
+// from the inputs to the outputs.
+//
+// This is the way ordinals go from inputs to outputs:
+// [a b] [c] [d e f] → [? ? ? ?] [? ?]
+// To figure out which satoshi goes to which output, go through the input
+// satoshis in order and assign each to a question mark:
+// [a b] [c] [d e f] → [a b c d] [e f]
+//
+// For more info check the Ordinals Theory Handbook (https://docs.ordinals.com/faq.html).
+func rangeAbove(is []*Input, inputIdx uint32, satIdx uint64) (uint64, error) {
+ if uint32(len(is)) < inputIdx {
+ return 0, ErrOutputNoExist
+ }
+
+ var acc uint64
+ for i, in := range is {
+ if uint32(i) >= inputIdx {
+ break
+ }
+ if in.PreviousTxSatoshis == 0 {
+ return 0, ErrInputSatsZero
+ }
+ acc += in.PreviousTxSatoshis
+ }
+ return acc + satIdx, nil
+}
diff --git a/vendor/github.com/libsv/go-bt/v2/output.go b/vendor/github.com/libsv/go-bt/v2/output.go
index 2a48910..37e0e7e 100644
--- a/vendor/github.com/libsv/go-bt/v2/output.go
+++ b/vendor/github.com/libsv/go-bt/v2/output.go
@@ -24,8 +24,8 @@ Txout-script / scriptPubKey Script 0 || extended {
+ // Re-read the actual output count...
+ n64, err = outputCount.ReadFrom(r)
+ bytesRead += n64
+ if err != nil {
+ return bytesRead, err
+ }
}
for i := uint64(0); i < uint64(outputCount); i++ {
@@ -178,7 +191,6 @@ func (tx *Tx) ReadFrom(r io.Reader) (int64, error) {
tx.Outputs = append(tx.Outputs, output)
}
- locktime := make([]byte, 4)
n, err = io.ReadFull(r, locktime)
bytesRead += int64(n)
if err != nil {
@@ -297,19 +309,28 @@ func IsValidTxID(txid []byte) bool {
// Bytes encodes the transaction into a byte array.
// See https://chainquery.com/bitcoin-cli/decoderawtransaction
func (tx *Tx) Bytes() []byte {
- return tx.toBytesHelper(0, nil)
+ return tx.toBytesHelper(0, nil, false)
+}
+
+// ExtendedBytes outputs the transaction into a byte array in extended format
+// (with PreviousTxSatoshis and PreviousTXScript included)
+func (tx *Tx) ExtendedBytes() []byte {
+ return tx.toBytesHelper(0, nil, true)
}
// BytesWithClearedInputs encodes the transaction into a byte array but clears its Inputs first.
// This is used when signing transactions.
func (tx *Tx) BytesWithClearedInputs(index int, lockingScript []byte) []byte {
- return tx.toBytesHelper(index, lockingScript)
+ return tx.toBytesHelper(index, lockingScript, false)
}
// Clone returns a clone of the tx
func (tx *Tx) Clone() *Tx {
// Ignore err as byte slice passed in is created from valid tx
- clone, _ := NewTxFromBytes(tx.Bytes())
+ clone, err := NewTxFromBytes(tx.Bytes())
+ if err != nil {
+ log.Fatal(err)
+ }
for i, input := range tx.Inputs {
clone.Inputs[i].PreviousTxSatoshis = input.PreviousTxSatoshis
@@ -322,11 +343,13 @@ func (tx *Tx) Clone() *Tx {
// NodeJSON returns a wrapped *bt.Tx for marshalling/unmarshalling into a node tx format.
//
// Marshalling usage example:
-// bb, err := json.Marshal(tx.NodeJSON())
+//
+// bb, err := json.Marshal(tx.NodeJSON())
//
// Unmarshalling usage example:
-// tx := bt.NewTx()
-// if err := json.Unmarshal(bb, tx.NodeJSON()); err != nil {}
+//
+// tx := bt.NewTx()
+// if err := json.Unmarshal(bb, tx.NodeJSON()); err != nil {}
func (tx *Tx) NodeJSON() interface{} {
return &nodeTxWrapper{Tx: tx}
}
@@ -334,20 +357,26 @@ func (tx *Tx) NodeJSON() interface{} {
// NodeJSON returns a wrapped bt.Txs for marshalling/unmarshalling into a node tx format.
//
// Marshalling usage example:
-// bb, err := json.Marshal(txs.NodeJSON())
+//
+// bb, err := json.Marshal(txs.NodeJSON())
//
// Unmarshalling usage example:
-// var txs bt.Txs
-// if err := json.Unmarshal(bb, txs.NodeJSON()); err != nil {}
+//
+// var txs bt.Txs
+// if err := json.Unmarshal(bb, txs.NodeJSON()); err != nil {}
func (tt *Txs) NodeJSON() interface{} {
return (*nodeTxsWrapper)(tt)
}
-func (tx *Tx) toBytesHelper(index int, lockingScript []byte) []byte {
+func (tx *Tx) toBytesHelper(index int, lockingScript []byte, extended bool) []byte {
h := make([]byte, 0)
h = append(h, LittleEndianBytes(tx.Version, 4)...)
+ if extended {
+ h = append(h, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0xEF}...)
+ }
+
h = append(h, VarInt(uint64(len(tx.Inputs))).Bytes()...)
for i, in := range tx.Inputs {
@@ -358,6 +387,20 @@ func (tx *Tx) toBytesHelper(index int, lockingScript []byte) []byte {
} else {
h = append(h, s...)
}
+
+ if extended {
+ b := make([]byte, 8)
+ binary.LittleEndian.PutUint64(b, in.PreviousTxSatoshis)
+ h = append(h, b...)
+
+ if in.PreviousTxScript != nil {
+ l := uint64(len(*in.PreviousTxScript))
+ h = append(h, VarInt(l).Bytes()...)
+ h = append(h, *in.PreviousTxScript...)
+ } else {
+ h = append(h, 0x00) // The length of the script is zero
+ }
+ }
}
h = append(h, VarInt(uint64(len(tx.Outputs))).Bytes()...)
@@ -435,12 +478,15 @@ func (tx *Tx) EstimateSizeWithTypes() (*TxSize, error) {
func (tx *Tx) estimatedFinalTx() (*Tx, error) {
tempTx := tx.Clone()
- for _, in := range tempTx.Inputs {
- if !in.PreviousTxScript.IsP2PKH() {
+ for i, in := range tempTx.Inputs {
+ if in.PreviousTxScript == nil {
+ return nil, fmt.Errorf("%w at index %d in order to calc expected UnlockingScript", ErrEmptyPreviousTxScript, i)
+ }
+ if !(in.PreviousTxScript.IsP2PKH() || in.PreviousTxScript.IsP2PKHInscription()) {
return nil, ErrUnsupportedScript
}
if in.UnlockingScript == nil || len(*in.UnlockingScript) == 0 {
- // nolint:lll // insert dummy p2pkh unlocking script (sig + pubkey)
+ //nolint:lll // insert dummy p2pkh unlocking script (sig + pubkey)
dummyUnlockingScript, _ := hex.DecodeString("4830450221009c13cbcbb16f2cfedc7abf3a4af1c3fe77df1180c0e7eee30d9bcc53ebda39da02207b258005f1bc3cf9dffa06edb358d6db2bcfc87f50516fac8e3f4686fc2a03df412103107feff22788a1fc8357240bf450fd7bca4bd45d5f8bac63818c5a7b67b03876")
in.UnlockingScript = bscript.NewFromBytes(dummyUnlockingScript)
}
@@ -524,12 +570,12 @@ func (tx *Tx) feesPaid(size *TxSize, fees *FeeQuote) (*TxFees, error) {
return nil, err
}
- resp := &TxFees{
+ txFees := &TxFees{
StdFeePaid: size.TotalStdBytes * uint64(stdFee.MiningFee.Satoshis) / uint64(stdFee.MiningFee.Bytes),
DataFeePaid: size.TotalDataBytes * uint64(dataFee.MiningFee.Satoshis) / uint64(dataFee.MiningFee.Bytes),
}
- resp.TotalFeePaid = resp.StdFeePaid + resp.DataFeePaid
- return resp, nil
+ txFees.TotalFeePaid = txFees.StdFeePaid + txFees.DataFeePaid
+ return txFees, nil
}
diff --git a/vendor/github.com/libsv/go-bt/v2/txinput.go b/vendor/github.com/libsv/go-bt/v2/txinput.go
index b12caf3..0f787f0 100644
--- a/vendor/github.com/libsv/go-bt/v2/txinput.go
+++ b/vendor/github.com/libsv/go-bt/v2/txinput.go
@@ -23,30 +23,6 @@ import (
// It is expected that bt.ErrNoUTXO will be returned once the utxo source is depleted.
type UTXOGetterFunc func(ctx context.Context, deficit uint64) ([]*UTXO, error)
-// newInputFromBytes returns a transaction input from the bytes provided.
-func newInputFromBytes(bytes []byte) (*Input, int, error) {
- if len(bytes) < 36 {
- return nil, 0, fmt.Errorf("%w < 36", ErrInputTooShort)
- }
-
- offset := 36
- l, size := NewVarIntFromBytes(bytes[offset:])
- offset += size
-
- totalLength := offset + int(l) + 4 // 4 bytes for nSeq
-
- if len(bytes) < totalLength {
- return nil, 0, fmt.Errorf("%w < 36 + script + 4", ErrInputTooShort)
- }
-
- return &Input{
- previousTxID: ReverseBytes(bytes[0:32]),
- PreviousTxOutIndex: binary.LittleEndian.Uint32(bytes[32:36]),
- SequenceNumber: binary.LittleEndian.Uint32(bytes[offset+int(l):]),
- UnlockingScript: bscript.NewFromBytes(bytes[offset : offset+int(l)]),
- }, totalLength, nil
-}
-
// TotalInputSatoshis returns the total Satoshis inputted to the transaction.
func (tx *Tx) TotalInputSatoshis() (total uint64) {
for _, in := range tx.Inputs {
@@ -137,25 +113,26 @@ func (tx *Tx) FromUTXOs(utxos ...*UTXO) error {
// If insufficient utxos are provided from the UTXOGetterFunc, a bt.ErrInsufficientFunds is returned.
//
// Example usage:
-// if err := tx.Fund(ctx, bt.NewFeeQuote(), func(ctx context.Context, deficit satoshis) ([]*bt.UTXO, error) {
-// utxos := make([]*bt.UTXO, 0)
-// for _, f := range funds {
-// deficit -= satoshis
-// utxos := append(utxos, &bt.UTXO{
-// TxID: f.TxID,
-// Vout: f.Vout,
-// LockingScript: f.Script,
-// Satoshis: f.Satoshis,
-// })
-// if deficit == 0 {
-// return utxos, nil
-// }
-// }
-// return nil, bt.ErrNoUTXO
-// }); err != nil {
-// if errors.Is(err, bt.ErrInsufficientFunds) { /* handle */ }
-// return err
-// }
+//
+// if err := tx.Fund(ctx, bt.NewFeeQuote(), func(ctx context.Context, deficit satoshis) ([]*bt.UTXO, error) {
+// utxos := make([]*bt.UTXO, 0)
+// for _, f := range funds {
+// deficit -= satoshis
+// utxos := append(utxos, &bt.UTXO{
+// TxID: f.TxID,
+// Vout: f.Vout,
+// LockingScript: f.Script,
+// Satoshis: f.Satoshis,
+// })
+// if deficit == 0 {
+// return utxos, nil
+// }
+// }
+// return nil, bt.ErrNoUTXO
+// }); err != nil {
+// if errors.Is(err, bt.ErrInsufficientFunds) { /* handle */ }
+// return err
+// }
func (tx *Tx) Fund(ctx context.Context, fq *FeeQuote, next UTXOGetterFunc) error {
deficit, err := tx.estimateDeficit(fq)
if err != nil {
@@ -234,7 +211,7 @@ func (tx *Tx) InsertInputUnlockingScript(index uint32, s *bscript.Script) error
// It takes an Unlocker interface as a parameter so that different
// unlocking implementations can be used to unlock the transaction -
// for example local or external unlocking (hardware wallet), or
-// signature/nonsignature based.
+// signature / non-signature based.
func (tx *Tx) FillInput(ctx context.Context, unlocker Unlocker, params UnlockerParams) error {
if unlocker == nil {
return ErrNoUnlocker
@@ -244,12 +221,12 @@ func (tx *Tx) FillInput(ctx context.Context, unlocker Unlocker, params UnlockerP
params.SigHashFlags = sighash.AllForkID
}
- uscript, err := unlocker.UnlockingScript(ctx, tx, params)
+ unlockingScript, err := unlocker.UnlockingScript(ctx, tx, params)
if err != nil {
return err
}
- return tx.InsertInputUnlockingScript(params.InputIdx, uscript)
+ return tx.InsertInputUnlockingScript(params.InputIdx, unlockingScript)
}
// FillAllInputs is used to sign all inputs. It takes an UnlockerGetter interface
diff --git a/vendor/github.com/libsv/go-bt/v2/txoutput.go b/vendor/github.com/libsv/go-bt/v2/txoutput.go
index e6a241e..be72f76 100644
--- a/vendor/github.com/libsv/go-bt/v2/txoutput.go
+++ b/vendor/github.com/libsv/go-bt/v2/txoutput.go
@@ -158,7 +158,7 @@ func (tx *Tx) AddHashPuzzleOutput(secret, publicKeyHash string, satoshis uint64)
// AddOpReturnOutput creates a new Output with OP_FALSE OP_RETURN and then the data
// passed in encoded as hex.
func (tx *Tx) AddOpReturnOutput(data []byte) error {
- o, err := createOpReturnOutput([][]byte{data})
+ o, err := CreateOpReturnOutput([][]byte{data})
if err != nil {
return err
}
@@ -170,7 +170,7 @@ func (tx *Tx) AddOpReturnOutput(data []byte) error {
// AddOpReturnPartsOutput creates a new Output with OP_FALSE OP_RETURN and then
// uses OP_PUSHDATA format to encode the multiple byte arrays passed in.
func (tx *Tx) AddOpReturnPartsOutput(data [][]byte) error {
- o, err := createOpReturnOutput(data)
+ o, err := CreateOpReturnOutput(data)
if err != nil {
return err
}
@@ -178,7 +178,9 @@ func (tx *Tx) AddOpReturnPartsOutput(data [][]byte) error {
return nil
}
-func createOpReturnOutput(data [][]byte) (*Output, error) {
+// CreateOpReturnOutput creates a new Output with OP_FALSE OP_RETURN and then
+// uses OP_PUSHDATA format to encode the multiple byte arrays passed in.
+func CreateOpReturnOutput(data [][]byte) (*Output, error) {
s := &bscript.Script{}
_ = s.AppendOpcodes(bscript.OpFALSE, bscript.OpRETURN)
diff --git a/vendor/github.com/libsv/go-bt/v2/unlocker.go b/vendor/github.com/libsv/go-bt/v2/unlocker.go
index 8db5984..c69e010 100644
--- a/vendor/github.com/libsv/go-bt/v2/unlocker.go
+++ b/vendor/github.com/libsv/go-bt/v2/unlocker.go
@@ -13,6 +13,8 @@ type UnlockerParams struct {
InputIdx uint32
// SigHashFlags the be applied [DEFAULT ALL|FORKID]
SigHashFlags sighash.Flag
+ // TODO: add previous tx script and sats here instead of in
+ // input (and potentially remove from input) - see issue #143
}
// Unlocker interface to allow custom implementations of different unlocking mechanisms.
diff --git a/vendor/github.com/libsv/go-bt/v2/utxo.go b/vendor/github.com/libsv/go-bt/v2/utxo.go
index 324fc5e..d4dacdb 100644
--- a/vendor/github.com/libsv/go-bt/v2/utxo.go
+++ b/vendor/github.com/libsv/go-bt/v2/utxo.go
@@ -8,11 +8,12 @@ import (
// UTXO an unspent transaction output, used for creating inputs
type UTXO struct {
- TxID []byte
- Vout uint32
- LockingScript *bscript.Script
- Satoshis uint64
- SequenceNumber uint32
+ TxID []byte `json:"txid"`
+ Vout uint32 `json:"vout"`
+ LockingScript *bscript.Script `json:"locking_script"`
+ Satoshis uint64 `json:"satoshis"`
+ SequenceNumber uint32 `json:"sequence_number"`
+ Unlocker *Unlocker `json:"-"`
}
// UTXOs a collection of *bt.UTXO.
diff --git a/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/README.md b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/README.md
new file mode 100644
index 0000000..a8279e3
--- /dev/null
+++ b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/README.md
@@ -0,0 +1,21 @@
+chainhash
+=========
+
+[![Build Status](https://travis-ci.org/bitcoinsv/bsvd.png?branch=master)](https://travis-ci.org/bitcoinsv/bsvd)
+[![ISC License](http://img.shields.io/badge/license-ISC-blue.svg)](http://copyfree.org)
+[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/arc/p2p/chaincfg/chainhash)
+=======
+
+chainhash provides a generic hash type and associated functions that allows the
+specific hash algorithm to be abstracted.
+
+## Installation and Updating
+
+```bash
+$ go get -u arc/p2p/chaincfg/chainhash
+```
+
+## License
+
+Package chainhash is licensed under the [copyfree](http://copyfree.org) ISC
+License.
diff --git a/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/doc.go b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/doc.go
new file mode 100644
index 0000000..c3eb43d
--- /dev/null
+++ b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/doc.go
@@ -0,0 +1,5 @@
+// Package chainhash provides abstracted hash functionality.
+//
+// This package provides a generic hash type and associated functions that
+// allows the specific hash algorithm to be abstracted.
+package chainhash
diff --git a/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/hash.go b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/hash.go
new file mode 100644
index 0000000..42fb1ec
--- /dev/null
+++ b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/hash.go
@@ -0,0 +1,156 @@
+// Copyright (c) 2013-2016 The btcsuite developers
+// Copyright (c) 2015 The Decred developers
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package chainhash
+
+import (
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+)
+
+// HashSize of array used to store hashes. See Hash.
+const HashSize = 32
+
+// MaxHashStringSize is the maximum length of a Hash hash string.
+const MaxHashStringSize = HashSize * 2
+
+// ErrHashStrSize describes an error that indicates the caller specified a hash
+// string that has too many characters.
+var ErrHashStrSize = fmt.Errorf("max hash string length is %v bytes", MaxHashStringSize)
+
+// Hash is used in several of the bitcoin messages and common structures. It
+// typically represents the double sha256 of data.
+type Hash [HashSize]byte
+
+// String returns the Hash as the hexadecimal string of the byte-reversed
+// hash.
+func (hash Hash) String() string {
+ for i := 0; i < HashSize/2; i++ {
+ hash[i], hash[HashSize-1-i] = hash[HashSize-1-i], hash[i]
+ }
+ return hex.EncodeToString(hash[:])
+}
+
+// CloneBytes returns a copy of the bytes which represent the hash as a byte
+// slice.
+//
+// NOTE: It is generally cheaper to just slice the hash directly thereby reusing
+// the same bytes rather than calling this method.
+func (hash *Hash) CloneBytes() []byte {
+ newHash := make([]byte, HashSize)
+ copy(newHash, hash[:])
+
+ return newHash
+}
+
+// SetBytes sets the bytes which represent the hash. An error is returned if
+// the number of bytes passed in is not HashSize.
+func (hash *Hash) SetBytes(newHash []byte) error {
+ nhlen := len(newHash)
+ if nhlen != HashSize {
+ return fmt.Errorf("invalid hash length of %v, want %v", nhlen,
+ HashSize)
+ }
+ copy(hash[:], newHash)
+
+ return nil
+}
+
+// IsEqual returns true if target is the same as hash.
+func (hash *Hash) IsEqual(target *Hash) bool {
+ if hash == nil && target == nil {
+ return true
+ }
+ if hash == nil || target == nil {
+ return false
+ }
+ return *hash == *target
+}
+
+func (hash *Hash) MarshalJSON() ([]byte, error) {
+ return json.Marshal(hash.String())
+}
+
+func (hash *Hash) UnmarshalJSON(data []byte) error {
+ var s string
+ if err := json.Unmarshal(data, &s); err != nil {
+ return err
+ }
+ h, err := NewHashFromStr(s)
+ if err != nil {
+ return err
+ }
+ *hash = *h
+ return nil
+}
+
+// NewHash returns a new Hash from a byte slice. An error is returned if
+// the number of bytes passed in is not HashSize.
+func NewHash(newHash []byte) (*Hash, error) {
+ var sh Hash
+ err := sh.SetBytes(newHash)
+ if err != nil {
+ return nil, err
+ }
+ return &sh, err
+}
+
+// func NewHashNoError(newHash []byte) *Hash {
+// sh, _ := NewHash(newHash)
+// return sh
+// }
+
+// NewHashFromStr creates a Hash from a hash string. The string should be
+// the hexadecimal string of a byte-reversed hash, but any missing characters
+// result in zero padding at the end of the Hash.
+func NewHashFromStr(hash string) (*Hash, error) {
+ ret := new(Hash)
+ err := Decode(ret, hash)
+ if err != nil {
+ return nil, err
+ }
+ return ret, nil
+}
+
+// func NewHashFromStrNoError(hash string) *Hash {
+// sh, _ := NewHashFromStr(hash)
+// return sh
+// }
+
+// Decode decodes the byte-reversed hexadecimal string encoding of a Hash to a
+// destination.
+func Decode(dst *Hash, src string) error {
+ // Return error if hash string is too long.
+ if len(src) > MaxHashStringSize {
+ return ErrHashStrSize
+ }
+
+ // Hex decoder expects the hash to be a multiple of two. When not, pad
+ // with a leading zero.
+ var srcBytes []byte
+ if len(src)%2 == 0 {
+ srcBytes = []byte(src)
+ } else {
+ srcBytes = make([]byte, 1+len(src))
+ srcBytes[0] = '0'
+ copy(srcBytes[1:], src)
+ }
+
+ // Hex decode the source bytes to a temporary destination.
+ var reversedHash Hash
+ _, err := hex.Decode(reversedHash[HashSize-hex.DecodedLen(len(srcBytes)):], srcBytes)
+ if err != nil {
+ return err
+ }
+
+ // Reverse copy from the temporary hash to destination. Because the
+ // temporary was zeroed, the written result will be correctly padded.
+ for i, b := range reversedHash[:HashSize/2] {
+ dst[i], dst[HashSize-1-i] = reversedHash[HashSize-1-i], b
+ }
+
+ return nil
+}
diff --git a/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/hashfuncs.go b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/hashfuncs.go
new file mode 100644
index 0000000..bf74f73
--- /dev/null
+++ b/vendor/github.com/libsv/go-p2p/chaincfg/chainhash/hashfuncs.go
@@ -0,0 +1,33 @@
+// Copyright (c) 2015 The Decred developers
+// Copyright (c) 2016-2017 The btcsuite developers
+// Use of this source code is governed by an ISC
+// license that can be found in the LICENSE file.
+
+package chainhash
+
+import "crypto/sha256"
+
+// HashB calculates hash(b) and returns the resulting bytes.
+func HashB(b []byte) []byte {
+ hash := sha256.Sum256(b)
+ return hash[:]
+}
+
+// HashH calculates hash(b) and returns the resulting bytes as a Hash.
+func HashH(b []byte) Hash {
+ return Hash(sha256.Sum256(b))
+}
+
+// DoubleHashB calculates hash(hash(b)) and returns the resulting bytes.
+func DoubleHashB(b []byte) []byte {
+ first := sha256.Sum256(b)
+ second := sha256.Sum256(first[:])
+ return second[:]
+}
+
+// DoubleHashH calculates hash(hash(b)) and returns the resulting bytes as a
+// Hash.
+func DoubleHashH(b []byte) Hash {
+ first := sha256.Sum256(b)
+ return Hash(sha256.Sum256(first[:]))
+}
diff --git a/vendor/golang.org/x/crypto/AUTHORS b/vendor/golang.org/x/crypto/AUTHORS
deleted file mode 100644
index 2b00ddb..0000000
--- a/vendor/golang.org/x/crypto/AUTHORS
+++ /dev/null
@@ -1,3 +0,0 @@
-# This source code refers to The Go Authors for copyright purposes.
-# The master list of authors is in the main Go distribution,
-# visible at https://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/crypto/CONTRIBUTORS b/vendor/golang.org/x/crypto/CONTRIBUTORS
deleted file mode 100644
index 1fbd3e9..0000000
--- a/vendor/golang.org/x/crypto/CONTRIBUTORS
+++ /dev/null
@@ -1,3 +0,0 @@
-# This source code was written by the Go contributors.
-# The master list of contributors is in the main Go distribution,
-# visible at https://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/modules.txt b/vendor/modules.txt
index babd313..9a84ec2 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,4 +1,4 @@
-# github.com/libsv/go-bc v0.1.11
+# github.com/libsv/go-bc v0.1.20
## explicit; go 1.17
github.com/libsv/go-bc
# github.com/libsv/go-bk v0.1.6
@@ -9,11 +9,14 @@ github.com/libsv/go-bk/bip32
github.com/libsv/go-bk/chaincfg
github.com/libsv/go-bk/crypto
github.com/libsv/go-bk/envelope
-# github.com/libsv/go-bt/v2 v2.1.0-beta.4
+# github.com/libsv/go-bt/v2 v2.2.5
## explicit; go 1.17
github.com/libsv/go-bt/v2
github.com/libsv/go-bt/v2/bscript
github.com/libsv/go-bt/v2/sighash
+# github.com/libsv/go-p2p v0.1.3
+## explicit; go 1.19
+github.com/libsv/go-p2p/chaincfg/chainhash
# github.com/matryer/is v1.4.0
## explicit; go 1.14
github.com/matryer/is
@@ -23,6 +26,6 @@ github.com/pkg/errors
# github.com/theflyingcodr/govalidator v0.1.3
## explicit; go 1.15
github.com/theflyingcodr/govalidator
-# golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
+# golang.org/x/crypto v0.13.0
## explicit; go 1.17
golang.org/x/crypto/ripemd160