Skip to content

Commit 71658ab

Browse files
authored
refactor: helper function for getting script hash from script purpose (#1161)
This also moves the bits related to the script purpose/info into a separate file Fixes #1160 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 619468f commit 71658ab

File tree

3 files changed

+206
-151
lines changed

3 files changed

+206
-151
lines changed

ledger/common/script/scriptcontext.go renamed to ledger/common/script/context.go

Lines changed: 0 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -258,94 +258,6 @@ func (t TimeRange) ToPlutusData() data.PlutusData {
258258
)
259259
}
260260

261-
type ScriptInfo interface {
262-
isScriptInfo()
263-
ToPlutusData
264-
}
265-
266-
type ScriptInfoMinting struct {
267-
PolicyId lcommon.Blake2b224
268-
}
269-
270-
func (ScriptInfoMinting) isScriptInfo() {}
271-
272-
func (s ScriptInfoMinting) ToPlutusData() data.PlutusData {
273-
return data.NewConstr(
274-
0,
275-
data.NewByteString(s.PolicyId.Bytes()),
276-
)
277-
}
278-
279-
type ScriptInfoSpending struct {
280-
Input lcommon.TransactionInput
281-
Datum data.PlutusData
282-
}
283-
284-
func (ScriptInfoSpending) isScriptInfo() {}
285-
286-
func (s ScriptInfoSpending) ToPlutusData() data.PlutusData {
287-
if s.Datum == nil {
288-
return data.NewConstr(
289-
1,
290-
s.Input.ToPlutusData(),
291-
)
292-
}
293-
return data.NewConstr(
294-
1,
295-
s.Input.ToPlutusData(),
296-
data.NewConstr(
297-
0,
298-
s.Datum,
299-
),
300-
)
301-
}
302-
303-
type ScriptInfoRewarding struct {
304-
StakeCredential lcommon.Credential
305-
}
306-
307-
func (ScriptInfoRewarding) isScriptInfo() {}
308-
309-
func (s ScriptInfoRewarding) ToPlutusData() data.PlutusData {
310-
// TODO
311-
return nil
312-
}
313-
314-
type ScriptInfoCertifying struct {
315-
Size uint64
316-
Certificate lcommon.Certificate
317-
}
318-
319-
func (ScriptInfoCertifying) isScriptInfo() {}
320-
321-
func (s ScriptInfoCertifying) ToPlutusData() data.PlutusData {
322-
// TODO
323-
return nil
324-
}
325-
326-
type ScriptInfoVoting struct {
327-
Voter lcommon.Voter
328-
}
329-
330-
func (ScriptInfoVoting) isScriptInfo() {}
331-
332-
func (s ScriptInfoVoting) ToPlutusData() data.PlutusData {
333-
// TODO
334-
return nil
335-
}
336-
337-
type ScriptInfoProposing struct {
338-
Size uint64
339-
ProposalProcedure lcommon.ProposalProcedure
340-
}
341-
342-
func (ScriptInfoProposing) isScriptInfo() {}
343-
344-
func (s ScriptInfoProposing) ToPlutusData() data.PlutusData {
345-
// TODO
346-
return nil
347-
}
348-
349261
func sortInputs(inputs []lcommon.TransactionInput) []lcommon.TransactionInput {
350262
ret := make([]lcommon.TransactionInput, len(inputs))
351263
copy(ret, inputs)
@@ -484,66 +396,3 @@ func signatoriesInfo(
484396
)
485397
return tmp
486398
}
487-
488-
type toScriptPurposeFunc func(lcommon.RedeemerKey) ScriptInfo
489-
490-
// scriptPurposeBuilder creates a reusable function preloaded with information about a particular transaction
491-
func scriptPurposeBuilder(
492-
resolvedInputs []lcommon.Utxo,
493-
inputs []lcommon.TransactionInput,
494-
mint lcommon.MultiAsset[lcommon.MultiAssetTypeMint],
495-
// TODO: certificates
496-
withdrawals map[*lcommon.Address]uint64,
497-
// TODO: proposal procedures
498-
// TODO: votes
499-
) toScriptPurposeFunc {
500-
return func(redeemerKey lcommon.RedeemerKey) ScriptInfo {
501-
// TODO: implement additional redeemer tags
502-
// https://github.com/aiken-lang/aiken/blob/af4e04b91e54dbba3340de03fc9e65a90f24a93b/crates/uplc/src/tx/script_context.rs#L771-L826
503-
switch redeemerKey.Tag {
504-
case lcommon.RedeemerTagSpend:
505-
var datum data.PlutusData
506-
tmpInput := inputs[redeemerKey.Index]
507-
for _, resolvedInput := range resolvedInputs {
508-
if resolvedInput.Id.String() == tmpInput.String() {
509-
if tmpDatum := resolvedInput.Output.Datum(); tmpDatum != nil {
510-
datum = tmpDatum.Data
511-
}
512-
break
513-
}
514-
}
515-
return ScriptInfoSpending{
516-
Input: inputs[redeemerKey.Index],
517-
Datum: datum,
518-
}
519-
case lcommon.RedeemerTagMint:
520-
// TODO: fix this to work for more than one minted policy
521-
mintPolicies := mint.Policies()
522-
slices.SortFunc(
523-
mintPolicies,
524-
func(a, b lcommon.Blake2b224) int { return bytes.Compare(a.Bytes(), b.Bytes()) },
525-
)
526-
return ScriptInfoMinting{
527-
PolicyId: mintPolicies[redeemerKey.Index],
528-
}
529-
case lcommon.RedeemerTagCert:
530-
return nil
531-
case lcommon.RedeemerTagReward:
532-
return nil
533-
case lcommon.RedeemerTagVoting:
534-
return nil
535-
case lcommon.RedeemerTagProposing:
536-
return nil
537-
}
538-
return nil
539-
}
540-
}
541-
542-
func scriptPurposeStripDatum(purpose ScriptInfo) ScriptInfo {
543-
switch p := purpose.(type) {
544-
case ScriptInfoSpending:
545-
p.Datum = nil
546-
return p
547-
}
548-
return purpose
549-
}

