Skip to content

Commit 7925c2f

Browse files
authored
Merge pull request #125 from BitcoinSchema/multiple-aip
Support validation of multiple AIPs in an output
2 parents 69d9dae + 8366080 commit 7925c2f

File tree

4 files changed

+117
-43
lines changed

4 files changed

+117
-43
lines changed

aip_test.go

+22
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,25 @@ func TestFromRawTx(t *testing.T) {
426426

427427
t.Log(a.Validate())
428428
}
429+
430+
func TestMultipleAIPs(t *testing.T) {
431+
432+
tx, err := bob.NewFromRawTxString("0100000001cad37bb62389fadd4ba383ef1a1d5edd5212de2ca87fc1b496fdd4163c932ecb010000008a473044022037bcb44b29c44be44f333dc8e2635e67eb1f21f7f38b86119055dfd975f01d7d022070ebbea020c24ea90eb367db07e5b03c082b1cab814281507b1f814195413faa4141043cf0a503fd150ad112de4503f7dd17dcdba99e41cd7f8b52315fa1a4f9e499b9493fddcc15a594022f9734b8cf12a068d51328664192f351c3b618e52ae1f85fffffffff020000000000000000fd74016a2231394878696756345179427633744870515663554551797131707a5a56646f4175740c48656c6c6f20776f726c64210a746578742f706c61696e057574662d380100017c22313550636948473232534e4c514a584d6f53556157566937575371633768436676610d424954434f494e5f45434453412231455868536247466945415a4345356565427655785436634256486872705057587a411cacee1dbe375e3e17a662b560944e0ff78dff9f194744fb2ee462d905bc785727420d5deed4b2dd019023f550af4f4f7934050179e217220592a41882f0251ef4017c22313550636948473232534e4c514a584d6f53556157566937575371633768436676610d424954434f494e5f45434453412231396e6b6e4c68526e474b525233686f6265467575716d48554d694e544b5a487352411c101c7d3cb207a6718e773856349b47e6676bf8b1be2c3096841b2181d736ab156645e0a84318dc0691574a26ed9a7c9b8abe7e0c30af845680259f59ceec319dbdc60500000000001976a9149467df677dc153a88243465d09ca5fe8f7ba8cf988ac00000000")
433+
if err != nil {
434+
t.Fatalf("error occurred: %s", err.Error())
435+
}
436+
437+
aips := NewFromAllTapes(tx.Out[0].Tape)
438+
439+
t.Log(aips)
440+
// t.Log(a)
441+
for _, a := range aips {
442+
t.Log(a.Algorithm)
443+
t.Log(a.AlgorithmSigningComponent)
444+
t.Log(a.Signature)
445+
t.Log(len(strings.Join(a.Data, "")))
446+
t.Log(a.Data)
447+
448+
t.Log(a.Validate())
449+
}
450+
}

bob.go

+84-32
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func NewFromTapes(tapes []bpu.Tape) (a *Aip) {
8181
if cell.S != nil && *cell.S == Prefix {
8282
a = new(Aip)
8383
a.FromTape(t)
84-
a.SetDataFromTapes(tapes)
84+
a.SetDataFromTapes(tapes, 0)
8585
return
8686
}
8787
}
@@ -90,50 +90,80 @@ func NewFromTapes(tapes []bpu.Tape) (a *Aip) {
9090
}
9191

