Skip to content

Commit 1483e8a

Browse files
authored
feat: support for proposing in script context (#1175)
* 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 1483e8a

File tree

10 files changed

+539
-154
lines changed

10 files changed

+539
-154
lines changed

ledger/common/gov.go

Lines changed: 56 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,19 @@ 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+
// nolint:unused
143+
func (ProposalProcedureBase) isProposalProcedure() {}
147144

148145
const (
149146
GovActionTypeParameterChange = 0
@@ -155,76 +152,15 @@ const (
155152
GovActionTypeInfo = 6
156153
)
157154

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-
206155
type GovAction interface {
207156
isGovAction()
208157
ToPlutusData() data.PlutusData
209158
}
210159

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-
}
160+
type GovActionBase struct{}
226161

227-
func (a ParameterChangeGovAction) isGovAction() {}
162+
// nolint:unused
163+
func (GovActionBase) isGovAction() {}
228164

229165
type HardForkInitiationGovAction struct {
230166
cbor.StructAsArray
@@ -238,8 +174,12 @@ type HardForkInitiationGovAction struct {
238174
}
239175

240176
func (a *HardForkInitiationGovAction) ToPlutusData() data.PlutusData {
177+
actionId := data.NewConstr(1)
178+
if a.ActionId != nil {
179+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
180+
}
241181
return data.NewConstr(1,
242-
a.ActionId.ToPlutusData(),
182+
actionId,
243183
data.NewConstr(
244184
0,
245185
data.NewInteger(
@@ -265,13 +205,20 @@ func (a *TreasuryWithdrawalGovAction) ToPlutusData() data.PlutusData {
265205
pairs := make([][2]data.PlutusData, 0, len(a.Withdrawals))
266206
for addr, amount := range a.Withdrawals {
267207
pairs = append(pairs, [2]data.PlutusData{
268-
data.NewConstr(0, addr.ToPlutusData()),
208+
addr.ToPlutusData(),
269209
data.NewInteger(new(big.Int).SetUint64(amount)),
270210
})
271211
}
212+
policyHash := data.NewConstr(1)
213+
if len(a.PolicyHash) > 0 {
214+
policyHash = data.NewConstr(
215+
0,
216+
data.NewByteString(a.PolicyHash),
217+
)
218+
}
272219
return data.NewConstr(2,
273220
data.NewMap(pairs),
274-
data.NewByteString(a.PolicyHash),
221+
policyHash,
275222
)
276223
}
277224

@@ -284,8 +231,12 @@ type NoConfidenceGovAction struct {
284231
}
285232

286233
func (a *NoConfidenceGovAction) ToPlutusData() data.PlutusData {
234+
actionId := data.NewConstr(1)
235+
if a.ActionId != nil {
236+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
237+
}
287238
return data.NewConstr(3,
288-
a.ActionId.ToPlutusData(),
239+
actionId,
289240
)
290241
}
291242

@@ -301,6 +252,10 @@ type UpdateCommitteeGovAction struct {
301252
}
302253

303254
func (a *UpdateCommitteeGovAction) ToPlutusData() data.PlutusData {
255+
actionId := data.NewConstr(1)
256+
if a.ActionId != nil {
257+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
258+
}
304259
removedItems := make([]data.PlutusData, 0, len(a.Credentials))
305260
for _, cred := range a.Credentials {
306261
removedItems = append(removedItems, cred.ToPlutusData())
@@ -325,11 +280,14 @@ func (a *UpdateCommitteeGovAction) ToPlutusData() data.PlutusData {
325280
}
326281

327282
return data.NewConstr(4,
328-
a.ActionId.ToPlutusData(),
283+
actionId,
329284
data.NewList(removedItems...),
330285
data.NewMap(addedPairs),
331-
data.NewInteger(num),
332-
data.NewInteger(den),
286+
data.NewConstr(
287+
0,
288+
data.NewInteger(num),
289+
data.NewInteger(den),
290+
),
333291
)
334292
}
335293

@@ -347,11 +305,21 @@ type NewConstitutionGovAction struct {
347305
}
348306

349307
func (a *NewConstitutionGovAction) ToPlutusData() data.PlutusData {
308+
actionId := data.NewConstr(1)
309+
if a.ActionId != nil {
310+
actionId = data.NewConstr(0, a.ActionId.ToPlutusData())
311+
}
312+
scriptHash := data.NewConstr(1)
313+
if len(a.Constitution.ScriptHash) > 0 {
314+
scriptHash = data.NewConstr(
315+
0,
316+
data.NewByteString(a.Constitution.ScriptHash),
317+
)
318+
}
350319
return data.NewConstr(5,
351-
a.ActionId.ToPlutusData(),
320+
actionId,
352321
data.NewConstr(0,
353-
a.Constitution.Anchor.ToPlutusData(),
354-
data.NewByteString(a.Constitution.ScriptHash),
322+
scriptHash,
355323
),
356324
)
357325
}

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)