Skip to content

Commit

Permalink
Rename Ref to Reference/Referential unlocks
Browse files Browse the repository at this point in the history
  • Loading branch information
muXxer committed Feb 26, 2024
1 parent 357bb2f commit 46f9503
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 144 deletions.
6 changes: 3 additions & 3 deletions gen/unlock_ref.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"github.com/iotaledger/hive.go/serializer/v2"
)

// {{.Name}} is an Unlock which references a previous unlock.
// {{.Name}} is an Unlock which references a previous input/unlock.
type {{.Name}} struct {
// The other unlock this {{.Name}} references to.
// The other input/unlock this {{.Name}} references to.
Reference uint16 `serix:""`
}

Expand All @@ -26,7 +26,7 @@ func ({{.Receiver}} *{{.Name}}) Chainable() bool {
{{if index .Features "chainable"}} return true {{else}} return false {{end}}
}

func ({{.Receiver}} *{{.Name}}) Ref() uint16 {
func ({{.Receiver}} *{{.Name}}) ReferencedInputIndex() uint16 {
return {{.Receiver}}.Reference
}

Expand Down
9 changes: 5 additions & 4 deletions input.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,17 @@ type Input interface {
Type() InputType
}

// InputsSyntacticalUnique returns an ElementValidationFunc which checks that every input has a unique UTXO ref.
// InputsSyntacticalUnique returns an ElementValidationFunc which checks that every input has a unique reference UTXO index.
func InputsSyntacticalUnique() ElementValidationFunc[Input] {
utxoSet := map[string]int{}

return func(index int, input Input) error {
switch castInput := input.(type) {
case *UTXOInput:
utxoRef := castInput.OutputID()
k := string(utxoRef[:])
referencedOutputID := castInput.OutputID()
k := string(referencedOutputID[:])
if j, has := utxoSet[k]; has {
return ierrors.Wrapf(ErrInputUTXORefsNotUnique, "input %d and %d share the same UTXO ref", j, index)
return ierrors.Wrapf(ErrInputUTXORefsNotUnique, "input %d and %d share the same referenced UTXO index", j, index)
}
utxoSet[k] = index
default:
Expand All @@ -106,6 +106,7 @@ func InputsSyntacticalIndicesWithinBounds() ElementValidationFunc[Input] {
return func(index int, input Input) error {
switch castInput := input.(type) {
case *UTXOInput:
// TODO: do we really want to check the max value on the input side?
if castInput.Index() < RefUTXOIndexMin || castInput.Index() > RefUTXOIndexMax {
return ierrors.Wrapf(ErrRefUTXOIndexInvalid, "input %d", index)
}
Expand Down
2 changes: 1 addition & 1 deletion input_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func TestInputsSyntacticalIndicesWithinBounds(t *testing.T) {
wantErr: nil,
},
{
name: "fail - invalid UTXO ref index",
name: "fail - invalid reference UTXO index",
inputs: iotago.Inputs[iotago.Input]{
&iotago.UTXOInput{
TransactionID: [36]byte{},
Expand Down
2 changes: 1 addition & 1 deletion signed_transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (t *SignedTransaction) syntacticallyValidate() error {
}

if err := ValidateUnlocks(t.Unlocks,
UnlocksSigUniqueAndRefValidator(t.API),
SignatureUniqueAndReferenceUnlocksValidator(t.API),
); err != nil {
return ierrors.Errorf("invalid unlocks: %w", err)
}
Expand Down
62 changes: 31 additions & 31 deletions unlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ var (
)

var (
// ErrSigUnlockNotUnique gets returned if sig unlocks making part of a transaction aren't unique.
ErrSigUnlockNotUnique = ierrors.New("signature unlock must be unique")
// ErrSignatureUnlockNotUnique gets returned if sig unlocks making part of a transaction aren't unique.
ErrSignatureUnlockNotUnique = ierrors.New("signature unlock must be unique")
// ErrUnlockSignatureInvalid gets returned when a signature in an unlock is invalid.
ErrUnlockSignatureInvalid = ierrors.New("signature in unlock is invalid")
// ErrMultiUnlockNotUnique gets returned if multi unlocks making part of a transaction aren't unique.
Expand All @@ -62,8 +62,8 @@ var (
ErrMultiAddressLengthUnlockLengthMismatch = ierrors.New("multi address length and multi unlock length do not match")
// ErrReferentialUnlockInvalid gets returned when a ReferentialUnlock is invalid.
ErrReferentialUnlockInvalid = ierrors.New("invalid referential unlock")
// ErrSigUnlockHasNilSig gets returned if a signature unlock contains a nil signature.
ErrSigUnlockHasNilSig = ierrors.New("signature is nil")
// ErrSignatureUnlockHasNilSignature gets returned if a signature unlock contains a nil signature.
ErrSignatureUnlockHasNilSignature = ierrors.New("signature is nil")
// ErrUnknownUnlockType gets returned for unknown unlock.
ErrUnknownUnlockType = ierrors.New("unknown unlock type")
// ErrNestedMultiUnlock gets returned when a MultiUnlock is nested inside a MultiUnlock.
Expand Down Expand Up @@ -124,8 +124,8 @@ type Unlock interface {
type ReferentialUnlock interface {
Unlock

// Ref returns the index of the Unlock this ReferentialUnlock references.
Ref() uint16
// ReferencedInputIndex returns the index of the Input/Unlock this ReferentialUnlock references.
ReferencedInputIndex() uint16
// Chainable indicates whether this ReferentialUnlock can reference another ReferentialUnlock.
Chainable() bool
// SourceAllowed tells whether the given Address is allowed to be the source of this ReferentialUnlock.
Expand All @@ -145,7 +145,7 @@ func publicKeyBytesFromSignatureBlock(signature Signature) ([]byte, error) {
// UnlockValidatorFunc which given the index and the Unlock itself, runs validations and returns an error if any should fail.
type UnlockValidatorFunc func(index int, unlock Unlock) error

// UnlocksSigUniqueAndRefValidator returns a validator which checks that:
// SignatureUniqueAndReferenceUnlocksValidator returns a validator which checks that:
// 1. SignatureUnlock(s) are unique (compared by public key)
// - SignatureUnlock(s) inside different MultiUnlock(s) don't need to be unique,
// as long as there is no equal SignatureUnlock(s) outside of a MultiUnlock(s).
Expand All @@ -155,19 +155,19 @@ type UnlockValidatorFunc func(index int, unlock Unlock) error
// 5. MultiUnlock(s) are not nested
// 6. MultiUnlock(s) are unique
// 7. ReferenceUnlock(s) to MultiUnlock(s) are not nested in MultiUnlock(s)
func UnlocksSigUniqueAndRefValidator(api API) UnlockValidatorFunc {
seenSigUnlocks := map[uint16]struct{}{}
func SignatureUniqueAndReferenceUnlocksValidator(api API) UnlockValidatorFunc {
seenSignatureUnlocks := map[uint16]struct{}{}
seenSigBlockPubkeyBytes := map[string]int{}
seenSigBlockPubkeyBytesInMultiUnlocks := map[string]int{}
seenRefUnlocks := map[uint16]ReferentialUnlock{}
seenReferentialUnlocks := map[uint16]ReferentialUnlock{}
seenMultiUnlocks := map[uint16]struct{}{}
seenMultiUnlockBytes := map[string]int{}

return func(index int, u Unlock) error {
switch unlock := u.(type) {
case *SignatureUnlock:
if unlock.Signature == nil {
return ierrors.Wrapf(ErrSigUnlockHasNilSig, "at index %d is nil", index)
return ierrors.Wrapf(ErrSignatureUnlockHasNilSignature, "at index %d is nil", index)
}

sigBlockPubKeyBytes, err := publicKeyBytesFromSignatureBlock(unlock.Signature)
Expand All @@ -177,34 +177,34 @@ func UnlocksSigUniqueAndRefValidator(api API) UnlockValidatorFunc {

// we check for duplicated pubkeys in SignatureUnlock(s)
if existingIndex, exists := seenSigBlockPubkeyBytes[string(sigBlockPubKeyBytes)]; exists {
return ierrors.Wrapf(ErrSigUnlockNotUnique, "signature unlock block at index %d is the same as %d", index, existingIndex)
return ierrors.Wrapf(ErrSignatureUnlockNotUnique, "signature unlock block at index %d is the same as %d", index, existingIndex)
}

// we also need to check for duplicated pubkeys in MultiUnlock(s)
if existingIndex, exists := seenSigBlockPubkeyBytesInMultiUnlocks[string(sigBlockPubKeyBytes)]; exists {
return ierrors.Wrapf(ErrSigUnlockNotUnique, "signature unlock block at index %d is the same as in multi unlock at index %d", index, existingIndex)
return ierrors.Wrapf(ErrSignatureUnlockNotUnique, "signature unlock block at index %d is the same as in multi unlock at index %d", index, existingIndex)
}

seenSigUnlocks[uint16(index)] = struct{}{}
seenSignatureUnlocks[uint16(index)] = struct{}{}
seenSigBlockPubkeyBytes[string(sigBlockPubKeyBytes)] = index

case ReferentialUnlock:
if prevRef := seenRefUnlocks[unlock.Ref()]; prevRef != nil {
if prevReferentialUnlock := seenReferentialUnlocks[unlock.ReferencedInputIndex()]; prevReferentialUnlock != nil {
if !unlock.Chainable() {
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d references existing referential unlock %d but it does not support chaining", index, unlock.Ref())
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d references existing referential unlock %d but it does not support chaining", index, unlock.ReferencedInputIndex())
}
seenRefUnlocks[uint16(index)] = unlock
seenReferentialUnlocks[uint16(index)] = unlock

break
}

// must reference a sig or multi unlock here
_, hasSigUnlock := seenSigUnlocks[unlock.Ref()]
_, hasMultiUnlock := seenMultiUnlocks[unlock.Ref()]
if !hasSigUnlock && !hasMultiUnlock {
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d references non existent unlock %d", index, unlock.Ref())
_, hasSignatureUnlock := seenSignatureUnlocks[unlock.ReferencedInputIndex()]
_, hasMultiUnlock := seenMultiUnlocks[unlock.ReferencedInputIndex()]
if !hasSignatureUnlock && !hasMultiUnlock {
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d references non existent unlock %d", index, unlock.ReferencedInputIndex())
}
seenRefUnlocks[uint16(index)] = unlock
seenReferentialUnlocks[uint16(index)] = unlock

case *MultiUnlock:
multiUnlockBytes, err := api.Encode(unlock)
Expand All @@ -220,7 +220,7 @@ func UnlocksSigUniqueAndRefValidator(api API) UnlockValidatorFunc {
switch subUnlock := subU.(type) {
case *SignatureUnlock:
if subUnlock.Signature == nil {
return ierrors.Wrapf(ErrSigUnlockHasNilSig, "at index %d.%d is nil", index, subIndex)
return ierrors.Wrapf(ErrSignatureUnlockHasNilSignature, "at index %d.%d is nil", index, subIndex)
}

sigBlockPubKeyBytes, err := publicKeyBytesFromSignatureBlock(subUnlock.Signature)
Expand All @@ -230,29 +230,29 @@ func UnlocksSigUniqueAndRefValidator(api API) UnlockValidatorFunc {

// we check for duplicated pubkeys in SignatureUnlock(s)
if existingIndex, exists := seenSigBlockPubkeyBytes[string(sigBlockPubKeyBytes)]; exists {
return ierrors.Wrapf(ErrSigUnlockNotUnique, "signature unlock block at index %d.%d is the same as %d", index, subIndex, existingIndex)
return ierrors.Wrapf(ErrSignatureUnlockNotUnique, "signature unlock block at index %d.%d is the same as %d", index, subIndex, existingIndex)
}

// we don't set the index here in "seenSigUnlocks" because there is no concept of reference unlocks inside of multi unlocks
// we don't set the index here in "seenSignatureUnlocks" because there is no concept of reference unlocks inside of multi unlocks

// add the pubkey to "seenSigBlockPubkeyBytesInMultiUnlocks", so we can check that pubkeys from a multi unlock are not reused in a normal SignatureUnlock
seenSigBlockPubkeyBytesInMultiUnlocks[string(sigBlockPubKeyBytes)] = index

case ReferentialUnlock:
if prevRef := seenRefUnlocks[subUnlock.Ref()]; prevRef != nil {
if prevRef := seenReferentialUnlocks[subUnlock.ReferencedInputIndex()]; prevRef != nil {
if !subUnlock.Chainable() {
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d.%d references existing referential unlock %d but it does not support chaining", index, subIndex, subUnlock.Ref())
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d.%d references existing referential unlock %d but it does not support chaining", index, subIndex, subUnlock.ReferencedInputIndex())
}
// we don't set the index here in "seenRefUnlocks" because it's not allowed to reference an unlock within a multi unlock
// we don't set the index here in "seenReferentialUnlocks" because it's not allowed to reference an unlock within a multi unlock

continue
}
// must reference a sig unlock here
// we don't check for "seenMultiUnlocks" here because we don't want to nest "reference unlocks to multi unlocks" in multi unlocks
if _, has := seenSigUnlocks[subUnlock.Ref()]; !has {
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d.%d references non existent unlock %d", index, subIndex, subUnlock.Ref())
if _, has := seenSignatureUnlocks[subUnlock.ReferencedInputIndex()]; !has {
return ierrors.Wrapf(ErrReferentialUnlockInvalid, "%d.%d references non existent unlock %d", index, subIndex, subUnlock.ReferencedInputIndex())
}
// we don't set the index here in "seenRefUnlocks" because it's not allowed to reference an unlock within a multi unlock
// we don't set the index here in "seenReferentialUnlocks" because it's not allowed to reference an unlock within a multi unlock

case *MultiUnlock:
return ierrors.Wrapf(ErrNestedMultiUnlock, "unlock at index %d.%d is invalid", index, subIndex)
Expand Down
6 changes: 3 additions & 3 deletions unlock_account.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"github.com/iotaledger/hive.go/serializer/v2"
)

// AccountUnlock is an Unlock which references a previous unlock.
// AccountUnlock is an Unlock which references a previous input/unlock.
type AccountUnlock struct {
// The other unlock this AccountUnlock references to.
// The other input/unlock this AccountUnlock references to.
Reference uint16 `serix:""`
}

Expand All @@ -26,7 +26,7 @@ func (r *AccountUnlock) Chainable() bool {
return true
}

func (r *AccountUnlock) Ref() uint16 {
func (r *AccountUnlock) ReferencedInputIndex() uint16 {
return r.Reference
}

Expand Down
6 changes: 3 additions & 3 deletions unlock_anchor.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"github.com/iotaledger/hive.go/serializer/v2"
)

// AnchorUnlock is an Unlock which references a previous unlock.
// AnchorUnlock is an Unlock which references a previous input/unlock.
type AnchorUnlock struct {
// The other unlock this AnchorUnlock references to.
// The other input/unlock this AnchorUnlock references to.
Reference uint16 `serix:""`
}

Expand All @@ -26,7 +26,7 @@ func (r *AnchorUnlock) Chainable() bool {
return true
}

func (r *AnchorUnlock) Ref() uint16 {
func (r *AnchorUnlock) ReferencedInputIndex() uint16 {
return r.Reference
}

Expand Down
6 changes: 3 additions & 3 deletions unlock_nft.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"github.com/iotaledger/hive.go/serializer/v2"
)

// NFTUnlock is an Unlock which references a previous unlock.
// NFTUnlock is an Unlock which references a previous input/unlock.
type NFTUnlock struct {
// The other unlock this NFTUnlock references to.
// The other input/unlock this NFTUnlock references to.
Reference uint16 `serix:""`
}

Expand All @@ -26,7 +26,7 @@ func (r *NFTUnlock) Chainable() bool {
return true
}

func (r *NFTUnlock) Ref() uint16 {
func (r *NFTUnlock) ReferencedInputIndex() uint16 {
return r.Reference
}

Expand Down
6 changes: 3 additions & 3 deletions unlock_reference.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"github.com/iotaledger/hive.go/serializer/v2"
)

// ReferenceUnlock is an Unlock which references a previous unlock.
// ReferenceUnlock is an Unlock which references a previous input/unlock.
type ReferenceUnlock struct {
// The other unlock this ReferenceUnlock references to.
// The other input/unlock this ReferenceUnlock references to.
Reference uint16 `serix:""`
}

Expand All @@ -26,7 +26,7 @@ func (r *ReferenceUnlock) Chainable() bool {
return false
}

func (r *ReferenceUnlock) Ref() uint16 {
func (r *ReferenceUnlock) ReferencedInputIndex() uint16 {
return r.Reference
}

Expand Down
18 changes: 9 additions & 9 deletions unlock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func TestUnlock_DeSerialize(t *testing.T) {
}
}

func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
func TestSignatureUniqueAndReferenceUnlocksValidator(t *testing.T) {
tests := []struct {
name string
unlocks iotago.Unlocks
Expand Down Expand Up @@ -119,7 +119,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
Signature: [64]byte{},
}},
},
wantErr: iotago.ErrSigUnlockNotUnique,
wantErr: iotago.ErrSignatureUnlockNotUnique,
},
{
name: "fail - signature reuse outside and inside the multi unlocks - 1",
Expand All @@ -137,7 +137,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
},
},
},
wantErr: iotago.ErrSigUnlockNotUnique,
wantErr: iotago.ErrSignatureUnlockNotUnique,
},
{
name: "fail - signature reuse outside and inside the multi unlocks - 2",
Expand All @@ -159,7 +159,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
Signature: [64]byte{},
}},
},
wantErr: iotago.ErrSigUnlockNotUnique,
wantErr: iotago.ErrSignatureUnlockNotUnique,
},
{
name: "ok - duplicate ed25519 sig block in different multi unlocks",
Expand Down Expand Up @@ -210,7 +210,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
wantErr: iotago.ErrMultiUnlockNotUnique,
},
{
name: "fail - reference unlock invalid ref",
name: "fail - reference unlock invalid reference",
unlocks: iotago.Unlocks{
tpkg.RandEd25519SignatureUnlock(),
tpkg.RandEd25519SignatureUnlock(),
Expand All @@ -219,7 +219,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
wantErr: iotago.ErrReferentialUnlockInvalid,
},
{
name: "fail - reference unlock invalid ref in multi unlock",
name: "fail - reference unlock invalid reference in multi unlock",
unlocks: iotago.Unlocks{
tpkg.RandEd25519SignatureUnlock(),
tpkg.RandEd25519SignatureUnlock(),
Expand All @@ -232,7 +232,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
wantErr: iotago.ErrReferentialUnlockInvalid,
},
{
name: "fail - reference unlock refs non sig unlock",
name: "fail - reference unlock references non sig unlock",
unlocks: iotago.Unlocks{
tpkg.RandEd25519SignatureUnlock(),
&iotago.ReferenceUnlock{Reference: 0},
Expand All @@ -241,7 +241,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
wantErr: iotago.ErrReferentialUnlockInvalid,
},
{
name: "fail - reference unlock refs non sig unlock in multi unlock",
name: "fail - reference unlock references non sig unlock in multi unlock",
unlocks: iotago.Unlocks{
tpkg.RandEd25519SignatureUnlock(),
&iotago.ReferenceUnlock{Reference: 0},
Expand Down Expand Up @@ -318,7 +318,7 @@ func TestUnlocksSigUniqueAndRefValidator(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
valFunc := iotago.UnlocksSigUniqueAndRefValidator(tpkg.ZeroCostTestAPI)
valFunc := iotago.SignatureUniqueAndReferenceUnlocksValidator(tpkg.ZeroCostTestAPI)
var runErr error
for index, unlock := range tt.unlocks {
if err := valFunc(index, unlock); err != nil {
Expand Down
Loading

0 comments on commit 46f9503

Please sign in to comment.