Skip to content

Commit

Permalink
Merge branch 'alias-state-transition-constrained' of github.com:iotal…
Browse files Browse the repository at this point in the history
…edger/iota.go into alias-state-transition-constrained
  • Loading branch information
luca-moser committed Aug 26, 2022
2 parents 6153f77 + 9777306 commit 7165175
Show file tree
Hide file tree
Showing 2 changed files with 220 additions and 1 deletion.
2 changes: 1 addition & 1 deletion signature_ed25519.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (e *Ed25519Signature) Valid(msg []byte, addr *Ed25519Address) error {
// an address is the Blake2b 256 hash of the public key
addrFromPubKey := Ed25519AddressFromPubKey(e.PublicKey[:])
if !bytes.Equal(addr[:], addrFromPubKey[:]) {
return fmt.Errorf("%w: address %s, address from public key %v", ErrEd25519PubKeyAndAddrMismatch, EncodeHex(addr[:]), addrFromPubKey)
return fmt.Errorf("%w: address %s, address from public key %v", ErrEd25519PubKeyAndAddrMismatch, EncodeHex(addr[:]), EncodeHex(addrFromPubKey[:]))
}
if valid := iotagoEd25519.Verify(e.PublicKey[:], msg, e.Signature[:]); !valid {
return fmt.Errorf("%w: address %s, public key %v, signature %v", ErrEd25519SignatureInvalid, EncodeHex(addr[:]), EncodeHex(e.PublicKey[:]), EncodeHex(e.Signature[:]))
Expand Down
219 changes: 219 additions & 0 deletions transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1999,6 +1999,225 @@ func TestTxSemanticOutputsSender(t *testing.T) {
}
}

func TestTxSemanticOutputsIssuer(t *testing.T) {
type test struct {
name string
svCtx *iotago.SemanticValidationContext
inputs iotago.OutputSet
tx *iotago.Transaction
wantErr error
}
tests := []test{
func() test {
_, ident1, ident1AddrKeys := tpkg.RandEd25519Identity()
_, stateController, _ := tpkg.RandEd25519Identity()
_, governor, governorAddrKeys := tpkg.RandEd25519Identity()
inputIDs := tpkg.RandOutputIDs(2)
aliasAddr := tpkg.RandAliasAddress()
aliasId := aliasAddr.AliasID()

inputs := iotago.OutputSet{
inputIDs[0]: &iotago.AliasOutput{
Amount: 100,
AliasID: aliasId,
Conditions: iotago.UnlockConditions{
&iotago.StateControllerAddressUnlockCondition{Address: stateController},
&iotago.GovernorAddressUnlockCondition{Address: governor},
},
},
inputIDs[1]: &iotago.BasicOutput{
Amount: 100,
Conditions: iotago.UnlockConditions{
&iotago.AddressUnlockCondition{Address: ident1},
},
},
}

essence := &iotago.TransactionEssence{
Inputs: inputIDs.UTXOInputs(),
Outputs: iotago.Outputs{
&iotago.AliasOutput{
Amount: 100,
AliasID: aliasId,
Conditions: iotago.UnlockConditions{
&iotago.StateControllerAddressUnlockCondition{Address: stateController},
&iotago.GovernorAddressUnlockCondition{Address: governor},
},
},
&iotago.NFTOutput{
Amount: 100,
Conditions: iotago.UnlockConditions{
&iotago.AddressUnlockCondition{Address: ident1},
},
ImmutableFeatures: iotago.Features{
&iotago.IssuerFeature{Address: aliasAddr},
},
},
},
}
sigs, err := essence.Sign(inputIDs.OrderedSet(inputs).MustCommitment(), governorAddrKeys, ident1AddrKeys)
require.NoError(t, err)

return test{
name: "fail - issuer not unlocked due to governance transition",
svCtx: &iotago.SemanticValidationContext{ExtParas: &iotago.ExternalUnlockParameters{}},
inputs: inputs,
tx: &iotago.Transaction{
Essence: essence,
Unlocks: iotago.Unlocks{
&iotago.SignatureUnlock{Signature: sigs[0]},
&iotago.SignatureUnlock{Signature: sigs[1]},
},
},
wantErr: iotago.ErrIssuerFeatureNotUnlocked,
}
}(),
func() test {
_, ident1, ident1AddrKeys := tpkg.RandEd25519Identity()
_, stateController, stateControllerAddrKeys := tpkg.RandEd25519Identity()
_, governor, _ := tpkg.RandEd25519Identity()
inputIDs := tpkg.RandOutputIDs(2)
aliasAddr := tpkg.RandAliasAddress()
aliasId := aliasAddr.AliasID()
currentStateIndex := uint32(1)

inputs := iotago.OutputSet{
inputIDs[0]: &iotago.AliasOutput{
Amount: 100,
AliasID: aliasId,
StateIndex: currentStateIndex,
Conditions: iotago.UnlockConditions{
&iotago.StateControllerAddressUnlockCondition{Address: stateController},
&iotago.GovernorAddressUnlockCondition{Address: governor},
},
},
inputIDs[1]: &iotago.BasicOutput{
Amount: 100,
Conditions: iotago.UnlockConditions{
&iotago.AddressUnlockCondition{Address: ident1},
},
},
}

essence := &iotago.TransactionEssence{
Inputs: inputIDs.UTXOInputs(),
Outputs: iotago.Outputs{
&iotago.AliasOutput{
Amount: 100,
AliasID: aliasId,
StateIndex: currentStateIndex + 1,
Conditions: iotago.UnlockConditions{
&iotago.StateControllerAddressUnlockCondition{Address: stateController},
&iotago.GovernorAddressUnlockCondition{Address: governor},
},
},
&iotago.NFTOutput{
Amount: 100,
Conditions: iotago.UnlockConditions{
&iotago.AddressUnlockCondition{Address: ident1},
},
ImmutableFeatures: iotago.Features{
&iotago.IssuerFeature{Address: aliasAddr},
},
},
},
}
sigs, err := essence.Sign(inputIDs.OrderedSet(inputs).MustCommitment(), stateControllerAddrKeys, ident1AddrKeys)
require.NoError(t, err)

return test{
name: "ok - issuer unlocked with state transition",
svCtx: &iotago.SemanticValidationContext{ExtParas: &iotago.ExternalUnlockParameters{}},
inputs: inputs,
tx: &iotago.Transaction{
Essence: essence,
Unlocks: iotago.Unlocks{
&iotago.SignatureUnlock{Signature: sigs[0]},
&iotago.SignatureUnlock{Signature: sigs[1]},
},
},
wantErr: nil,
}
}(),
func() test {
_, ident1, ident1AddrKeys := tpkg.RandEd25519Identity()
_, stateController, _ := tpkg.RandEd25519Identity()
_, governor, governorAddrKeys := tpkg.RandEd25519Identity()
inputIDs := tpkg.RandOutputIDs(2)
aliasAddr := tpkg.RandAliasAddress()
aliasId := aliasAddr.AliasID()

inputs := iotago.OutputSet{
inputIDs[0]: &iotago.AliasOutput{
Amount: 100,
AliasID: aliasId,
Conditions: iotago.UnlockConditions{
&iotago.StateControllerAddressUnlockCondition{Address: stateController},
&iotago.GovernorAddressUnlockCondition{Address: governor},
},
},
inputIDs[1]: &iotago.BasicOutput{
Amount: 100,
Conditions: iotago.UnlockConditions{
&iotago.AddressUnlockCondition{Address: ident1},
},
},
}

essence := &iotago.TransactionEssence{
Inputs: inputIDs.UTXOInputs(),
Outputs: iotago.Outputs{
&iotago.AliasOutput{
Amount: 100,
AliasID: aliasId,
Conditions: iotago.UnlockConditions{
&iotago.StateControllerAddressUnlockCondition{Address: stateController},
&iotago.GovernorAddressUnlockCondition{Address: governor},
},
},
&iotago.NFTOutput{
Amount: 100,
Conditions: iotago.UnlockConditions{
&iotago.AddressUnlockCondition{Address: ident1},
},
ImmutableFeatures: iotago.Features{
&iotago.IssuerFeature{Address: governor},
},
},
},
}
sigs, err := essence.Sign(inputIDs.OrderedSet(inputs).MustCommitment(), governorAddrKeys, ident1AddrKeys)
require.NoError(t, err)

return test{
name: "ok - issuer is the governor",
svCtx: &iotago.SemanticValidationContext{ExtParas: &iotago.ExternalUnlockParameters{}},
inputs: inputs,
tx: &iotago.Transaction{
Essence: essence,
Unlocks: iotago.Unlocks{
&iotago.SignatureUnlock{Signature: sigs[0]},
&iotago.SignatureUnlock{Signature: sigs[1]},
},
},
wantErr: nil,
}
}(),
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

err := tt.tx.SemanticallyValidate(tt.svCtx, tt.inputs)
if tt.wantErr != nil {
require.ErrorIs(t, err, tt.wantErr)
return
}

require.NoError(t, err)
})
}
}

func TestTxSemanticTimelocks(t *testing.T) {
type test struct {
name string
Expand Down

0 comments on commit 7165175

Please sign in to comment.