9292
// SetDataFromTapes sets the data the AIP signature is signing
93-
func (a *Aip) SetDataFromTapes(tapes []bpu.Tape) {
94-
93+
func (a *Aip) SetDataFromTapes(tapes []bpu.Tape, instance int) {
9594
// Set OP_RETURN to be consistent with BitcoinFiles SDK
95+
// var data [][]byte
9696
var data = []string{opReturn}
97+
var foundAIP bool
98+
var aipTapeIndex int
99+
var aipCellIndex int
97100

98-
if len(a.Indices) == 0 {
99-
100-
// Walk over all output values and concatenate them until we hit the AIP prefix, then add in the separator
101-
for _, tape := range tapes {
102-
for _, cell := range tape.Cell {
103-
if cell.S != nil && *cell.S == Prefix {
104-
data = append(data, pipe)
105-
a.Data = data
106-
return
107-
}
108-
// Skip the OPS
109-
// if cell.Ops != nil {
110-
if cell.Op != nil && (*cell.Op == 0 || *cell.Op > 0x4e) {
111-
continue
112-
}
113-
if cell.S != nil {
114-
data = append(data, strings.TrimSpace(*cell.S))
101+
// First find the AIP tape and cell index
102+
aipCount := 0
103+
for i, tape := range tapes {
104+
for j, cell := range tape.Cell {
105+
if cell.S != nil && *cell.S == Prefix {
106+
if aipCount == instance {
107+
aipTapeIndex = i
108+
aipCellIndex = j
109+
foundAIP = true
110+
break
115111
}
116-
112+
aipCount++
117113
}
114+
118115
}
116+
if foundAIP {
117+
break
118+
}
119+
}
120+
121+
// If we found AIP, collect data from all tapes up to the AIP tape
122+
if foundAIP {
123+
if len(a.Indices) == 0 {
124+
125+
// Walk over all output values and concatenate them until we hit the AIP prefix, then add in the separator
126+
for i, tape := range tapes {
127+
for j, cell := range tape.Cell {
119128

120-
} else {
129+
if cell.S != nil && *cell.S == Prefix {
130+
data = append(data, pipe)
131+
a.Data = data
132+
if i == aipTapeIndex && j >= aipCellIndex {
133+
return
134+
}
135+
}
121136

122-
var indexCt = 0
137+
// Skip the OPS
138+
// if cell.Ops != nil {
139+
if cell.Op != nil && (*cell.Op == 0 || *cell.Op > 0x4e) {
140+
continue
141+
}
142+
if cell.S != nil {
143+
data = append(data, strings.TrimSpace(*cell.S))
144+
}
123145

124-
for _, tape := range tapes {
125-
for _, cell := range tape.Cell {
126-
if cell.S != nil && *cell.S != Prefix && contains(a.Indices, indexCt) {
127-
data = append(data, *cell.S)
128-
} else {
129-
data = append(data, pipe)
130146
}
131-
indexCt++
132147
}
133-
}
134148

149+
} else {
150+
151+
var indexCt = 0
152+
153+
for _, tape := range tapes {
154+
for _, cell := range tape.Cell {
155+
if cell.S != nil && *cell.S != Prefix && contains(a.Indices, indexCt) {
156+
data = append(data, *cell.S)
157+
} else {
158+
data = append(data, pipe)
159+
}
160+
indexCt++
161+
}
162+
}
163+
}
135164
a.Data = data
136165
}
166+
137167
}
138168

139169
// SignBobOpReturnData appends a signature to a BOB Tx by adding a
@@ -200,7 +230,7 @@ func ValidateTapes(tapes []bpu.Tape) (bool, error) {
200230
// Once we hit AIP Prefix, stop
201231
if cell.S != nil && *cell.S == Prefix {
202232
a := NewFromTape(tape)
203-
a.SetDataFromTapes(tapes)
233+
a.SetDataFromTapes(tapes, 0)
204234
return a.Validate()
205235
}
206236
}
@@ -218,3 +248,25 @@ func contains(s []int, e int) bool {
218248
}
219249
return false
220250
}
251+
252+
// NewFromAllTapes will create all AIP objects from a []bob.Tape
253+
func NewFromAllTapes(tapes []bpu.Tape) []*Aip {
254+
var aips []*Aip
255+
256+
// Find all tapes that contain the AIP prefix
257+
instance := 0
258+
for i, t := range tapes {
259+
for _, cell := range t.Cell {
260+
if cell.S != nil && *cell.S == Prefix {
261+
a := new(Aip)
262+
a.FromTape(t)
263+
// For all AIP entries, include all data from the start up to this entry
264+
a.SetDataFromTapes(tapes[:i+1], instance)
265+
instance++
266+
aips = append(aips, a)
267+
continue
268+
}
269+
}
270+
}
271+
return aips
272+
}

go.mod

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ go 1.23.1
44

55
require (
66
github.com/bitcoin-sv/go-sdk v1.1.18
7-
github.com/bitcoinschema/go-bob v0.5.0
8-
github.com/bitcoinschema/go-bpu v0.2.0
7+
github.com/bitcoinschema/go-bob v0.5.1
8+
github.com/bitcoinschema/go-bpu v0.2.1
99

1010
)
1111

1212
require (
1313
github.com/pkg/errors v0.9.1 // indirect
14-
golang.org/x/crypto v0.31.0 // indirect
14+
golang.org/x/crypto v0.32.0 // indirect
1515
)

go.sum

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
github.com/bitcoin-sv/go-sdk v1.1.18 h1:6lMdQGxlLFWysR2O4m8t0FpdEmdvqHIvYjp8+UV8AjI=
22
github.com/bitcoin-sv/go-sdk v1.1.18/go.mod h1:E/gP4wd23aa7clO4vYx+xMNwEs/I3shKv5NdwWgNkx8=
3-
github.com/bitcoinschema/go-bob v0.5.0 h1:Fjl60RuiQiUuZWLfXE8ETdcgmJBHYu9MYfbrbZU7yHs=
4-
github.com/bitcoinschema/go-bob v0.5.0/go.mod h1:bREtBvZuMKe3DX2oCUSE+LOuy9HDJnOC3qcWr0oLoy4=
5-
github.com/bitcoinschema/go-bpu v0.2.0 h1:/WI/F+ShIj50HUD1EBPPHTCBzSeiPDohy77W3Y8xx+s=
6-
github.com/bitcoinschema/go-bpu v0.2.0/go.mod h1:58mg4m1wlQY3TFfvlba7zRs5dTb4O2cqlzRWjcJPLuo=
3+
github.com/bitcoinschema/go-bob v0.5.1 h1:pvRX16sAkQRRNBu1UpRnrbd/WX9MKwYEh0LRb7/u9FI=
4+
github.com/bitcoinschema/go-bob v0.5.1/go.mod h1:z/et0FNbSJobzmU6cQYjByGFNcUfRwgSsqKR9uJOg9k=
5+
github.com/bitcoinschema/go-bpu v0.2.1 h1:4p4LKa+BtP4Ahv5wFbt/RuQbob3u37CrBSuD1aruSQ0=
6+
github.com/bitcoinschema/go-bpu v0.2.1/go.mod h1:WhXazKw2p4OIKhkd5A9JgDsaq3a7QRPmqzwCb/835uA=
77
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
88
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
99
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
1010
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
1111
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1212
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
13-
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
14-
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
15-
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
16-
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
13+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
14+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
15+
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
16+
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
1717
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1818
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)