Skip to content

Commit 6a40143

Browse files
authored
feat: Shelley era 'Utxo' validation rules (#881)
This implements the remainder of the Shelley era "Utxo" validation rules, as well as tests for each. It also includes the following changes to support the validation rules: * expose address network ID, type, and Byron attributes * add helpers for ShelleyTransactionInputSet to make use in tests easier * change UtxoState interface to lookup a single UTxO at a time * add NetworkId() to LedgerState interface * add String() to TransactionInput interface Fixes #875 Signed-off-by: Aurora Gaffney <[email protected]>
1 parent 2876b3c commit 6a40143

File tree

7 files changed

+1067
-5
lines changed

7 files changed

+1067
-5
lines changed

ledger/common/address.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,25 @@ func (a *Address) MarshalCBOR() ([]byte, error) {
276276
return cbor.Encode(addrBytes)
277277
}
278278

279+
func (a Address) NetworkId() uint {
280+
if a.addressType == AddressTypeByron {
281+
if a.byronAddressAttr.Network == nil {
282+
return AddressNetworkMainnet
283+
}
284+
return uint(*a.byronAddressAttr.Network)
285+
} else {
286+
return uint(a.networkId)
287+
}
288+
}
289+
290+
func (a Address) Type() uint8 {
291+
return a.addressType
292+
}
293+
294+
func (a Address) ByronType() uint64 {
295+
return a.byronAddressType
296+
}
297+
279298
// PaymentAddress returns a new Address with only the payment address portion. This will return nil for anything other than payment and script addresses
280299
func (a Address) PaymentAddress() *Address {
281300
var addrType uint8
@@ -337,6 +356,10 @@ func (a *Address) StakeKeyHash() Blake2b224 {
337356
return Blake2b224(a.stakingAddress[:])
338357
}
339358

359+
func (a *Address) ByronAttr() ByronAddressAttributes {
360+
return a.byronAddressAttr
361+
}
362+
340363
func (a Address) generateHRP() string {
341364
var ret string
342365
if a.addressType == AddressTypeNoneKey ||

ledger/common/state.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020

2121
// UtxoState defines the interface for querying the UTxO state
2222
type UtxoState interface {
23-
UtxosById([]TransactionInput) ([]Utxo, error)
23+
UtxoById(TransactionInput) (Utxo, error)
2424
}
2525

2626
// CertState defines the interface for querying the certificate state
@@ -30,6 +30,7 @@ type CertState interface{}
3030
type LedgerState interface {
3131
UtxoState
3232
CertState
33+
NetworkId() uint
3334
}
3435

3536
// TipState defines the interface for querying the current tip

ledger/common/tx.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type TransactionBody interface {
5858
type TransactionInput interface {
5959
Id() Blake2b256
6060
Index() uint32
61+
String() string
6162
Utxorpc() *utxorpc.TxInput
6263
}
6364

ledger/shelley/errors.go

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414

1515
package shelley
1616

17-
import "fmt"
17+
import (
18+
"fmt"
19+
"strings"
20+
21+
"github.com/blinklabs-io/gouroboros/ledger/common"
22+
)
1823

1924
type ExpiredUtxoError struct {
2025
Ttl uint64
@@ -28,3 +33,125 @@ func (e ExpiredUtxoError) Error() string {
2833
e.Slot,
2934
)
3035
}
36+
37+
type InputSetEmptyUtxoError struct{}
38+
39+
func (InputSetEmptyUtxoError) Error() string {
40+
return "input set empty"
41+
}
42+
43+
type FeeTooSmallUtxoError struct {
44+
Provided uint64
45+
Min uint64
46+
}
47+
48+
func (e FeeTooSmallUtxoError) Error() string {
49+
return fmt.Sprintf(
50+
"fee too small: provided %d, minimum %d",
51+
e.Provided,
52+
e.Min,
53+
)
54+
}
55+
56+
type BadInputsUtxoError struct {
57+
Inputs []common.TransactionInput
58+
}
59+
60+
func (e BadInputsUtxoError) Error() string {
61+
tmpInputs := make([]string, 0, len(e.Inputs))
62+
for idx, tmpInput := range e.Inputs {
63+
tmpInputs[idx] = tmpInput.String()
64+
}
65+
return fmt.Sprintf(
66+
"bad input(s): %s",
67+
strings.Join(tmpInputs, ", "),
68+
)
69+
}
70+
71+
type WrongNetworkError struct {
72+
NetId uint
73+
Addrs []common.Address
74+
}
75+
76+
func (e WrongNetworkError) Error() string {
77+
tmpAddrs := make([]string, 0, len(e.Addrs))
78+
for idx, tmpAddr := range e.Addrs {
79+
tmpAddrs[idx] = tmpAddr.String()
80+
}
81+
return fmt.Sprintf(
82+
"wrong network: %s",
83+
strings.Join(tmpAddrs, ", "),
84+
)
85+
}
86+
87+
type WrongNetworkWithdrawalError struct {
88+
NetId uint
89+
Addrs []common.Address
90+
}
91+
92+
func (e WrongNetworkWithdrawalError) Error() string {
93+
tmpAddrs := make([]string, 0, len(e.Addrs))
94+
for idx, tmpAddr := range e.Addrs {
95+
tmpAddrs[idx] = tmpAddr.String()
96+
}
97+
return fmt.Sprintf(
98+
"wrong network withdrawals: %s",
99+
strings.Join(tmpAddrs, ", "),
100+
)
101+
}
102+
103+
type ValueNotConservedUtxoError struct {
104+
Consumed uint64
105+
Produced uint64
106+
}
107+
108+
func (e ValueNotConservedUtxoError) Error() string {
109+
return fmt.Sprintf(
110+
"value not conserved: consumed %d, produced %d",
111+
e.Consumed,
112+
e.Produced,
113+
)
114+
}
115+
116+
type OutputTooSmallUtxoError struct {
117+
Outputs []common.TransactionOutput
118+
}
119+
120+
func (e OutputTooSmallUtxoError) Error() string {
121+
tmpOutputs := make([]string, 0, len(e.Outputs))
122+
for idx, tmpOutput := range e.Outputs {
123+
tmpOutputs[idx] = fmt.Sprintf("%#v", tmpOutput)
124+
}
125+
return fmt.Sprintf(
126+
"output too small: %s",
127+
strings.Join(tmpOutputs, ", "),
128+
)
129+
}
130+
131+
type OutputBootAddrAttrsTooBigError struct {
132+
Outputs []common.TransactionOutput
133+
}
134+
135+
func (e OutputBootAddrAttrsTooBigError) Error() string {
136+
tmpOutputs := make([]string, 0, len(e.Outputs))
137+
for idx, tmpOutput := range e.Outputs {
138+
tmpOutputs[idx] = fmt.Sprintf("%#v", tmpOutput)
139+
}
140+
return fmt.Sprintf(
141+
"output bootstrap address attributes too big: %s",
142+
strings.Join(tmpOutputs, ", "),
143+
)
144+
}
145+
146+
type MaxTxSizeUtxoError struct {
147+
TxSize uint
148+
MaxTxSize uint
149+
}
150+
151+
func (e MaxTxSizeUtxoError) Error() string {
152+
return fmt.Sprintf(
153+
"transaction size too large: size %d, max %d",
154+
e.TxSize,
155+
e.MaxTxSize,
156+
)
157+
}

0 commit comments

Comments
 (0)