ledger/common/script/purpose.go

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
// Copyright 2025 Blink Labs Software
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package script
16+
17+
import (
18+
"bytes"
19+
"slices"
20+
21+
lcommon "github.com/blinklabs-io/gouroboros/ledger/common"
22+
"github.com/blinklabs-io/plutigo/data"
23+
)
24+
25+
type ScriptInfo interface {
26+
isScriptInfo()
27+
ScriptHash() lcommon.ScriptHash
28+
ToPlutusData
29+
}
30+
31+
type ScriptInfoMinting struct {
32+
PolicyId lcommon.Blake2b224
33+
}
34+
35+
func (ScriptInfoMinting) isScriptInfo() {}
36+
37+
func (s ScriptInfoMinting) ScriptHash() lcommon.ScriptHash {
38+
return s.PolicyId
39+
}
40+
41+
func (s ScriptInfoMinting) ToPlutusData() data.PlutusData {
42+
return data.NewConstr(
43+
0,
44+
data.NewByteString(s.PolicyId.Bytes()),
45+
)
46+
}
47+
48+
type ScriptInfoSpending struct {
49+
Input lcommon.Utxo
50+
Datum data.PlutusData
51+
}
52+
53+
func (ScriptInfoSpending) isScriptInfo() {}
54+
55+
func (s ScriptInfoSpending) ScriptHash() lcommon.ScriptHash {
56+
tmpAddr := s.Input.Output.Address()
57+
return tmpAddr.PaymentKeyHash()
58+
}
59+
60+
func (s ScriptInfoSpending) ToPlutusData() data.PlutusData {
61+
if s.Datum == nil {
62+
return data.NewConstr(
63+
1,
64+
s.Input.Id.ToPlutusData(),
65+
)
66+
}
67+
return data.NewConstr(
68+
1,
69+
s.Input.Id.ToPlutusData(),
70+
data.NewConstr(
71+
0,
72+
s.Datum,
73+
),
74+
)
75+
}
76+
77+
type ScriptInfoRewarding struct {
78+
StakeCredential lcommon.Credential
79+
}
80+
81+
func (ScriptInfoRewarding) isScriptInfo() {}
82+
83+
func (s ScriptInfoRewarding) ScriptHash() lcommon.ScriptHash {
84+
// TODO
85+
return lcommon.ScriptHash{}
86+
}
87+
88+
func (s ScriptInfoRewarding) ToPlutusData() data.PlutusData {
89+
// TODO
90+
return nil
91+
}
92+
93+
type ScriptInfoCertifying struct {
94+
Size uint64
95+
Certificate lcommon.Certificate
96+
}
97+
98+
func (ScriptInfoCertifying) isScriptInfo() {}
99+
100+
func (s ScriptInfoCertifying) ScriptHash() lcommon.ScriptHash {
101+
// TODO
102+
return lcommon.ScriptHash{}
103+
}
104+
105+
func (s ScriptInfoCertifying) ToPlutusData() data.PlutusData {
106+
// TODO
107+
return nil
108+
}
109+
110+
type ScriptInfoVoting struct {
111+
Voter lcommon.Voter
112+
}
113+
114+
func (ScriptInfoVoting) isScriptInfo() {}
115+
116+
func (s ScriptInfoVoting) ScriptHash() lcommon.ScriptHash {
117+
// TODO
118+
return lcommon.ScriptHash{}
119+
}
120+
121+
func (s ScriptInfoVoting) ToPlutusData() data.PlutusData {
122+
// TODO
123+
return nil
124+
}
125+
126+
type ScriptInfoProposing struct {
127+
Size uint64
128+
ProposalProcedure lcommon.ProposalProcedure
129+
}
130+
131+
func (ScriptInfoProposing) isScriptInfo() {}
132+
133+
func (s ScriptInfoProposing) ScriptHash() lcommon.ScriptHash {
134+
// TODO
135+
return lcommon.ScriptHash{}
136+
}
137+
138+
func (s ScriptInfoProposing) ToPlutusData() data.PlutusData {
139+
// TODO
140+
return nil
141+
}
142+
143+
type toScriptPurposeFunc func(lcommon.RedeemerKey) ScriptInfo
144+
145+
// scriptPurposeBuilder creates a reusable function preloaded with information about a particular transaction
146+
func scriptPurposeBuilder(
147+
resolvedInputs []lcommon.Utxo,
148+
inputs []lcommon.TransactionInput,
149+
mint lcommon.MultiAsset[lcommon.MultiAssetTypeMint],
150+
// TODO: certificates
151+
withdrawals map[*lcommon.Address]uint64,
152+
// TODO: proposal procedures
153+
// TODO: votes
154+
) toScriptPurposeFunc {
155+
return func(redeemerKey lcommon.RedeemerKey) ScriptInfo {
156+
// TODO: implement additional redeemer tags
157+
// https://github.com/aiken-lang/aiken/blob/af4e04b91e54dbba3340de03fc9e65a90f24a93b/crates/uplc/src/tx/script_context.rs#L771-L826
158+
switch redeemerKey.Tag {
159+
case lcommon.RedeemerTagSpend:
160+
var datum data.PlutusData
161+
tmpInput := inputs[redeemerKey.Index]
162+
var resolvedInput lcommon.Utxo
163+
for _, tmpResolvedInput := range resolvedInputs {
164+
if tmpResolvedInput.Id.String() == tmpInput.String() {
165+
resolvedInput = tmpResolvedInput
166+
if tmpDatum := resolvedInput.Output.Datum(); tmpDatum != nil {
167+
datum = tmpDatum.Data
168+
}
169+
break
170+
}
171+
}
172+
return ScriptInfoSpending{
173+
Input: resolvedInput,
174+
Datum: datum,
175+
}
176+
case lcommon.RedeemerTagMint:
177+
// TODO: fix this to work for more than one minted policy
178+
mintPolicies := mint.Policies()
179+
slices.SortFunc(
180+
mintPolicies,
181+
func(a, b lcommon.Blake2b224) int { return bytes.Compare(a.Bytes(), b.Bytes()) },
182+
)
183+
return ScriptInfoMinting{
184+
PolicyId: mintPolicies[redeemerKey.Index],
185+
}
186+
case lcommon.RedeemerTagCert:
187+
return nil
188+
case lcommon.RedeemerTagReward:
189+
return nil
190+
case lcommon.RedeemerTagVoting:
191+
return nil
192+
case lcommon.RedeemerTagProposing:
193+
return nil
194+
}
195+
return nil
196+
}
197+
}
198+
199+
func scriptPurposeStripDatum(purpose ScriptInfo) ScriptInfo {
200+
switch p := purpose.(type) {
201+
case ScriptInfoSpending:
202+
p.Datum = nil
203+
return p
204+
}
205+
return purpose
206+
}

0 commit comments

Comments
 (0)