Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GetNativeCompositeValueComputedFields #2977

Merged
merged 2 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 66 additions & 2 deletions runtime/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"strconv"
"testing"

"github.com/onflow/atree"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

Expand Down Expand Up @@ -51,9 +52,9 @@ func TestRuntimeAccountKeyConstructor(t *testing.T) {
let key = AccountKey(
PublicKey(
publicKey: "0102".decodeHex(),
signAlgo: "SignatureAlgorithmECDSA_P256"
signatureAlgorithm: SignatureAlgorithm.ECDSA_P256
),
hashAlgorithm: "HashAlgorithmSHA3_256",
hashAlgorithm: HashAlgorithm.SHA3_256,
weight: 1.7
)

Expand Down Expand Up @@ -2228,3 +2229,66 @@ type fakeError struct{}
func (fakeError) Error() string {
return "fake error for testing"
}

// TestRuntimePublicKeyPublicKeyField tests PublicKey's `publicKey` field.
// It is a computed field, which always returns a copy of the stored raw public key ([UInt8]).
//
// This test ensures that the field can be accessed even after the PublicKey value has been transferred (copied),
// and the original PublicKey value has been removed.
func TestRuntimePublicKeyPublicKeyField(t *testing.T) {

t.Parallel()

inter := NewTestInterpreter(t)

locationRange := interpreter.EmptyLocationRange

publicKey := interpreter.NewCompositeValue(
inter,
locationRange,
nil,
sema.PublicKeyType.Identifier,
common.CompositeKindStructure,
[]interpreter.CompositeField{
{
Name: sema.PublicKeyTypePublicKeyFieldName,
Value: interpreter.NewArrayValue(
inter,
locationRange,
interpreter.ByteArrayStaticType,
common.ZeroAddress,
interpreter.NewUnmeteredUInt8Value(1),
),
},
},
common.ZeroAddress,
)

publicKeyArray1 := publicKey.GetMember(
inter,
locationRange,
sema.PublicKeyTypePublicKeyFieldName,
)

publicKey2 := publicKey.Transfer(
inter,
locationRange,
atree.Address{},
false,
nil,
nil,
).(*interpreter.CompositeValue)

publicKey.DeepRemove(inter)

publicKeyArray2 := publicKey2.GetMember(
inter,
locationRange,
sema.PublicKeyTypePublicKeyFieldName,
)

require.True(t,
publicKeyArray2.(interpreter.EquatableValue).
Equal(inter, locationRange, publicKeyArray1),
)
}
12 changes: 8 additions & 4 deletions runtime/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -4601,11 +4601,15 @@ func (interpreter *Interpreter) GetContractComposite(contractLocation common.Add
return contractValue, nil
}

func GetNativeCompositeValueComputedFields(v *CompositeValue) map[string]ComputedField {
switch v.QualifiedIdentifier {
func GetNativeCompositeValueComputedFields(qualifiedIdentifier string) map[string]ComputedField {
switch qualifiedIdentifier {
case sema.PublicKeyType.Identifier:
return map[string]ComputedField{
sema.PublicKeyTypePublicKeyFieldName: func(interpreter *Interpreter, locationRange LocationRange) Value {
sema.PublicKeyTypePublicKeyFieldName: func(
interpreter *Interpreter,
locationRange LocationRange,
v *CompositeValue,
) Value {
publicKeyValue := v.GetField(interpreter, locationRange, sema.PublicKeyTypePublicKeyFieldName)
return publicKeyValue.Transfer(
interpreter,
Expand All @@ -4626,7 +4630,7 @@ func (interpreter *Interpreter) GetCompositeValueComputedFields(v *CompositeValu

var computedFields map[string]ComputedField
if v.Location == nil {
computedFields = GetNativeCompositeValueComputedFields(v)
computedFields = GetNativeCompositeValueComputedFields(v.QualifiedIdentifier)
if computedFields != nil {
return computedFields
}
Expand Down
6 changes: 3 additions & 3 deletions runtime/interpreter/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -16312,7 +16312,7 @@
isDestroyed bool
}

type ComputedField func(*Interpreter, LocationRange) Value
type ComputedField func(*Interpreter, LocationRange, *CompositeValue) Value

type CompositeField struct {
Value Value
Expand Down Expand Up @@ -16744,7 +16744,7 @@
return nil
}

return computedField(interpreter, locationRange)
return computedField(interpreter, locationRange, v)
}

func (v *CompositeValue) GetInjectedField(interpreter *Interpreter, name string) Value {
Expand Down Expand Up @@ -17198,7 +17198,7 @@
return false
}

value = fieldGetter(interpreter, locationRange)
value = fieldGetter(interpreter, locationRange, v)

Check warning on line 17201 in runtime/interpreter/value.go

View check run for this annotation

Codecov / codecov/patch

runtime/interpreter/value.go#L17201

Added line #L17201 was not covered by tests
}

member, ok := compositeType.Members.Get(fieldName)
Expand Down
Loading