Skip to content

Commit c3f6e6b

Browse files
committed
feat: support for proposing in script context
* un-embed ConwayProtocolParameterUpdate * fix PlutusData encodings for various gov types * create Conway-specific version of pparam update gov action * PlutusData encoding for Conway pparam update * port script_context_propose_* tests from Aiken Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 9be8367 commit c3f6e6b

File tree

10 files changed

+537
-154
lines changed

10 files changed

+537
-154
lines changed

ledger/common/gov.go

Lines changed: 54 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
package common
1616

1717
import (
18-
"fmt"
1918
"math/big"
2019

2120
"github.com/blinklabs-io/gouroboros/cbor"
@@ -129,21 +128,18 @@ func (id *GovActionId) ToPlutusData() data.PlutusData {
129128
)
130129
}
131130

132-
type ProposalProcedure struct {
133-
cbor.StructAsArray
134-
Deposit uint64
135-
RewardAccount Address
136-
GovAction GovActionWrapper
137-
Anchor GovAnchor
131+
type ProposalProcedure interface {
132+
isProposalProcedure()
133+
ToPlutusData() data.PlutusData
134+
Deposit() uint64
135+
RewardAccount() Address
136+
GovAction() GovAction
137+
Anchor() GovAnchor
138138
}
139139

140-
func (p *ProposalProcedure) ToPlutusData() data.PlutusData {
141-
return data.NewConstr(0,
142-
data.NewInteger(new(big.Int).SetUint64(p.Deposit)),
143-
p.RewardAccount.ToPlutusData(),
144-
p.GovAction.ToPlutusData(),
145-
)
146-
}
140+
type ProposalProcedureBase struct{}
141+
142+
func (ProposalProcedureBase) isProposalProcedure() {}
147143

148144
const (
149145
GovActionTypeParameterChange = 0
@@ -155,76 +151,14 @@ const (
155151
GovActionTypeInfo = 6
156152
)
157153

158-
type GovActionWrapper struct {
159-
Type uint
160-
Action GovAction
161-
}
162-
163-
func (g *GovActionWrapper) ToPlutusData() data.PlutusData {
164-
return g.Action.ToPlutusData()
165-
}
166-
167-
func (g *GovActionWrapper) UnmarshalCBOR(data []byte) error {
168-
// Determine action type
169-
actionType, err := cbor.DecodeIdFromList(data)
170-
if err != nil {
171-
return err
172-
}
173-
var tmpAction GovAction
174-
switch actionType {
175-
case GovActionTypeParameterChange:
176-
tmpAction = &ParameterChangeGovAction{}
177-
case GovActionTypeHardForkInitiation:
178-
tmpAction = &HardForkInitiationGovAction{}
179-
case GovActionTypeTreasuryWithdrawal:
180-
tmpAction = &TreasuryWithdrawalGovAction{}
181-
case GovActionTypeNoConfidence:
182-
tmpAction = &NoConfidenceGovAction{}
183-
case GovActionTypeUpdateCommittee:
184-
tmpAction = &UpdateCommitteeGovAction{}
185-
case GovActionTypeNewConstitution:
186-
tmpAction = &NewConstitutionGovAction{}
187-
case GovActionTypeInfo:
188-
tmpAction = &InfoGovAction{}
189-
default:
190-
return fmt.Errorf("unknown governance action type: %d", actionType)
191-
}
192-
// Decode action
193-
if _, err := cbor.Decode(data, tmpAction); err != nil {
194-
return err
195-
}
196-
// action type is known within uint range
197-
g.Type = uint(actionType) // #nosec G115
198-
g.Action = tmpAction
199-
return nil
200-
}
201-
202-
func (g *GovActionWrapper) MarshalCBOR() ([]byte, error) {
203-
return cbor.Encode(g.Action)
204-
}
205-
206154
type GovAction interface {
207155
isGovAction()
208156
ToPlutusData() data.PlutusData
209157
}
210158

211-
type ParameterChangeGovAction struct {
212-
cbor.StructAsArray
213-
Type uint
214-
ActionId *GovActionId
215-
ParamUpdate cbor.RawMessage // NOTE: we use raw to defer processing to account for per-era types
216-
PolicyHash []byte
217-
}
218-
219-
func (a *ParameterChangeGovAction) ToPlutusData() data.PlutusData {
220-
return data.NewConstr(0,
221-
a.ActionId.ToPlutusData(),
222-
data.NewByteString(a.ParamUpdate),
223-
data.NewByteString(a.PolicyHash),
224-
)
225-
}
159+
type GovActionBase struct{}
226160

227-
func (a ParameterChangeGovAction) isGovAction() {}
161+
func (GovActionBase) isGovAction() {}
228162

229163
type HardForkInitiationGovAction struct {
230164
cbor.StructAsArray
@@ -238,8 +172,12 @@ type HardForkInitiationGovAction struct {
238172
}
239173

240174
func (a *HardForkInitiationGovAction) ToPlutusData() data.PlutusData {
175+
actionId := data.NewConstr(1)
176+
if a.ActionId != nil {
177+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
178+
}
241179
return data.NewConstr(1,
242-
a.ActionId.ToPlutusData(),
180+
actionId,
243181
data.NewConstr(
244182
0,
245183
data.NewInteger(
@@ -265,13 +203,20 @@ func (a *TreasuryWithdrawalGovAction) ToPlutusData() data.PlutusData {
265203
pairs := make([][2]data.PlutusData, 0, len(a.Withdrawals))
266204
for addr, amount := range a.Withdrawals {
267205
pairs = append(pairs, [2]data.PlutusData{
268-
data.NewConstr(0, addr.ToPlutusData()),
206+
addr.ToPlutusData(),
269207
data.NewInteger(new(big.Int).SetUint64(amount)),
270208
})
271209
}
210+
policyHash := data.NewConstr(1)
211+
if len(a.PolicyHash) > 0 {
212+
policyHash = data.NewConstr(
213+
0,
214+
data.NewByteString(a.PolicyHash),
215+
)
216+
}
272217
return data.NewConstr(2,
273218
data.NewMap(pairs),
274-
data.NewByteString(a.PolicyHash),
219+
policyHash,
275220
)
276221
}
277222

@@ -284,8 +229,12 @@ type NoConfidenceGovAction struct {
284229
}
285230

286231
func (a *NoConfidenceGovAction) ToPlutusData() data.PlutusData {
232+
actionId := data.NewConstr(1)
233+
if a.ActionId != nil {
234+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
235+
}
287236
return data.NewConstr(3,
288-
a.ActionId.ToPlutusData(),
237+
actionId,
289238
)
290239
}
291240

@@ -301,6 +250,10 @@ type UpdateCommitteeGovAction struct {
301250
}
302251

303252
func (a *UpdateCommitteeGovAction) ToPlutusData() data.PlutusData {
253+
actionId := data.NewConstr(1)
254+
if a.ActionId != nil {
255+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
256+
}
304257
removedItems := make([]data.PlutusData, 0, len(a.Credentials))
305258
for _, cred := range a.Credentials {
306259
removedItems = append(removedItems, cred.ToPlutusData())
@@ -325,11 +278,14 @@ func (a *UpdateCommitteeGovAction) ToPlutusData() data.PlutusData {
325278
}
326279

327280
return data.NewConstr(4,
328-
a.ActionId.ToPlutusData(),
281+
actionId,
329282
data.NewList(removedItems...),
330283
data.NewMap(addedPairs),
331-
data.NewInteger(num),
332-
data.NewInteger(den),
284+
data.NewConstr(
285+
0,
286+
data.NewInteger(num),
287+
data.NewInteger(den),
288+
),
333289
)
334290
}
335291

@@ -347,11 +303,21 @@ type NewConstitutionGovAction struct {
347303
}
348304

349305
func (a *NewConstitutionGovAction) ToPlutusData() data.PlutusData {
306+
actionId := data.NewConstr(1)
307+
if a.ActionId != nil {
308+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
309+
}
310+
scriptHash := data.NewConstr(1)
311+
if len(a.Constitution.ScriptHash) > 0 {
312+
scriptHash = data.NewConstr(
313+
0,
314+
data.NewByteString(a.Constitution.ScriptHash),
315+
)
316+
}
350317
return data.NewConstr(5,
351-
a.ActionId.ToPlutusData(),
318+
actionId,
352319
data.NewConstr(0,
353-
a.Constitution.Anchor.ToPlutusData(),
354-
data.NewByteString(a.Constitution.ScriptHash),
320+
scriptHash,
355321
),
356322
)
357323
}

ledger/common/gov_test.go

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -262,23 +262,6 @@ func TestVotingProcedureToPlutusData(t *testing.T) {
262262
}
263263
}
264264

265-
func TestProposalProcedureToPlutusData(t *testing.T) {
266-
addr := Address{}
267-
action := &InfoGovAction{}
268-
269-
pp := &ProposalProcedure{
270-
Deposit: 1000000,
271-
RewardAccount: addr,
272-
GovAction: GovActionWrapper{Action: action},
273-
}
274-
275-
pd := pp.ToPlutusData()
276-
constr, ok := pd.(*data.Constr)
277-
assert.True(t, ok)
278-
assert.Equal(t, uint(0), constr.Tag)
279-
assert.Len(t, constr.Fields, 3)
280-
}
281-
282265
func TestGovActionIdToPlutusData(t *testing.T) {
283266
txId := [32]byte{1, 2, 3, 4}
284267
govActionId := &GovActionId{
@@ -293,20 +276,6 @@ func TestGovActionIdToPlutusData(t *testing.T) {
293276
assert.Len(t, constr.Fields, 2)
294277
}
295278

296-
func TestParameterChangeGovActionToPlutusData(t *testing.T) {
297-
action := &ParameterChangeGovAction{
298-
ActionId: &GovActionId{},
299-
ParamUpdate: []byte{1, 2, 3},
300-
PolicyHash: []byte{4, 5, 6},
301-
}
302-
303-
pd := action.ToPlutusData()
304-
constr, ok := pd.(*data.Constr)
305-
assert.True(t, ok)
306-
assert.Equal(t, uint(0), constr.Tag)
307-
assert.Len(t, constr.Fields, 3)
308-
}
309-
310279
func TestHardForkInitiationGovActionToPlutusData(t *testing.T) {
311280
action := &HardForkInitiationGovAction{
312281
ActionId: &GovActionId{},
@@ -383,12 +352,16 @@ func TestUpdateCommitteeGovActionToPlutusData(t *testing.T) {
383352
assert.True(t, ok)
384353
assert.Equal(t, uint(4), constr.Tag)
385354

355+
innerConstr, ok := constr.Fields[3].(*data.Constr)
356+
assert.True(t, ok)
357+
assert.Equal(t, uint(0), innerConstr.Tag)
358+
386359
// Verify default values were used
387-
num, ok := constr.Fields[3].(*data.Integer)
360+
num, ok := innerConstr.Fields[0].(*data.Integer)
388361
assert.True(t, ok)
389362
assert.Equal(t, int64(0), num.Inner.Int64())
390363

391-
den, ok := constr.Fields[4].(*data.Integer)
364+
den, ok := innerConstr.Fields[1].(*data.Integer)
392365
assert.True(t, ok)
393366
assert.Equal(t, int64(1), den.Inner.Int64())
394367
})

ledger/common/script/context.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,7 @@ func (t TxInfoV3) ToPlutusData() data.PlutusData {
161161
t.Data.ToPlutusData(),
162162
data.NewByteString(t.Id.Bytes()),
163163
t.Votes.ToPlutusData(),
164-
// TODO: proposal procedures
165-
toPlutusData([]any{}),
164+
toPlutusData(t.ProposalProcedures),
166165
t.CurrentTreasuryAmount.ToPlutusData(),
167166
t.TreasuryDonation.ToPlutusData(),
168167
)
@@ -188,6 +187,7 @@ func NewTxInfoV3FromTransaction(
188187
inputs := sortInputs(tx.Inputs())
189188
withdrawals := withdrawalsInfo(tx.Withdrawals())
190189
votes := votingInfo(tx.VotingProcedures())
190+
proposalProcedures := tx.ProposalProcedures()
191191
redeemers := redeemersInfo(
192192
tx.Witnesses(),
193193
scriptPurposeBuilder(
@@ -196,8 +196,8 @@ func NewTxInfoV3FromTransaction(
196196
*assetMint,
197197
tx.Certificates(),
198198
withdrawals,
199-
// TODO: proposal procedures
200199
votes,
200+
proposalProcedures,
201201
),
202202
)
203203
tmpData := dataInfo(tx.Witnesses())
@@ -207,18 +207,18 @@ func NewTxInfoV3FromTransaction(
207207
sortInputs(tx.ReferenceInputs()),
208208
resolvedInputs,
209209
),
210-
Outputs: collapseOutputs(tx.Produced()),
211-
Fee: tx.Fee(),
212-
Mint: *assetMint,
213-
ValidRange: validityRange,
214-
Certificates: tx.Certificates(),
215-
Withdrawals: withdrawals,
216-
Signatories: signatoriesInfo(tx.RequiredSigners()),
217-
Redeemers: redeemers,
218-
Data: tmpData,
219-
Id: tx.Hash(),
220-
Votes: votes,
221-
// TODO: ProposalProcedures
210+
Outputs: collapseOutputs(tx.Produced()),
211+
Fee: tx.Fee(),
212+
Mint: *assetMint,
213+
ValidRange: validityRange,
214+
Certificates: tx.Certificates(),
215+
Withdrawals: withdrawals,
216+
Signatories: signatoriesInfo(tx.RequiredSigners()),
217+
Redeemers: redeemers,
218+
Data: tmpData,
219+
Id: tx.Hash(),
220+
Votes: votes,
221+
ProposalProcedures: proposalProcedures,
222222
}
223223
if amt := tx.CurrentTreasuryValue(); amt > 0 {
224224
ret.CurrentTreasuryAmount.Value = amt

0 commit comments

Comments
 (0)