From 5b030e29085e9d53af4460f31f07ef4dde2d172f Mon Sep 17 00:00:00 2001 From: darkdrag00n Date: Wed, 6 Dec 2023 14:18:57 +0530 Subject: [PATCH 1/6] Update interface of revertibleRandom --- encoding/ccf/ccf_test.go | 1 + encoding/ccf/simpletype.go | 2 + encoding/ccf/simpletype_string.go | 9 +- encoding/ccf/traverse_value.go | 1 + runtime/convertTypes.go | 2 + runtime/convertValues_test.go | 5 + runtime/interpreter/big.go | 13 ++ runtime/interpreter/interpreter.go | 2 +- runtime/interpreter/interpreter_expression.go | 2 +- runtime/interpreter/primitivestatictype.go | 7 +- .../interpreter/primitivestatictype_string.go | 174 +++++++++--------- runtime/interpreter/statictype_test.go | 5 + runtime/interpreter/value_test.go | 4 +- runtime/literal.go | 2 +- runtime/runtime_test.go | 93 +++++++++- runtime/sema/type.go | 37 +++- runtime/sema/type_names.go | 13 +- runtime/sema/type_tags.go | 34 ++-- runtime/sema/type_test.go | 19 ++ runtime/stdlib/random.go | 166 +++++++++++++++-- .../tests/checker/builtinfunctions_test.go | 86 ++++++++- runtime/tests/checker/integer_test.go | 9 +- runtime/tests/checker/operations_test.go | 1 + runtime/tests/interpreter/arithmetic_test.go | 2 +- runtime/tests/interpreter/bitwise_test.go | 2 +- .../interpreter/builtinfunctions_test.go | 4 +- runtime/tests/interpreter/integers_test.go | 6 +- runtime/tests/interpreter/interpreter_test.go | 2 +- types.go | 1 + values_test.go | 2 +- 30 files changed, 549 insertions(+), 157 deletions(-) diff --git a/encoding/ccf/ccf_test.go b/encoding/ccf/ccf_test.go index 740cc9e743..26cb346a64 100644 --- a/encoding/ccf/ccf_test.go +++ b/encoding/ccf/ccf_test.go @@ -7811,6 +7811,7 @@ func TestEncodeSimpleTypes(t *testing.T) { ccf.SimpleTypeSignedNumber: cadence.SignedNumberType, ccf.SimpleTypeInteger: cadence.IntegerType, ccf.SimpleTypeSignedInteger: cadence.SignedIntegerType, + ccf.SimpleTypeFixedSizeUnsignedInteger: cadence.FixedSizeUnsignedIntegerType, ccf.SimpleTypeFixedPoint: cadence.FixedPointType, ccf.SimpleTypeSignedFixedPoint: cadence.SignedFixedPointType, ccf.SimpleTypeInt: cadence.IntType, diff --git a/encoding/ccf/simpletype.go b/encoding/ccf/simpletype.go index 1f8c722333..6cccd03e03 100644 --- a/encoding/ccf/simpletype.go +++ b/encoding/ccf/simpletype.go @@ -138,6 +138,7 @@ const ( // Cadence simple type IDs SimpleTypeCapabilitiesMapping SimpleTypeAccountMapping SimpleTypeHashableStruct + SimpleTypeFixedSizeUnsignedInteger // !!! *WARNING* !!! // ADD NEW TYPES *BEFORE* THIS WARNING. @@ -168,6 +169,7 @@ func initSimpleTypeIDBiMap() (m *bimap.BiMap[cadence.PrimitiveType, SimpleType]) m.Insert(cadence.SignedNumberType, SimpleTypeSignedNumber) m.Insert(cadence.IntegerType, SimpleTypeInteger) m.Insert(cadence.SignedIntegerType, SimpleTypeSignedInteger) + m.Insert(cadence.FixedSizeUnsignedIntegerType, SimpleTypeFixedSizeUnsignedInteger) m.Insert(cadence.FixedPointType, SimpleTypeFixedPoint) m.Insert(cadence.SignedFixedPointType, SimpleTypeSignedFixedPoint) diff --git a/encoding/ccf/simpletype_string.go b/encoding/ccf/simpletype_string.go index fd131f8c60..a3155d138a 100644 --- a/encoding/ccf/simpletype_string.go +++ b/encoding/ccf/simpletype_string.go @@ -99,18 +99,19 @@ func _() { _ = x[SimpleTypeCapabilitiesMapping-95] _ = x[SimpleTypeAccountMapping-96] _ = x[SimpleTypeHashableStruct-97] - _ = x[SimpleType_Count-98] + _ = x[SimpleTypeFixedSizeUnsignedInteger-98] + _ = x[SimpleType_Count-99] } const ( _SimpleType_name_0 = "SimpleTypeBoolSimpleTypeStringSimpleTypeCharacterSimpleTypeAddressSimpleTypeIntSimpleTypeInt8SimpleTypeInt16SimpleTypeInt32SimpleTypeInt64SimpleTypeInt128SimpleTypeInt256SimpleTypeUIntSimpleTypeUInt8SimpleTypeUInt16SimpleTypeUInt32SimpleTypeUInt64SimpleTypeUInt128SimpleTypeUInt256SimpleTypeWord8SimpleTypeWord16SimpleTypeWord32SimpleTypeWord64SimpleTypeFix64SimpleTypeUFix64SimpleTypePathSimpleTypeCapabilityPathSimpleTypeStoragePathSimpleTypePublicPathSimpleTypePrivatePath" _SimpleType_name_1 = "SimpleTypeDeployedContract" - _SimpleType_name_2 = "SimpleTypeBlockSimpleTypeAnySimpleTypeAnyStructSimpleTypeAnyResourceSimpleTypeMetaTypeSimpleTypeNeverSimpleTypeNumberSimpleTypeSignedNumberSimpleTypeIntegerSimpleTypeSignedIntegerSimpleTypeFixedPointSimpleTypeSignedFixedPointSimpleTypeBytesSimpleTypeVoidSimpleTypeFunctionSimpleTypeWord128SimpleTypeWord256SimpleTypeAnyStructAttachmentTypeSimpleTypeAnyResourceAttachmentTypeSimpleTypeStorageCapabilityControllerSimpleTypeAccountCapabilityControllerSimpleTypeAccountSimpleTypeAccount_ContractsSimpleTypeAccount_KeysSimpleTypeAccount_InboxSimpleTypeAccount_StorageCapabilitiesSimpleTypeAccount_AccountCapabilitiesSimpleTypeAccount_CapabilitiesSimpleTypeAccount_StorageSimpleTypeMutateSimpleTypeInsertSimpleTypeRemoveSimpleTypeIdentitySimpleTypeStorageSimpleTypeSaveValueSimpleTypeLoadValueSimpleTypeCopyValueSimpleTypeBorrowValueSimpleTypeContractsSimpleTypeAddContractSimpleTypeUpdateContractSimpleTypeRemoveContractSimpleTypeKeysSimpleTypeAddKeySimpleTypeRevokeKeySimpleTypeInboxSimpleTypePublishInboxCapabilitySimpleTypeUnpublishInboxCapabilitySimpleTypeClaimInboxCapabilitySimpleTypeCapabilitiesSimpleTypeStorageCapabilitiesSimpleTypeAccountCapabilitiesSimpleTypePublishCapabilitySimpleTypeUnpublishCapabilitySimpleTypeGetStorageCapabilityControllerSimpleTypeIssueStorageCapabilityControllerSimpleTypeGetAccountCapabilityControllerSimpleTypeIssueAccountCapabilityControllerSimpleTypeCapabilitiesMappingSimpleTypeAccountMappingSimpleTypeHashableStructSimpleType_Count" + _SimpleType_name_2 = "SimpleTypeBlockSimpleTypeAnySimpleTypeAnyStructSimpleTypeAnyResourceSimpleTypeMetaTypeSimpleTypeNeverSimpleTypeNumberSimpleTypeSignedNumberSimpleTypeIntegerSimpleTypeSignedIntegerSimpleTypeFixedPointSimpleTypeSignedFixedPointSimpleTypeBytesSimpleTypeVoidSimpleTypeFunctionSimpleTypeWord128SimpleTypeWord256SimpleTypeAnyStructAttachmentTypeSimpleTypeAnyResourceAttachmentTypeSimpleTypeStorageCapabilityControllerSimpleTypeAccountCapabilityControllerSimpleTypeAccountSimpleTypeAccount_ContractsSimpleTypeAccount_KeysSimpleTypeAccount_InboxSimpleTypeAccount_StorageCapabilitiesSimpleTypeAccount_AccountCapabilitiesSimpleTypeAccount_CapabilitiesSimpleTypeAccount_StorageSimpleTypeMutateSimpleTypeInsertSimpleTypeRemoveSimpleTypeIdentitySimpleTypeStorageSimpleTypeSaveValueSimpleTypeLoadValueSimpleTypeCopyValueSimpleTypeBorrowValueSimpleTypeContractsSimpleTypeAddContractSimpleTypeUpdateContractSimpleTypeRemoveContractSimpleTypeKeysSimpleTypeAddKeySimpleTypeRevokeKeySimpleTypeInboxSimpleTypePublishInboxCapabilitySimpleTypeUnpublishInboxCapabilitySimpleTypeClaimInboxCapabilitySimpleTypeCapabilitiesSimpleTypeStorageCapabilitiesSimpleTypeAccountCapabilitiesSimpleTypePublishCapabilitySimpleTypeUnpublishCapabilitySimpleTypeGetStorageCapabilityControllerSimpleTypeIssueStorageCapabilityControllerSimpleTypeGetAccountCapabilityControllerSimpleTypeIssueAccountCapabilityControllerSimpleTypeCapabilitiesMappingSimpleTypeAccountMappingSimpleTypeHashableStructSimpleTypeFixedSizeUnsignedIntegerSimpleType_Count" ) var ( _SimpleType_index_0 = [...]uint16{0, 14, 30, 49, 66, 79, 93, 108, 123, 138, 154, 170, 184, 199, 215, 231, 247, 264, 281, 296, 312, 328, 344, 359, 375, 389, 413, 434, 454, 475} - _SimpleType_index_2 = [...]uint16{0, 15, 28, 47, 68, 86, 101, 117, 139, 156, 179, 199, 225, 240, 254, 272, 289, 306, 339, 374, 411, 448, 465, 492, 514, 537, 574, 611, 641, 666, 682, 698, 714, 732, 749, 768, 787, 806, 827, 846, 867, 891, 915, 929, 945, 964, 979, 1011, 1045, 1075, 1097, 1126, 1155, 1182, 1211, 1251, 1293, 1333, 1375, 1404, 1428, 1452, 1468} + _SimpleType_index_2 = [...]uint16{0, 15, 28, 47, 68, 86, 101, 117, 139, 156, 179, 199, 225, 240, 254, 272, 289, 306, 339, 374, 411, 448, 465, 492, 514, 537, 574, 611, 641, 666, 682, 698, 714, 732, 749, 768, 787, 806, 827, 846, 867, 891, 915, 929, 945, 964, 979, 1011, 1045, 1075, 1097, 1126, 1155, 1182, 1211, 1251, 1293, 1333, 1375, 1404, 1428, 1452, 1486, 1502} ) func (i SimpleType) String() string { @@ -119,7 +120,7 @@ func (i SimpleType) String() string { return _SimpleType_name_0[_SimpleType_index_0[i]:_SimpleType_index_0[i+1]] case i == 35: return _SimpleType_name_1 - case 37 <= i && i <= 98: + case 37 <= i && i <= 99: i -= 37 return _SimpleType_name_2[_SimpleType_index_2[i]:_SimpleType_index_2[i+1]] default: diff --git a/encoding/ccf/traverse_value.go b/encoding/ccf/traverse_value.go index bd05246bfd..d35d497add 100644 --- a/encoding/ccf/traverse_value.go +++ b/encoding/ccf/traverse_value.go @@ -225,6 +225,7 @@ func (ct *compositeTypes) traverseType(typ cadence.Type) (checkRuntimeType bool) cadence.SignedNumberType, cadence.IntegerType, cadence.SignedIntegerType, + cadence.FixedSizeUnsignedIntegerType, cadence.FixedPointType, cadence.SignedFixedPointType: diff --git a/runtime/convertTypes.go b/runtime/convertTypes.go index 0f5493cdef..efa8d9115e 100644 --- a/runtime/convertTypes.go +++ b/runtime/convertTypes.go @@ -58,6 +58,8 @@ func ExportMeteredType( return cadence.IntegerType case sema.SignedIntegerType: return cadence.SignedIntegerType + case sema.FixedSizeUnsignedIntegerType: + return cadence.FixedSizeUnsignedIntegerType case sema.FixedPointType: return cadence.FixedPointType case sema.SignedFixedPointType: diff --git a/runtime/convertValues_test.go b/runtime/convertValues_test.go index e0635104f7..bb46a65e9e 100644 --- a/runtime/convertValues_test.go +++ b/runtime/convertValues_test.go @@ -990,6 +990,11 @@ func TestRuntimeImportRuntimeType(t *testing.T) { actual: cadence.SignedIntegerType, expected: interpreter.PrimitiveStaticTypeSignedInteger, }, + { + label: "FixedSizeUnsignedInteger", + actual: cadence.FixedSizeUnsignedIntegerType, + expected: interpreter.PrimitiveStaticTypeFixedSizeUnsignedInteger, + }, { label: "FixedPoint", actual: cadence.FixedPointType, diff --git a/runtime/interpreter/big.go b/runtime/interpreter/big.go index efb359d500..14d0ed2748 100644 --- a/runtime/interpreter/big.go +++ b/runtime/interpreter/big.go @@ -140,3 +140,16 @@ func BigEndianBytesToSignedBigInt(b []byte) *big.Int { func BigEndianBytesToUnsignedBigInt(b []byte) *big.Int { return new(big.Int).SetBytes(b) } + +func LittleEndianBytesToUnsignedBigInt(b []byte) *big.Int { + len := len(b) + + // Convert the little endian byte slice to big-endian. + bigEndianBytes := make([]byte, len) + copy(bigEndianBytes, b) + for i := 0; i < len/2; i++ { + bigEndianBytes[i], bigEndianBytes[len-i-1] = bigEndianBytes[len-i-1], bigEndianBytes[i] + } + + return BigEndianBytesToUnsignedBigInt(bigEndianBytes) +} diff --git a/runtime/interpreter/interpreter.go b/runtime/interpreter/interpreter.go index 7ec3a47007..8326abb795 100644 --- a/runtime/interpreter/interpreter.go +++ b/runtime/interpreter/interpreter.go @@ -3343,7 +3343,7 @@ func init() { switch numberType { case sema.NumberType, sema.SignedNumberType, - sema.IntegerType, sema.SignedIntegerType, + sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType, sema.FixedPointType, sema.SignedFixedPointType: continue } diff --git a/runtime/interpreter/interpreter_expression.go b/runtime/interpreter/interpreter_expression.go index c2c2ad4e6d..edf185435d 100644 --- a/runtime/interpreter/interpreter_expression.go +++ b/runtime/interpreter/interpreter_expression.go @@ -784,7 +784,7 @@ func (interpreter *Interpreter) NewIntegerValueFromBigInt(value *big.Int, intege case sema.UInt128Type: // BigInt value is already metered at parser. return NewUnmeteredUInt128ValueFromBigInt(value) - case sema.UInt256Type: + case sema.UInt256Type, sema.FixedSizeUnsignedIntegerType: // BigInt value is already metered at parser. return NewUnmeteredUInt256ValueFromBigInt(value) diff --git a/runtime/interpreter/primitivestatictype.go b/runtime/interpreter/primitivestatictype.go index bbc0517bac..d66ffb1d04 100644 --- a/runtime/interpreter/primitivestatictype.go +++ b/runtime/interpreter/primitivestatictype.go @@ -97,7 +97,7 @@ const ( // Integer PrimitiveStaticTypeInteger PrimitiveStaticTypeSignedInteger - _ + PrimitiveStaticTypeFixedSizeUnsignedInteger _ _ _ @@ -303,6 +303,7 @@ func (t PrimitiveStaticType) elementSize() uint { PrimitiveStaticTypeWord256, PrimitiveStaticTypeInteger, PrimitiveStaticTypeSignedInteger, + PrimitiveStaticTypeFixedSizeUnsignedInteger, PrimitiveStaticTypeNumber, PrimitiveStaticTypeSignedNumber: return UnknownElementSize @@ -480,6 +481,8 @@ func (t PrimitiveStaticType) SemaType() sema.Type { return sema.IntegerType case PrimitiveStaticTypeSignedInteger: return sema.SignedIntegerType + case PrimitiveStaticTypeFixedSizeUnsignedInteger: + return sema.FixedSizeUnsignedIntegerType // FixedPoint case PrimitiveStaticTypeFixedPoint: @@ -693,6 +696,8 @@ func ConvertSemaToPrimitiveStaticType( typ = PrimitiveStaticTypeInteger case sema.SignedIntegerType: typ = PrimitiveStaticTypeSignedInteger + case sema.FixedSizeUnsignedIntegerType: + typ = PrimitiveStaticTypeFixedSizeUnsignedInteger // FixedPoint case sema.FixedPointType: diff --git a/runtime/interpreter/primitivestatictype_string.go b/runtime/interpreter/primitivestatictype_string.go index 8996c1b52f..23e7b7875e 100644 --- a/runtime/interpreter/primitivestatictype_string.go +++ b/runtime/interpreter/primitivestatictype_string.go @@ -27,6 +27,7 @@ func _() { _ = x[PrimitiveStaticTypeSignedNumber-19] _ = x[PrimitiveStaticTypeInteger-24] _ = x[PrimitiveStaticTypeSignedInteger-25] + _ = x[PrimitiveStaticTypeFixedSizeUnsignedInteger-26] _ = x[PrimitiveStaticTypeFixedPoint-30] _ = x[PrimitiveStaticTypeSignedFixedPoint-31] _ = x[PrimitiveStaticTypeInt-36] @@ -114,7 +115,7 @@ func _() { _ = x[PrimitiveStaticType_Count-152] } -const _PrimitiveStaticType_name = "UnknownVoidAnyNeverAnyStructAnyResourceBoolAddressStringCharacterMetaTypeBlockAnyResourceAttachmentAnyStructAttachmentHashableStructNumberSignedNumberIntegerSignedIntegerFixedPointSignedFixedPointIntInt8Int16Int32Int64Int128Int256UIntUInt8UInt16UInt32UInt64UInt128UInt256Word8Word16Word32Word64Word128Word256Fix64UFix64PathCapabilityStoragePathCapabilityPathPublicPathPrivatePathAuthAccountPublicAccountDeployedContractAuthAccountContractsPublicAccountContractsAuthAccountKeysPublicAccountKeysAccountKeyAuthAccountInboxStorageCapabilityControllerAccountCapabilityControllerAuthAccountStorageCapabilitiesAuthAccountAccountCapabilitiesAuthAccountCapabilitiesPublicAccountCapabilitiesAccountAccount_ContractsAccount_KeysAccount_InboxAccount_StorageCapabilitiesAccount_AccountCapabilitiesAccount_CapabilitiesAccount_StorageMutateInsertRemoveIdentityStorageSaveValueLoadValueCopyValueBorrowValueContractsAddContractUpdateContractRemoveContractKeysAddKeyRevokeKeyInboxPublishInboxCapabilityUnpublishInboxCapabilityClaimInboxCapabilityCapabilitiesStorageCapabilitiesAccountCapabilitiesPublishCapabilityUnpublishCapabilityGetStorageCapabilityControllerIssueStorageCapabilityControllerGetAccountCapabilityControllerIssueAccountCapabilityControllerCapabilitiesMappingAccountMapping_Count" +const _PrimitiveStaticType_name = "UnknownVoidAnyNeverAnyStructAnyResourceBoolAddressStringCharacterMetaTypeBlockAnyResourceAttachmentAnyStructAttachmentHashableStructNumberSignedNumberIntegerSignedIntegerFixedSizeUnsignedIntegerFixedPointSignedFixedPointIntInt8Int16Int32Int64Int128Int256UIntUInt8UInt16UInt32UInt64UInt128UInt256Word8Word16Word32Word64Word128Word256Fix64UFix64PathCapabilityStoragePathCapabilityPathPublicPathPrivatePathAuthAccountPublicAccountDeployedContractAuthAccountContractsPublicAccountContractsAuthAccountKeysPublicAccountKeysAccountKeyAuthAccountInboxStorageCapabilityControllerAccountCapabilityControllerAuthAccountStorageCapabilitiesAuthAccountAccountCapabilitiesAuthAccountCapabilitiesPublicAccountCapabilitiesAccountAccount_ContractsAccount_KeysAccount_InboxAccount_StorageCapabilitiesAccount_AccountCapabilitiesAccount_CapabilitiesAccount_StorageMutateInsertRemoveIdentityStorageSaveValueLoadValueCopyValueBorrowValueContractsAddContractUpdateContractRemoveContractKeysAddKeyRevokeKeyInboxPublishInboxCapabilityUnpublishInboxCapabilityClaimInboxCapabilityCapabilitiesStorageCapabilitiesAccountCapabilitiesPublishCapabilityUnpublishCapabilityGetStorageCapabilityControllerIssueStorageCapabilityControllerGetAccountCapabilityControllerIssueAccountCapabilityControllerCapabilitiesMappingAccountMapping_Count" var _PrimitiveStaticType_map = map[PrimitiveStaticType]string{ 0: _PrimitiveStaticType_name[0:7], @@ -136,91 +137,92 @@ var _PrimitiveStaticType_map = map[PrimitiveStaticType]string{ 19: _PrimitiveStaticType_name[138:150], 24: _PrimitiveStaticType_name[150:157], 25: _PrimitiveStaticType_name[157:170], - 30: _PrimitiveStaticType_name[170:180], - 31: _PrimitiveStaticType_name[180:196], - 36: _PrimitiveStaticType_name[196:199], - 37: _PrimitiveStaticType_name[199:203], - 38: _PrimitiveStaticType_name[203:208], - 39: _PrimitiveStaticType_name[208:213], - 40: _PrimitiveStaticType_name[213:218], - 41: _PrimitiveStaticType_name[218:224], - 42: _PrimitiveStaticType_name[224:230], - 44: _PrimitiveStaticType_name[230:234], - 45: _PrimitiveStaticType_name[234:239], - 46: _PrimitiveStaticType_name[239:245], - 47: _PrimitiveStaticType_name[245:251], - 48: _PrimitiveStaticType_name[251:257], - 49: _PrimitiveStaticType_name[257:264], - 50: _PrimitiveStaticType_name[264:271], - 53: _PrimitiveStaticType_name[271:276], - 54: _PrimitiveStaticType_name[276:282], - 55: _PrimitiveStaticType_name[282:288], - 56: _PrimitiveStaticType_name[288:294], - 57: _PrimitiveStaticType_name[294:301], - 58: _PrimitiveStaticType_name[301:308], - 64: _PrimitiveStaticType_name[308:313], - 72: _PrimitiveStaticType_name[313:319], - 76: _PrimitiveStaticType_name[319:323], - 77: _PrimitiveStaticType_name[323:333], - 78: _PrimitiveStaticType_name[333:344], - 79: _PrimitiveStaticType_name[344:358], - 80: _PrimitiveStaticType_name[358:368], - 81: _PrimitiveStaticType_name[368:379], - 90: _PrimitiveStaticType_name[379:390], - 91: _PrimitiveStaticType_name[390:403], - 92: _PrimitiveStaticType_name[403:419], - 93: _PrimitiveStaticType_name[419:439], - 94: _PrimitiveStaticType_name[439:461], - 95: _PrimitiveStaticType_name[461:476], - 96: _PrimitiveStaticType_name[476:493], - 97: _PrimitiveStaticType_name[493:503], - 98: _PrimitiveStaticType_name[503:519], - 99: _PrimitiveStaticType_name[519:546], - 100: _PrimitiveStaticType_name[546:573], - 101: _PrimitiveStaticType_name[573:603], - 102: _PrimitiveStaticType_name[603:633], - 103: _PrimitiveStaticType_name[633:656], - 104: _PrimitiveStaticType_name[656:681], - 105: _PrimitiveStaticType_name[681:688], - 106: _PrimitiveStaticType_name[688:705], - 107: _PrimitiveStaticType_name[705:717], - 108: _PrimitiveStaticType_name[717:730], - 109: _PrimitiveStaticType_name[730:757], - 110: _PrimitiveStaticType_name[757:784], - 111: _PrimitiveStaticType_name[784:804], - 112: _PrimitiveStaticType_name[804:819], - 118: _PrimitiveStaticType_name[819:825], - 119: _PrimitiveStaticType_name[825:831], - 120: _PrimitiveStaticType_name[831:837], - 121: _PrimitiveStaticType_name[837:845], - 125: _PrimitiveStaticType_name[845:852], - 126: _PrimitiveStaticType_name[852:861], - 127: _PrimitiveStaticType_name[861:870], - 128: _PrimitiveStaticType_name[870:879], - 129: _PrimitiveStaticType_name[879:890], - 130: _PrimitiveStaticType_name[890:899], - 131: _PrimitiveStaticType_name[899:910], - 132: _PrimitiveStaticType_name[910:924], - 133: _PrimitiveStaticType_name[924:938], - 134: _PrimitiveStaticType_name[938:942], - 135: _PrimitiveStaticType_name[942:948], - 136: _PrimitiveStaticType_name[948:957], - 137: _PrimitiveStaticType_name[957:962], - 138: _PrimitiveStaticType_name[962:984], - 139: _PrimitiveStaticType_name[984:1008], - 140: _PrimitiveStaticType_name[1008:1028], - 141: _PrimitiveStaticType_name[1028:1040], - 142: _PrimitiveStaticType_name[1040:1059], - 143: _PrimitiveStaticType_name[1059:1078], - 144: _PrimitiveStaticType_name[1078:1095], - 145: _PrimitiveStaticType_name[1095:1114], - 146: _PrimitiveStaticType_name[1114:1144], - 147: _PrimitiveStaticType_name[1144:1176], - 148: _PrimitiveStaticType_name[1176:1206], - 149: _PrimitiveStaticType_name[1206:1238], - 150: _PrimitiveStaticType_name[1238:1257], - 151: _PrimitiveStaticType_name[1257:1271], - 152: _PrimitiveStaticType_name[1271:1277], + 26: _PrimitiveStaticType_name[170:194], + 30: _PrimitiveStaticType_name[194:204], + 31: _PrimitiveStaticType_name[204:220], + 36: _PrimitiveStaticType_name[220:223], + 37: _PrimitiveStaticType_name[223:227], + 38: _PrimitiveStaticType_name[227:232], + 39: _PrimitiveStaticType_name[232:237], + 40: _PrimitiveStaticType_name[237:242], + 41: _PrimitiveStaticType_name[242:248], + 42: _PrimitiveStaticType_name[248:254], + 44: _PrimitiveStaticType_name[254:258], + 45: _PrimitiveStaticType_name[258:263], + 46: _PrimitiveStaticType_name[263:269], + 47: _PrimitiveStaticType_name[269:275], + 48: _PrimitiveStaticType_name[275:281], + 49: _PrimitiveStaticType_name[281:288], + 50: _PrimitiveStaticType_name[288:295], + 53: _PrimitiveStaticType_name[295:300], + 54: _PrimitiveStaticType_name[300:306], + 55: _PrimitiveStaticType_name[306:312], + 56: _PrimitiveStaticType_name[312:318], + 57: _PrimitiveStaticType_name[318:325], + 58: _PrimitiveStaticType_name[325:332], + 64: _PrimitiveStaticType_name[332:337], + 72: _PrimitiveStaticType_name[337:343], + 76: _PrimitiveStaticType_name[343:347], + 77: _PrimitiveStaticType_name[347:357], + 78: _PrimitiveStaticType_name[357:368], + 79: _PrimitiveStaticType_name[368:382], + 80: _PrimitiveStaticType_name[382:392], + 81: _PrimitiveStaticType_name[392:403], + 90: _PrimitiveStaticType_name[403:414], + 91: _PrimitiveStaticType_name[414:427], + 92: _PrimitiveStaticType_name[427:443], + 93: _PrimitiveStaticType_name[443:463], + 94: _PrimitiveStaticType_name[463:485], + 95: _PrimitiveStaticType_name[485:500], + 96: _PrimitiveStaticType_name[500:517], + 97: _PrimitiveStaticType_name[517:527], + 98: _PrimitiveStaticType_name[527:543], + 99: _PrimitiveStaticType_name[543:570], + 100: _PrimitiveStaticType_name[570:597], + 101: _PrimitiveStaticType_name[597:627], + 102: _PrimitiveStaticType_name[627:657], + 103: _PrimitiveStaticType_name[657:680], + 104: _PrimitiveStaticType_name[680:705], + 105: _PrimitiveStaticType_name[705:712], + 106: _PrimitiveStaticType_name[712:729], + 107: _PrimitiveStaticType_name[729:741], + 108: _PrimitiveStaticType_name[741:754], + 109: _PrimitiveStaticType_name[754:781], + 110: _PrimitiveStaticType_name[781:808], + 111: _PrimitiveStaticType_name[808:828], + 112: _PrimitiveStaticType_name[828:843], + 118: _PrimitiveStaticType_name[843:849], + 119: _PrimitiveStaticType_name[849:855], + 120: _PrimitiveStaticType_name[855:861], + 121: _PrimitiveStaticType_name[861:869], + 125: _PrimitiveStaticType_name[869:876], + 126: _PrimitiveStaticType_name[876:885], + 127: _PrimitiveStaticType_name[885:894], + 128: _PrimitiveStaticType_name[894:903], + 129: _PrimitiveStaticType_name[903:914], + 130: _PrimitiveStaticType_name[914:923], + 131: _PrimitiveStaticType_name[923:934], + 132: _PrimitiveStaticType_name[934:948], + 133: _PrimitiveStaticType_name[948:962], + 134: _PrimitiveStaticType_name[962:966], + 135: _PrimitiveStaticType_name[966:972], + 136: _PrimitiveStaticType_name[972:981], + 137: _PrimitiveStaticType_name[981:986], + 138: _PrimitiveStaticType_name[986:1008], + 139: _PrimitiveStaticType_name[1008:1032], + 140: _PrimitiveStaticType_name[1032:1052], + 141: _PrimitiveStaticType_name[1052:1064], + 142: _PrimitiveStaticType_name[1064:1083], + 143: _PrimitiveStaticType_name[1083:1102], + 144: _PrimitiveStaticType_name[1102:1119], + 145: _PrimitiveStaticType_name[1119:1138], + 146: _PrimitiveStaticType_name[1138:1168], + 147: _PrimitiveStaticType_name[1168:1200], + 148: _PrimitiveStaticType_name[1200:1230], + 149: _PrimitiveStaticType_name[1230:1262], + 150: _PrimitiveStaticType_name[1262:1281], + 151: _PrimitiveStaticType_name[1281:1295], + 152: _PrimitiveStaticType_name[1295:1301], } func (i PrimitiveStaticType) String() string { diff --git a/runtime/interpreter/statictype_test.go b/runtime/interpreter/statictype_test.go index e9e36363b3..d28ac7cf8b 100644 --- a/runtime/interpreter/statictype_test.go +++ b/runtime/interpreter/statictype_test.go @@ -1020,6 +1020,11 @@ func TestStaticTypeConversion(t *testing.T) { semaType: sema.SignedIntegerType, staticType: PrimitiveStaticTypeSignedInteger, }, + { + name: "FixedSizeUnsignedInteger", + semaType: sema.FixedSizeUnsignedIntegerType, + staticType: PrimitiveStaticTypeFixedSizeUnsignedInteger, + }, { name: "FixedPoint", diff --git a/runtime/interpreter/value_test.go b/runtime/interpreter/value_test.go index a3b00b8985..ad5431c5a6 100644 --- a/runtime/interpreter/value_test.go +++ b/runtime/interpreter/value_test.go @@ -3492,7 +3492,7 @@ func TestNumberValueIntegerConversion(t *testing.T) { for _, ty := range sema.AllIntegerTypes { // Only test leaf types switch ty { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } @@ -3797,7 +3797,7 @@ func TestValue_ConformsToStaticType(t *testing.T) { for _, ty := range sema.AllIntegerTypes { // Only test leaf types switch ty { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } diff --git a/runtime/literal.go b/runtime/literal.go index 53efe30bb5..03dda380aa 100644 --- a/runtime/literal.go +++ b/runtime/literal.go @@ -258,7 +258,7 @@ func convertIntValue( return interpreter.ConvertUInt64(memoryGauge, intValue, interpreter.EmptyLocationRange), nil case sema.UInt128Type: return interpreter.ConvertUInt128(memoryGauge, intValue, interpreter.EmptyLocationRange), nil - case sema.UInt256Type: + case sema.UInt256Type, sema.FixedSizeUnsignedIntegerType: return interpreter.ConvertUInt256(memoryGauge, intValue, interpreter.EmptyLocationRange), nil case sema.Word8Type: diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index 253dbd1826..cca852c24d 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -23,6 +23,7 @@ import ( "encoding/hex" "errors" "fmt" + "math" "sync" "sync/atomic" "testing" @@ -4459,7 +4460,7 @@ func TestRuntimeBlock(t *testing.T) { ) } -func TestRuntimeRandom(t *testing.T) { +func TestRuntimeRandomWithUnsafeRandom(t *testing.T) { t.Parallel() @@ -4468,7 +4469,8 @@ func TestRuntimeRandom(t *testing.T) { script := []byte(` transaction { prepare() { - log(revertibleRandom()) + let rand1 = revertibleRandom() + log(rand1) } } `) @@ -4506,6 +4508,93 @@ func TestRuntimeRandom(t *testing.T) { ) } +func getFixedSizeUnsignedIntegerForSemaType(ty sema.Type) cadence.Value { + switch ty { + case sema.UInt8Type: + return cadence.NewUInt8(math.MaxUint8) + case sema.UInt16Type: + return cadence.NewUInt16(math.MaxUint16) + case sema.UInt32Type: + return cadence.NewUInt32(math.MaxUint32) + case sema.UInt64Type: + return cadence.NewUInt64(math.MaxUint64) + case sema.UInt128Type: + value, _ := cadence.NewUInt128FromBig(sema.UInt128TypeMaxIntBig) + return value + case sema.UInt256Type: + value, _ := cadence.NewUInt256FromBig(sema.UInt256TypeMaxIntBig) + return value + + case sema.Word8Type: + return cadence.NewWord8(math.MaxUint8) + case sema.Word16Type: + return cadence.NewWord16(math.MaxUint16) + case sema.Word32Type: + return cadence.NewWord32(math.MaxUint32) + case sema.Word64Type: + return cadence.NewWord64(math.MaxUint64) + case sema.Word128Type: + value, _ := cadence.NewWord128FromBig(sema.Word128TypeMaxIntBig) + return value + case sema.Word256Type: + value, _ := cadence.NewWord256FromBig(sema.Word256TypeMaxIntBig) + return value + } + + panic(fmt.Sprintf("Broken test. Trying to get fixed size unsigned integer for ty: %s", ty)) +} + +func TestRuntimeRandom(t *testing.T) { + + t.Parallel() + + script := ` + access(all) fun main(): %[1]s { + let rand = revertibleRandom<%[1]s>() + return rand + } + ` + + runValidCaseWithoutModulo := func(t *testing.T, ty sema.Type) { + t.Run(ty.String(), func(t *testing.T) { + t.Parallel() + + nextScriptLocation := NewScriptLocationGenerator() + + runtime := NewTestInterpreterRuntime() + value, err := runtime.ExecuteScript( + Script{ + Source: []byte(fmt.Sprintf(script, ty.String())), + }, + Context{ + Interface: &TestRuntimeInterface{ + OnReadRandom: func(buffer []byte) error { + for i := 0; i < len(buffer); i++ { + buffer[i] = 0xff + } + return nil + }, + }, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + require.Equal(t, getFixedSizeUnsignedIntegerForSemaType(ty), value) + }) + } + + for _, ty := range sema.AllFixedSizeUnsignedIntegerTypes { + switch ty { + case sema.FixedSizeUnsignedIntegerType: + continue + + default: + runValidCaseWithoutModulo(t, ty) + } + } +} + func TestRuntimeTransactionTopLevelDeclarations(t *testing.T) { t.Parallel() diff --git a/runtime/sema/type.go b/runtime/sema/type.go index e99b80c536..06fdb816fa 100644 --- a/runtime/sema/type.go +++ b/runtime/sema/type.go @@ -1492,6 +1492,11 @@ var ( SignedIntegerTypeAnnotation = NewTypeAnnotation(SignedIntegerType) + // FixedSizeUnsignedIntegerType represents the super-type of all unsigned integer types which have a fixed size. + FixedSizeUnsignedIntegerType = NewNumericType(FixedSizeUnsignedIntegerTypeName). + WithTag(FixedSizeUnsignedIntegerTypeTag). + AsSuperType() + // IntType represents the arbitrary-precision integer type `Int` IntType = NewNumericType(IntTypeName). WithTag(IntTypeTag) @@ -3847,9 +3852,8 @@ var AllSignedIntegerTypes = []Type{ Int256Type, } -var AllUnsignedIntegerTypes = []Type{ +var AllFixedSizeUnsignedIntegerTypes = []Type{ // UInt* - UIntType, UInt8Type, UInt16Type, UInt32Type, @@ -3865,12 +3869,20 @@ var AllUnsignedIntegerTypes = []Type{ Word256Type, } +var AllUnsignedIntegerTypes = common.Concat( + AllFixedSizeUnsignedIntegerTypes, + []Type{ + UIntType, + }, +) + var AllIntegerTypes = common.Concat( AllUnsignedIntegerTypes, AllSignedIntegerTypes, []Type{ IntegerType, SignedIntegerType, + FixedSizeUnsignedIntegerType, }, ) @@ -3910,7 +3922,7 @@ func init() { switch numberType { case NumberType, SignedNumberType, - IntegerType, SignedIntegerType, + IntegerType, SignedIntegerType, FixedSizeUnsignedIntegerType, FixedPointType, SignedFixedPointType: continue @@ -6514,15 +6526,13 @@ func checkSubTypeWithoutEquality(subType Type, superType Type) bool { case IntegerType: switch subType { - case IntegerType, SignedIntegerType, - UIntType, - UInt8Type, UInt16Type, UInt32Type, UInt64Type, UInt128Type, UInt256Type, - Word8Type, Word16Type, Word32Type, Word64Type, Word128Type, Word256Type: + case IntegerType, SignedIntegerType, FixedSizeUnsignedIntegerType, + UIntType: return true default: - return IsSubType(subType, SignedIntegerType) + return IsSubType(subType, SignedIntegerType) || IsSubType(subType, FixedSizeUnsignedIntegerType) } case SignedIntegerType: @@ -6537,6 +6547,17 @@ func checkSubTypeWithoutEquality(subType Type, superType Type) bool { return false } + case FixedSizeUnsignedIntegerType: + switch subType { + case UInt8Type, UInt16Type, UInt32Type, UInt64Type, UInt128Type, UInt256Type, + Word8Type, Word16Type, Word32Type, Word64Type, Word128Type, Word256Type: + + return true + + default: + return false + } + case FixedPointType: switch subType { case FixedPointType, SignedFixedPointType, diff --git a/runtime/sema/type_names.go b/runtime/sema/type_names.go index 7ac1ac7ca2..f1581c5c03 100644 --- a/runtime/sema/type_names.go +++ b/runtime/sema/type_names.go @@ -19,12 +19,13 @@ package sema const ( - NumberTypeName = "Number" - SignedNumberTypeName = "SignedNumber" - IntegerTypeName = "Integer" - SignedIntegerTypeName = "SignedInteger" - FixedPointTypeName = "FixedPoint" - SignedFixedPointTypeName = "SignedFixedPoint" + NumberTypeName = "Number" + SignedNumberTypeName = "SignedNumber" + IntegerTypeName = "Integer" + SignedIntegerTypeName = "SignedInteger" + FixedSizeUnsignedIntegerTypeName = "FixedSizeUnsignedInteger" + FixedPointTypeName = "FixedPoint" + SignedFixedPointTypeName = "SignedFixedPoint" IntTypeName = "Int" Int8TypeName = "Int8" diff --git a/runtime/sema/type_tags.go b/runtime/sema/type_tags.go index e0abd87e24..88e8deca96 100644 --- a/runtime/sema/type_tags.go +++ b/runtime/sema/type_tags.go @@ -221,6 +221,8 @@ const ( storageCapabilityControllerTypeMask accountCapabilityControllerTypeMask + fixedSizeUnsignedIntegerTypeMask + interfaceTypeMask functionTypeMask @@ -242,20 +244,23 @@ var ( Or(Int128TypeTag). Or(Int256TypeTag) + FixedSizeUnsignedIntegerTypeTag = newTypeTagFromUpperMask(fixedSizeUnsignedIntegerTypeMask). + Or(UInt8TypeTag). + Or(UInt16TypeTag). + Or(UInt32TypeTag). + Or(UInt64TypeTag). + Or(UInt128TypeTag). + Or(UInt256TypeTag). + Or(Word8TypeTag). + Or(Word16TypeTag). + Or(Word32TypeTag). + Or(Word64TypeTag). + Or(Word128TypeTag). + Or(Word256TypeTag) + UnsignedIntegerTypeTag = newTypeTagFromLowerMask(unsignedIntegerTypeMask). Or(UIntTypeTag). - Or(UInt8TypeTag). - Or(UInt16TypeTag). - Or(UInt32TypeTag). - Or(UInt64TypeTag). - Or(UInt128TypeTag). - Or(UInt256TypeTag). - Or(Word8TypeTag). - Or(Word16TypeTag). - Or(Word32TypeTag). - Or(Word64TypeTag). - Or(Word128TypeTag). - Or(Word256TypeTag) + Or(FixedSizeUnsignedIntegerTypeTag) IntegerTypeTag = newTypeTagFromLowerMask(integerTypeMask). Or(SignedIntegerTypeTag). @@ -502,6 +507,8 @@ func findCommonSuperType(joinedTypeTag TypeTag, types ...Type) Type { return InvalidType case joinedTypeTag.BelongsTo(SignedIntegerTypeTag): return SignedIntegerType + case joinedTypeTag.BelongsTo(FixedSizeUnsignedIntegerTypeTag): + return FixedSizeUnsignedIntegerType case joinedTypeTag.BelongsTo(IntegerTypeTag): return IntegerType case joinedTypeTag.BelongsTo(SignedFixedPointTypeTag): @@ -701,6 +708,9 @@ func findSuperTypeFromUpperMask(joinedTypeTag TypeTag, types []Type) Type { case accountCapabilityControllerTypeMask: return AccountCapabilityControllerType + case fixedSizeUnsignedIntegerTypeMask: + return FixedSizeUnsignedIntegerType + default: return nil } diff --git a/runtime/sema/type_test.go b/runtime/sema/type_test.go index 3308e027ef..40d4d97dc7 100644 --- a/runtime/sema/type_test.go +++ b/runtime/sema/type_test.go @@ -772,9 +772,18 @@ func TestCommonSuperType(t *testing.T) { types: []Type{ UInt8Type, UInt128Type, + UIntType, }, expectedSuperType: IntegerType, }, + { + name: "fixed size unsigned integers", + types: []Type{ + UInt8Type, + UInt128Type, + }, + expectedSuperType: FixedSizeUnsignedIntegerType, + }, { name: "heterogeneous simple types", types: []Type{ @@ -1748,6 +1757,16 @@ func TestTypeInclusions(t *testing.T) { } }) + t.Run("FixedSizeUnsignedInteger", func(t *testing.T) { + t.Parallel() + + for _, typ := range AllFixedSizeUnsignedIntegerTypes { + t.Run(typ.String(), func(t *testing.T) { + assert.True(t, FixedSizeUnsignedIntegerTypeTag.ContainsAny(typ.Tag())) + }) + } + }) + t.Run("FixedPoint", func(t *testing.T) { t.Parallel() diff --git a/runtime/stdlib/random.go b/runtime/stdlib/random.go index 4e738e8dba..ba9a00fc5e 100644 --- a/runtime/stdlib/random.go +++ b/runtime/stdlib/random.go @@ -20,6 +20,7 @@ package stdlib import ( "encoding/binary" + "math/big" "github.com/onflow/cadence/runtime/errors" "github.com/onflow/cadence/runtime/interpreter" @@ -34,37 +35,164 @@ NOTE: The use of this function is unsafe if not used correctly. Follow best practices to prevent security issues when using this function ` -var revertibleRandomFunctionType = sema.NewSimpleFunctionType( - sema.FunctionPurityImpure, - nil, - sema.UInt64TypeAnnotation, -) +var revertibleRandomFunctionType = func() *sema.FunctionType { + typeParameter := &sema.TypeParameter{ + Name: "T", + TypeBound: sema.FixedSizeUnsignedIntegerType, + } + + typeAnnotation := sema.NewTypeAnnotation( + &sema.GenericType{ + TypeParameter: typeParameter, + }, + ) + + return &sema.FunctionType{ + TypeParameters: []*sema.TypeParameter{ + typeParameter, + }, + Parameters: []sema.Parameter{ + { + Identifier: "modulo", + TypeAnnotation: typeAnnotation, + }, + }, + ReturnTypeAnnotation: typeAnnotation, + // `modulo` parameter is optional + Arity: &sema.Arity{Min: 0, Max: 1}, + } +}() type RandomGenerator interface { // ReadRandom reads pseudo-random bytes into the input slice, using distributed randomness. + // The number of bytes read is equal to the length of input slice. ReadRandom([]byte) error } +func getRandomBytes(generator RandomGenerator, numBytes int) []byte { + buffer := make([]byte, numBytes) + + var err error + errors.WrapPanic(func() { + err = generator.ReadRandom(buffer[:]) + }) + if err != nil { + panic(interpreter.WrappedExternalError(err)) + } + + return buffer +} + func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue { return NewStandardLibraryFunction( "revertibleRandom", revertibleRandomFunctionType, revertibleRandomFunctionDocString, func(invocation interpreter.Invocation) interpreter.Value { - return interpreter.NewUInt64Value( - invocation.Interpreter, - func() uint64 { - var buffer [8]byte - var err error - errors.WrapPanic(func() { - err = generator.ReadRandom(buffer[:]) - }) - if err != nil { - panic(interpreter.WrappedExternalError(err)) - } - return binary.LittleEndian.Uint64(buffer[:]) - }, - ) + inter := invocation.Interpreter + + // TODO: Check if invocation has an argument and implement modulo operation. + + returnIntegerType := invocation.TypeParameterTypes.Oldest().Value + returnIntegerStaticType := interpreter.ConvertSemaToStaticType(inter, returnIntegerType) + + switch returnIntegerStaticType { + // UInt* + case interpreter.PrimitiveStaticTypeUInt8: + return interpreter.NewUInt8Value( + inter, + func() uint8 { + return getRandomBytes(generator, 1)[0] + }, + ) + case interpreter.PrimitiveStaticTypeUInt16: + return interpreter.NewUInt16Value( + inter, + func() uint16 { + return binary.LittleEndian.Uint16(getRandomBytes(generator, 2)) + }, + ) + case interpreter.PrimitiveStaticTypeUInt32: + return interpreter.NewUInt32Value( + inter, + func() uint32 { + return binary.LittleEndian.Uint32(getRandomBytes(generator, 4)) + }, + ) + case interpreter.PrimitiveStaticTypeUInt64: + return interpreter.NewUInt64Value( + inter, + func() uint64 { + return binary.LittleEndian.Uint64(getRandomBytes(generator, 8)) + }, + ) + case interpreter.PrimitiveStaticTypeUInt128: + return interpreter.NewUInt128ValueFromBigInt( + inter, + func() *big.Int { + buffer := getRandomBytes(generator, 16) + return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + }, + ) + case interpreter.PrimitiveStaticTypeUInt256: + return interpreter.NewUInt256ValueFromBigInt( + inter, + func() *big.Int { + buffer := getRandomBytes(generator, 32) + return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + }, + ) + + // Word* + case interpreter.PrimitiveStaticTypeWord8: + return interpreter.NewWord8Value( + inter, + func() uint8 { + return getRandomBytes(generator, 1)[0] + }, + ) + case interpreter.PrimitiveStaticTypeWord16: + return interpreter.NewWord16Value( + inter, + func() uint16 { + return binary.LittleEndian.Uint16(getRandomBytes(generator, 2)) + }, + ) + case interpreter.PrimitiveStaticTypeWord32: + return interpreter.NewWord32Value( + inter, + func() uint32 { + return binary.LittleEndian.Uint32(getRandomBytes(generator, 4)) + }, + ) + case interpreter.PrimitiveStaticTypeWord64: + return interpreter.NewWord64Value( + inter, + func() uint64 { + return binary.LittleEndian.Uint64(getRandomBytes(generator, 8)) + }, + ) + case interpreter.PrimitiveStaticTypeWord128: + return interpreter.NewWord128ValueFromBigInt( + inter, + func() *big.Int { + buffer := getRandomBytes(generator, 16) + return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + }, + ) + case interpreter.PrimitiveStaticTypeWord256: + return interpreter.NewWord256ValueFromBigInt( + inter, + func() *big.Int { + buffer := getRandomBytes(generator, 32) + return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + }, + ) + + default: + // Checker should prevent this. + panic(errors.NewUnreachableError()) + } }, ) } diff --git a/runtime/tests/checker/builtinfunctions_test.go b/runtime/tests/checker/builtinfunctions_test.go index 12e0cb4f14..7df0ede09a 100644 --- a/runtime/tests/checker/builtinfunctions_test.go +++ b/runtime/tests/checker/builtinfunctions_test.go @@ -27,6 +27,7 @@ import ( "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/sema" + "github.com/onflow/cadence/runtime/stdlib" ) func TestCheckToString(t *testing.T) { @@ -252,7 +253,7 @@ func TestCheckFromBigEndianBytes(t *testing.T) { for _, ty := range sema.AllNumberTypes { switch ty { case sema.NumberType, sema.SignedNumberType, - sema.IntegerType, sema.SignedIntegerType, + sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType, sema.FixedPointType, sema.SignedFixedPointType: continue @@ -268,3 +269,86 @@ func TestCheckFromBigEndianBytes(t *testing.T) { } } } + +type testRandomGenerator struct{} + +func (*testRandomGenerator) ReadRandom([]byte) error { + return nil +} + +func TestCheckRevertibleRandom(t *testing.T) { + + t.Parallel() + + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseValueActivation.DeclareValue(stdlib.NewRevertibleRandomFunction(&testRandomGenerator{})) + options := ParseAndCheckOptions{ + Config: &sema.Config{ + BaseValueActivationHandler: func(_ common.Location) *sema.VariableActivation { + return baseValueActivation + }, + }, + } + + runCase := func(t *testing.T, ty sema.Type, code string) { + checker, err := ParseAndCheckWithOptions(t, code, options) + + require.NoError(t, err) + + resType := RequireGlobalValue(t, checker.Elaboration, "rand") + require.Equal(t, ty, resType) + } + + runValidCaseWithoutModulo := func(t *testing.T, ty sema.Type) { + t.Run(fmt.Sprintf("revertibleRandom<%s>_no_modulo", ty), func(t *testing.T) { + t.Parallel() + + code := fmt.Sprintf("let rand = revertibleRandom<%s>()", ty) + runCase(t, ty, code) + }) + } + + runValidCaseWithModulo := func(t *testing.T, ty sema.Type) { + t.Run(fmt.Sprintf("revertibleRandom<%s>_modulo", ty), func(t *testing.T) { + t.Parallel() + + code := fmt.Sprintf("let rand = revertibleRandom<%[1]s>(modulo: %[1]s(1))", ty) + runCase(t, ty, code) + }) + } + + runInvalidCase := func(t *testing.T, testName string, code string, expectedErrors []error) { + t.Run(testName, func(t *testing.T) { + t.Parallel() + + _, err := ParseAndCheckWithOptions(t, code, options) + + errs := RequireCheckerErrors(t, err, len(expectedErrors)) + for i := range expectedErrors { + assert.IsType(t, expectedErrors[i], errs[i]) + } + }) + } + + for _, ty := range sema.AllFixedSizeUnsignedIntegerTypes { + switch ty { + case sema.FixedSizeUnsignedIntegerType: + continue + + default: + runValidCaseWithoutModulo(t, ty) + runValidCaseWithModulo(t, ty) + } + } + + runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom()", []error{&sema.TypeMismatchError{}}) + runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom(modulo: \"abcd\")", []error{&sema.TypeMismatchError{}}) + runInvalidCase(t, "missing_argument_label", "let rand = revertibleRandom(UInt256(1))", []error{&sema.MissingArgumentLabelError{}}) + runInvalidCase(t, "incorrect_argument_label", "let rand = revertibleRandom(typo: UInt256(1))", []error{&sema.IncorrectArgumentLabelError{}}) + runInvalidCase(t, "too_many_args", "let rand = revertibleRandom(modulo: UInt256(1), 2, 3)", []error{&sema.ExcessiveArgumentsError{}}) + runInvalidCase(t, "modulo type mismatch", "let rand = revertibleRandom(modulo: UInt128(1))", []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) + runInvalidCase(t, "string modulo", "let rand = revertibleRandom(modulo: \"abcd\")", []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) + + // This is an error since we do not support type inference of function arguments. + runInvalidCase(t, "missing_typeinference", "let rand = revertibleRandom(modulo: 1)", []error{&sema.TypeParameterTypeMismatchError{}}) +} diff --git a/runtime/tests/checker/integer_test.go b/runtime/tests/checker/integer_test.go index 6f55526aba..7051db107b 100644 --- a/runtime/tests/checker/integer_test.go +++ b/runtime/tests/checker/integer_test.go @@ -458,7 +458,7 @@ func TestCheckInvalidIntegerConversionFunctionWithoutArgs(t *testing.T) { for _, ty := range allIntegerTypesAndAddressType { // Only test leaf types switch ty { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } @@ -488,7 +488,7 @@ func TestCheckFixedPointToIntegerConversion(t *testing.T) { for _, ty := range sema.AllIntegerTypes { // Only test leaf types switch ty { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } @@ -531,7 +531,8 @@ func TestCheckIntegerLiteralArguments(t *testing.T) { switch ty { case sema.IntegerType, - sema.SignedIntegerType: + sema.SignedIntegerType, + sema.FixedSizeUnsignedIntegerType: errs := RequireCheckerErrors(t, err, 1) assert.IsType(t, &sema.InvalidBinaryOperandsError{}, errs[0]) default: @@ -567,7 +568,7 @@ func TestCheckIntegerMinMax(t *testing.T) { for _, ty := range sema.AllIntegerTypes { // Only test leaf types switch ty { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } diff --git a/runtime/tests/checker/operations_test.go b/runtime/tests/checker/operations_test.go index 8f9f9d3091..1716b73437 100644 --- a/runtime/tests/checker/operations_test.go +++ b/runtime/tests/checker/operations_test.go @@ -600,6 +600,7 @@ func TestCheckNumericSuperTypeBinaryOperations(t *testing.T) { sema.SignedNumberType, sema.IntegerType, sema.SignedIntegerType, + sema.FixedSizeUnsignedIntegerType, sema.FixedPointType, sema.SignedFixedPointType, } diff --git a/runtime/tests/interpreter/arithmetic_test.go b/runtime/tests/interpreter/arithmetic_test.go index d108ca90b1..84974e2d4a 100644 --- a/runtime/tests/interpreter/arithmetic_test.go +++ b/runtime/tests/interpreter/arithmetic_test.go @@ -62,7 +62,7 @@ func init() { for _, integerType := range sema.AllIntegerTypes { switch integerType { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } diff --git a/runtime/tests/interpreter/bitwise_test.go b/runtime/tests/interpreter/bitwise_test.go index ad44a095ca..eb88426bda 100644 --- a/runtime/tests/interpreter/bitwise_test.go +++ b/runtime/tests/interpreter/bitwise_test.go @@ -97,7 +97,7 @@ func init() { for _, integerType := range sema.AllIntegerTypes { switch integerType { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } diff --git a/runtime/tests/interpreter/builtinfunctions_test.go b/runtime/tests/interpreter/builtinfunctions_test.go index ffecb3e172..f70d97f3cc 100644 --- a/runtime/tests/interpreter/builtinfunctions_test.go +++ b/runtime/tests/interpreter/builtinfunctions_test.go @@ -559,7 +559,7 @@ func TestInterpretToBigEndianBytes(t *testing.T) { for _, integerType := range sema.AllNumberTypes { switch integerType { case sema.NumberType, sema.SignedNumberType, - sema.IntegerType, sema.SignedIntegerType, + sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType, sema.FixedPointType, sema.SignedFixedPointType: continue } @@ -894,7 +894,7 @@ func TestInterpretFromBigEndianBytes(t *testing.T) { for _, integerType := range sema.AllNumberTypes { switch integerType { case sema.NumberType, sema.SignedNumberType, - sema.IntegerType, sema.SignedIntegerType, + sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType, sema.FixedPointType, sema.SignedFixedPointType: continue } diff --git a/runtime/tests/interpreter/integers_test.go b/runtime/tests/interpreter/integers_test.go index 160826e5f1..285b35dd63 100644 --- a/runtime/tests/interpreter/integers_test.go +++ b/runtime/tests/interpreter/integers_test.go @@ -64,7 +64,7 @@ func init() { for _, integerType := range sema.AllIntegerTypes { // Only test leaf types switch integerType { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } @@ -705,7 +705,7 @@ func TestInterpretIntegerConversion(t *testing.T) { for _, ty := range sema.AllIntegerTypes { // Only test leaf types switch ty { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } @@ -891,7 +891,7 @@ func TestInterpretIntegerMinMax(t *testing.T) { for _, ty := range sema.AllIntegerTypes { // Only test leaf types switch ty { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } diff --git a/runtime/tests/interpreter/interpreter_test.go b/runtime/tests/interpreter/interpreter_test.go index f189dcd5ad..e22656e190 100644 --- a/runtime/tests/interpreter/interpreter_test.go +++ b/runtime/tests/interpreter/interpreter_test.go @@ -7510,7 +7510,7 @@ func TestInterpretEmitEventParameterTypes(t *testing.T) { for _, integerType := range sema.AllIntegerTypes { switch integerType { - case sema.IntegerType, sema.SignedIntegerType: + case sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType: continue } diff --git a/types.go b/types.go index ac62eb8c4f..2bfc7c101c 100644 --- a/types.go +++ b/types.go @@ -137,6 +137,7 @@ var SignedNumberType = PrimitiveType(interpreter.PrimitiveStaticTypeSignedNumber var IntegerType = PrimitiveType(interpreter.PrimitiveStaticTypeInteger) var SignedIntegerType = PrimitiveType(interpreter.PrimitiveStaticTypeSignedInteger) +var FixedSizeUnsignedIntegerType = PrimitiveType(interpreter.PrimitiveStaticTypeFixedSizeUnsignedInteger) var FixedPointType = PrimitiveType(interpreter.PrimitiveStaticTypeFixedPoint) var SignedFixedPointType = PrimitiveType(interpreter.PrimitiveStaticTypeSignedFixedPoint) diff --git a/values_test.go b/values_test.go index a86ab1e740..66f90fc4a6 100644 --- a/values_test.go +++ b/values_test.go @@ -634,7 +634,7 @@ func TestNumberValue_ToBigEndianBytes(t *testing.T) { for _, integerType := range sema.AllNumberTypes { switch integerType { case sema.NumberType, sema.SignedNumberType, - sema.IntegerType, sema.SignedIntegerType, + sema.IntegerType, sema.SignedIntegerType, sema.FixedSizeUnsignedIntegerType, sema.FixedPointType, sema.SignedFixedPointType: continue } From 7465d6541df49e91497c8d7a82c9e67d5b839176 Mon Sep 17 00:00:00 2001 From: darkdrag00n Date: Wed, 6 Dec 2023 14:26:42 +0530 Subject: [PATCH 2/6] use big-endian throughout --- runtime/interpreter/big.go | 13 ------------- runtime/stdlib/random.go | 20 ++++++++++---------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/runtime/interpreter/big.go b/runtime/interpreter/big.go index 14d0ed2748..efb359d500 100644 --- a/runtime/interpreter/big.go +++ b/runtime/interpreter/big.go @@ -140,16 +140,3 @@ func BigEndianBytesToSignedBigInt(b []byte) *big.Int { func BigEndianBytesToUnsignedBigInt(b []byte) *big.Int { return new(big.Int).SetBytes(b) } - -func LittleEndianBytesToUnsignedBigInt(b []byte) *big.Int { - len := len(b) - - // Convert the little endian byte slice to big-endian. - bigEndianBytes := make([]byte, len) - copy(bigEndianBytes, b) - for i := 0; i < len/2; i++ { - bigEndianBytes[i], bigEndianBytes[len-i-1] = bigEndianBytes[len-i-1], bigEndianBytes[i] - } - - return BigEndianBytesToUnsignedBigInt(bigEndianBytes) -} diff --git a/runtime/stdlib/random.go b/runtime/stdlib/random.go index ba9a00fc5e..122415e548 100644 --- a/runtime/stdlib/random.go +++ b/runtime/stdlib/random.go @@ -109,21 +109,21 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue return interpreter.NewUInt16Value( inter, func() uint16 { - return binary.LittleEndian.Uint16(getRandomBytes(generator, 2)) + return binary.BigEndian.Uint16(getRandomBytes(generator, 2)) }, ) case interpreter.PrimitiveStaticTypeUInt32: return interpreter.NewUInt32Value( inter, func() uint32 { - return binary.LittleEndian.Uint32(getRandomBytes(generator, 4)) + return binary.BigEndian.Uint32(getRandomBytes(generator, 4)) }, ) case interpreter.PrimitiveStaticTypeUInt64: return interpreter.NewUInt64Value( inter, func() uint64 { - return binary.LittleEndian.Uint64(getRandomBytes(generator, 8)) + return binary.BigEndian.Uint64(getRandomBytes(generator, 8)) }, ) case interpreter.PrimitiveStaticTypeUInt128: @@ -131,7 +131,7 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue inter, func() *big.Int { buffer := getRandomBytes(generator, 16) - return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + return interpreter.BigEndianBytesToUnsignedBigInt(buffer) }, ) case interpreter.PrimitiveStaticTypeUInt256: @@ -139,7 +139,7 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue inter, func() *big.Int { buffer := getRandomBytes(generator, 32) - return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + return interpreter.BigEndianBytesToUnsignedBigInt(buffer) }, ) @@ -155,21 +155,21 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue return interpreter.NewWord16Value( inter, func() uint16 { - return binary.LittleEndian.Uint16(getRandomBytes(generator, 2)) + return binary.BigEndian.Uint16(getRandomBytes(generator, 2)) }, ) case interpreter.PrimitiveStaticTypeWord32: return interpreter.NewWord32Value( inter, func() uint32 { - return binary.LittleEndian.Uint32(getRandomBytes(generator, 4)) + return binary.BigEndian.Uint32(getRandomBytes(generator, 4)) }, ) case interpreter.PrimitiveStaticTypeWord64: return interpreter.NewWord64Value( inter, func() uint64 { - return binary.LittleEndian.Uint64(getRandomBytes(generator, 8)) + return binary.BigEndian.Uint64(getRandomBytes(generator, 8)) }, ) case interpreter.PrimitiveStaticTypeWord128: @@ -177,7 +177,7 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue inter, func() *big.Int { buffer := getRandomBytes(generator, 16) - return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + return interpreter.BigEndianBytesToUnsignedBigInt(buffer) }, ) case interpreter.PrimitiveStaticTypeWord256: @@ -185,7 +185,7 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue inter, func() *big.Int { buffer := getRandomBytes(generator, 32) - return interpreter.LittleEndianBytesToUnsignedBigInt(buffer) + return interpreter.BigEndianBytesToUnsignedBigInt(buffer) }, ) From eb39e9dad5469fba9db50fb2d4423767d28eabaf Mon Sep 17 00:00:00 2001 From: darkdrag00n Date: Wed, 6 Dec 2023 14:31:54 +0530 Subject: [PATCH 3/6] Fix TestRuntimeRandomWithUnsafeRandom test --- runtime/runtime_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index cca852c24d..d0421effc1 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -4479,7 +4479,7 @@ func TestRuntimeRandomWithUnsafeRandom(t *testing.T) { runtimeInterface := &TestRuntimeInterface{ OnReadRandom: func(buffer []byte) error { - binary.LittleEndian.PutUint64(buffer, 7558174677681708339) + binary.BigEndian.PutUint64(buffer, 7558174677681708339) return nil }, OnProgramLog: func(message string) { From 9c6d4fc3ed3b2248c98354de0e3dd11b3bbc930c Mon Sep 17 00:00:00 2001 From: darkdrag00n Date: Wed, 6 Dec 2023 16:29:11 +0530 Subject: [PATCH 4/6] Add more tests --- .../imported_values_memory_metering_test.go | 12 ++++ runtime/sema/checker_test.go | 9 +++ .../tests/checker/builtinfunctions_test.go | 32 +++++----- runtime/tests/checker/casting_test.go | 15 +++++ runtime/tests/interpreter/equality_test.go | 64 +++++++++++++++++++ 5 files changed, 116 insertions(+), 16 deletions(-) diff --git a/runtime/imported_values_memory_metering_test.go b/runtime/imported_values_memory_metering_test.go index ad90f76c9b..7b0eec28c0 100644 --- a/runtime/imported_values_memory_metering_test.go +++ b/runtime/imported_values_memory_metering_test.go @@ -192,6 +192,18 @@ func TestRuntimeImportedValueMemoryMetering(t *testing.T) { assert.Equal(t, uint64(32), meter[common.MemoryKindBigInt]) }) + t.Run("FixedSizeUnsignedInteger", func(t *testing.T) { + t.Parallel() + + script := []byte(` + access(all) fun main(x: FixedSizeUnsignedInteger) {} + `) + + meter := make(map[common.MemoryKind]uint64) + executeScript(t, script, meter, cadence.NewUInt256(2)) + assert.Equal(t, uint64(32), meter[common.MemoryKindBigInt]) + }) + t.Run("Int", func(t *testing.T) { t.Parallel() diff --git a/runtime/sema/checker_test.go b/runtime/sema/checker_test.go index 5c88403d65..a56c67c0f6 100644 --- a/runtime/sema/checker_test.go +++ b/runtime/sema/checker_test.go @@ -57,6 +57,15 @@ func TestOptionalSubtyping(t *testing.T) { ), ) }) + + t.Run("UInt8? <: FixedSizedUnsignedInteger?", func(t *testing.T) { + assert.True(t, + IsSubType( + &OptionalType{Type: UInt8Type}, + &OptionalType{Type: FixedSizeUnsignedIntegerType}, + ), + ) + }) } func TestCompositeType_ID(t *testing.T) { diff --git a/runtime/tests/checker/builtinfunctions_test.go b/runtime/tests/checker/builtinfunctions_test.go index 7df0ede09a..3db3d4f320 100644 --- a/runtime/tests/checker/builtinfunctions_test.go +++ b/runtime/tests/checker/builtinfunctions_test.go @@ -290,7 +290,7 @@ func TestCheckRevertibleRandom(t *testing.T) { }, } - runCase := func(t *testing.T, ty sema.Type, code string) { + runCase := func(t *testing.T, ty sema.Type, code string, options ParseAndCheckOptions) { checker, err := ParseAndCheckWithOptions(t, code, options) require.NoError(t, err) @@ -299,25 +299,25 @@ func TestCheckRevertibleRandom(t *testing.T) { require.Equal(t, ty, resType) } - runValidCaseWithoutModulo := func(t *testing.T, ty sema.Type) { + runValidCaseWithoutModulo := func(t *testing.T, ty sema.Type, options ParseAndCheckOptions) { t.Run(fmt.Sprintf("revertibleRandom<%s>_no_modulo", ty), func(t *testing.T) { t.Parallel() code := fmt.Sprintf("let rand = revertibleRandom<%s>()", ty) - runCase(t, ty, code) + runCase(t, ty, code, options) }) } - runValidCaseWithModulo := func(t *testing.T, ty sema.Type) { + runValidCaseWithModulo := func(t *testing.T, ty sema.Type, options ParseAndCheckOptions) { t.Run(fmt.Sprintf("revertibleRandom<%s>_modulo", ty), func(t *testing.T) { t.Parallel() code := fmt.Sprintf("let rand = revertibleRandom<%[1]s>(modulo: %[1]s(1))", ty) - runCase(t, ty, code) + runCase(t, ty, code, options) }) } - runInvalidCase := func(t *testing.T, testName string, code string, expectedErrors []error) { + runInvalidCase := func(t *testing.T, testName string, code string, options ParseAndCheckOptions, expectedErrors []error) { t.Run(testName, func(t *testing.T) { t.Parallel() @@ -336,19 +336,19 @@ func TestCheckRevertibleRandom(t *testing.T) { continue default: - runValidCaseWithoutModulo(t, ty) - runValidCaseWithModulo(t, ty) + runValidCaseWithoutModulo(t, ty, options) + runValidCaseWithModulo(t, ty, options) } } - runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom()", []error{&sema.TypeMismatchError{}}) - runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom(modulo: \"abcd\")", []error{&sema.TypeMismatchError{}}) - runInvalidCase(t, "missing_argument_label", "let rand = revertibleRandom(UInt256(1))", []error{&sema.MissingArgumentLabelError{}}) - runInvalidCase(t, "incorrect_argument_label", "let rand = revertibleRandom(typo: UInt256(1))", []error{&sema.IncorrectArgumentLabelError{}}) - runInvalidCase(t, "too_many_args", "let rand = revertibleRandom(modulo: UInt256(1), 2, 3)", []error{&sema.ExcessiveArgumentsError{}}) - runInvalidCase(t, "modulo type mismatch", "let rand = revertibleRandom(modulo: UInt128(1))", []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) - runInvalidCase(t, "string modulo", "let rand = revertibleRandom(modulo: \"abcd\")", []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) + runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom()", options, []error{&sema.TypeMismatchError{}}) + runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom(modulo: \"abcd\")", options, []error{&sema.TypeMismatchError{}}) + runInvalidCase(t, "missing_argument_label", "let rand = revertibleRandom(UInt256(1))", options, []error{&sema.MissingArgumentLabelError{}}) + runInvalidCase(t, "incorrect_argument_label", "let rand = revertibleRandom(typo: UInt256(1))", options, []error{&sema.IncorrectArgumentLabelError{}}) + runInvalidCase(t, "too_many_args", "let rand = revertibleRandom(modulo: UInt256(1), 2, 3)", options, []error{&sema.ExcessiveArgumentsError{}}) + runInvalidCase(t, "modulo type mismatch", "let rand = revertibleRandom(modulo: UInt128(1))", options, []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) + runInvalidCase(t, "string modulo", "let rand = revertibleRandom(modulo: \"abcd\")", options, []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) // This is an error since we do not support type inference of function arguments. - runInvalidCase(t, "missing_typeinference", "let rand = revertibleRandom(modulo: 1)", []error{&sema.TypeParameterTypeMismatchError{}}) + runInvalidCase(t, "missing_typeinference", "let rand = revertibleRandom(modulo: 1)", options, []error{&sema.TypeParameterTypeMismatchError{}}) } diff --git a/runtime/tests/checker/casting_test.go b/runtime/tests/checker/casting_test.go index 762d91e598..ac38c74f1b 100644 --- a/runtime/tests/checker/casting_test.go +++ b/runtime/tests/checker/casting_test.go @@ -4442,6 +4442,21 @@ func TestCheckStaticCastElaboration(t *testing.T) { } }) + t.Run("Fixed size unsigned integer literal", func(t *testing.T) { + t.Parallel() + + checker, err := ParseAndCheckWithAny(t, ` + let x = 45 as FixedSizeUnsignedInteger + `) + + require.NoError(t, err) + + require.Len(t, checker.Elaboration.AllStaticCastTypes(), 1) + for _, cast := range checker.Elaboration.AllStaticCastTypes() { // nolint:maprange + assert.Equal(t, sema.FixedSizeUnsignedIntegerType, cast.TargetType) + } + }) + t.Run("Fixed point literal", func(t *testing.T) { t.Parallel() diff --git a/runtime/tests/interpreter/equality_test.go b/runtime/tests/interpreter/equality_test.go index efe2a8d277..567b328791 100644 --- a/runtime/tests/interpreter/equality_test.go +++ b/runtime/tests/interpreter/equality_test.go @@ -225,6 +225,70 @@ func TestInterpretEqualityOnNumericSuperTypes(t *testing.T) { } }) + t.Run("FixedSizeUnsignedInteger subtypes", func(t *testing.T) { + t.Parallel() + + subtypes := []interpreter.StaticType{ + interpreter.PrimitiveStaticTypeUInt8, + interpreter.PrimitiveStaticTypeUInt16, + interpreter.PrimitiveStaticTypeUInt32, + interpreter.PrimitiveStaticTypeUInt64, + interpreter.PrimitiveStaticTypeUInt128, + interpreter.PrimitiveStaticTypeUInt256, + interpreter.PrimitiveStaticTypeWord8, + interpreter.PrimitiveStaticTypeWord16, + interpreter.PrimitiveStaticTypeWord32, + interpreter.PrimitiveStaticTypeWord64, + interpreter.PrimitiveStaticTypeWord128, + interpreter.PrimitiveStaticTypeWord256, + } + + for _, subtype := range subtypes { + rhsType := interpreter.PrimitiveStaticTypeUInt8 + if subtype == rhsType { + rhsType = interpreter.PrimitiveStaticTypeWord128 + } + + for _, op := range operations { + t.Run(fmt.Sprintf("%s,%s", op.String(), subtype.String()), func(t *testing.T) { + + code := fmt.Sprintf(` + fun test(): Bool { + let x: FixedSizeUnsignedInteger = 5 as %s + let y: FixedSizeUnsignedInteger = 2 as %s + return x %s y + }`, + subtype.String(), + rhsType.String(), + op.Symbol(), + ) + + inter := parseCheckAndInterpret(t, code) + + result, err := inter.Invoke("test") + + switch op { + case ast.OperationEqual: + require.NoError(t, err) + assert.Equal(t, interpreter.FalseValue, result) + case ast.OperationNotEqual: + require.NoError(t, err) + assert.Equal(t, interpreter.TrueValue, result) + default: + RequireError(t, err) + + operandError := &interpreter.InvalidOperandsError{} + require.ErrorAs(t, err, operandError) + + assert.Equal(t, op, operandError.Operation) + assert.Equal(t, subtype, operandError.LeftType) + assert.Equal(t, rhsType, operandError.RightType) + } + }) + } + } + }) + t.Run("Fixed point subtypes", func(t *testing.T) { t.Parallel() From 4c928ddef33050b4d8713ee6ba39734eeca6da45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Wed, 6 Dec 2023 15:10:12 -0800 Subject: [PATCH 5/6] fix and improve test --- .../tests/checker/builtinfunctions_test.go | 121 ++++++++++++++---- 1 file changed, 94 insertions(+), 27 deletions(-) diff --git a/runtime/tests/checker/builtinfunctions_test.go b/runtime/tests/checker/builtinfunctions_test.go index 3db3d4f320..1bff1ba334 100644 --- a/runtime/tests/checker/builtinfunctions_test.go +++ b/runtime/tests/checker/builtinfunctions_test.go @@ -280,18 +280,21 @@ func TestCheckRevertibleRandom(t *testing.T) { t.Parallel() - baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) - baseValueActivation.DeclareValue(stdlib.NewRevertibleRandomFunction(&testRandomGenerator{})) - options := ParseAndCheckOptions{ - Config: &sema.Config{ - BaseValueActivationHandler: func(_ common.Location) *sema.VariableActivation { - return baseValueActivation + newOptions := func() ParseAndCheckOptions { + baseValueActivation := sema.NewVariableActivation(sema.BaseValueActivation) + baseValueActivation.DeclareValue(stdlib.NewRevertibleRandomFunction(&testRandomGenerator{})) + return ParseAndCheckOptions{ + Config: &sema.Config{ + BaseValueActivationHandler: func(_ common.Location) *sema.VariableActivation { + return baseValueActivation + }, }, - }, + } } - runCase := func(t *testing.T, ty sema.Type, code string, options ParseAndCheckOptions) { - checker, err := ParseAndCheckWithOptions(t, code, options) + runCase := func(t *testing.T, ty sema.Type, code string) { + + checker, err := ParseAndCheckWithOptions(t, code, newOptions()) require.NoError(t, err) @@ -299,29 +302,29 @@ func TestCheckRevertibleRandom(t *testing.T) { require.Equal(t, ty, resType) } - runValidCaseWithoutModulo := func(t *testing.T, ty sema.Type, options ParseAndCheckOptions) { - t.Run(fmt.Sprintf("revertibleRandom<%s>_no_modulo", ty), func(t *testing.T) { + runValidCaseWithoutModulo := func(t *testing.T, ty sema.Type) { + t.Run(fmt.Sprintf("revertibleRandom<%s>, no modulo", ty), func(t *testing.T) { t.Parallel() code := fmt.Sprintf("let rand = revertibleRandom<%s>()", ty) - runCase(t, ty, code, options) + runCase(t, ty, code) }) } - runValidCaseWithModulo := func(t *testing.T, ty sema.Type, options ParseAndCheckOptions) { - t.Run(fmt.Sprintf("revertibleRandom<%s>_modulo", ty), func(t *testing.T) { + runValidCaseWithModulo := func(t *testing.T, ty sema.Type) { + t.Run(fmt.Sprintf("revertibleRandom<%s>, modulo", ty), func(t *testing.T) { t.Parallel() code := fmt.Sprintf("let rand = revertibleRandom<%[1]s>(modulo: %[1]s(1))", ty) - runCase(t, ty, code, options) + runCase(t, ty, code) }) } - runInvalidCase := func(t *testing.T, testName string, code string, options ParseAndCheckOptions, expectedErrors []error) { + runInvalidCase := func(t *testing.T, testName string, code string, expectedErrors []error) { t.Run(testName, func(t *testing.T) { t.Parallel() - _, err := ParseAndCheckWithOptions(t, code, options) + _, err := ParseAndCheckWithOptions(t, code, newOptions()) errs := RequireCheckerErrors(t, err, len(expectedErrors)) for i := range expectedErrors { @@ -336,19 +339,83 @@ func TestCheckRevertibleRandom(t *testing.T) { continue default: - runValidCaseWithoutModulo(t, ty, options) - runValidCaseWithModulo(t, ty, options) + runValidCaseWithoutModulo(t, ty) + runValidCaseWithModulo(t, ty) } } - runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom()", options, []error{&sema.TypeMismatchError{}}) - runInvalidCase(t, "revertibleRandom", "let rand = revertibleRandom(modulo: \"abcd\")", options, []error{&sema.TypeMismatchError{}}) - runInvalidCase(t, "missing_argument_label", "let rand = revertibleRandom(UInt256(1))", options, []error{&sema.MissingArgumentLabelError{}}) - runInvalidCase(t, "incorrect_argument_label", "let rand = revertibleRandom(typo: UInt256(1))", options, []error{&sema.IncorrectArgumentLabelError{}}) - runInvalidCase(t, "too_many_args", "let rand = revertibleRandom(modulo: UInt256(1), 2, 3)", options, []error{&sema.ExcessiveArgumentsError{}}) - runInvalidCase(t, "modulo type mismatch", "let rand = revertibleRandom(modulo: UInt128(1))", options, []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) - runInvalidCase(t, "string modulo", "let rand = revertibleRandom(modulo: \"abcd\")", options, []error{&sema.TypeParameterTypeMismatchError{}, &sema.TypeMismatchError{}}) + runInvalidCase( + t, + "revertibleRandom", + "let rand = revertibleRandom()", + []error{ + &sema.TypeMismatchError{}, + }, + ) + + runInvalidCase( + t, + "revertibleRandom", + `let rand = revertibleRandom(modulo: "abcd")`, + []error{ + &sema.TypeMismatchError{}, + }, + ) + + runInvalidCase( + t, + "missing_argument_label", + "let rand = revertibleRandom(UInt256(1))", + []error{ + &sema.MissingArgumentLabelError{}, + }, + ) + + runInvalidCase( + t, + "incorrect_argument_label", + "let rand = revertibleRandom(typo: UInt256(1))", + []error{ + &sema.IncorrectArgumentLabelError{}, + }, + ) + + runInvalidCase( + t, + "too_many_args", + "let rand = revertibleRandom(modulo: UInt256(1), 2, 3)", + []error{ + &sema.ExcessiveArgumentsError{}, + }, + ) + + runInvalidCase( + t, + "modulo type mismatch", + "let rand = revertibleRandom(modulo: UInt128(1))", + []error{ + &sema.TypeParameterTypeMismatchError{}, + &sema.TypeMismatchError{}, + }, + ) + + runInvalidCase( + t, + "string modulo", + `let rand = revertibleRandom(modulo: "abcd")`, + []error{ + &sema.TypeParameterTypeMismatchError{}, + &sema.TypeMismatchError{}, + }, + ) // This is an error since we do not support type inference of function arguments. - runInvalidCase(t, "missing_typeinference", "let rand = revertibleRandom(modulo: 1)", options, []error{&sema.TypeParameterTypeMismatchError{}}) + runInvalidCase( + t, + "missing type inference", + "let rand = revertibleRandom(modulo: 1)", + []error{ + &sema.TypeParameterTypeMismatchError{}, + }, + ) } From 901bb55c35abebb4d619f34d6c6503d8a5ae70c0 Mon Sep 17 00:00:00 2001 From: darkdrag00n Date: Thu, 7 Dec 2023 20:59:57 +0530 Subject: [PATCH 6/6] Switch on the sema.type --- runtime/stdlib/random.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/runtime/stdlib/random.go b/runtime/stdlib/random.go index 122415e548..76a813f889 100644 --- a/runtime/stdlib/random.go +++ b/runtime/stdlib/random.go @@ -94,39 +94,38 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue // TODO: Check if invocation has an argument and implement modulo operation. returnIntegerType := invocation.TypeParameterTypes.Oldest().Value - returnIntegerStaticType := interpreter.ConvertSemaToStaticType(inter, returnIntegerType) - switch returnIntegerStaticType { + switch returnIntegerType { // UInt* - case interpreter.PrimitiveStaticTypeUInt8: + case sema.UInt8Type: return interpreter.NewUInt8Value( inter, func() uint8 { return getRandomBytes(generator, 1)[0] }, ) - case interpreter.PrimitiveStaticTypeUInt16: + case sema.UInt16Type: return interpreter.NewUInt16Value( inter, func() uint16 { return binary.BigEndian.Uint16(getRandomBytes(generator, 2)) }, ) - case interpreter.PrimitiveStaticTypeUInt32: + case sema.UInt32Type: return interpreter.NewUInt32Value( inter, func() uint32 { return binary.BigEndian.Uint32(getRandomBytes(generator, 4)) }, ) - case interpreter.PrimitiveStaticTypeUInt64: + case sema.UInt64Type: return interpreter.NewUInt64Value( inter, func() uint64 { return binary.BigEndian.Uint64(getRandomBytes(generator, 8)) }, ) - case interpreter.PrimitiveStaticTypeUInt128: + case sema.UInt128Type: return interpreter.NewUInt128ValueFromBigInt( inter, func() *big.Int { @@ -134,7 +133,7 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue return interpreter.BigEndianBytesToUnsignedBigInt(buffer) }, ) - case interpreter.PrimitiveStaticTypeUInt256: + case sema.UInt256Type: return interpreter.NewUInt256ValueFromBigInt( inter, func() *big.Int { @@ -144,35 +143,35 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue ) // Word* - case interpreter.PrimitiveStaticTypeWord8: + case sema.Word8Type: return interpreter.NewWord8Value( inter, func() uint8 { return getRandomBytes(generator, 1)[0] }, ) - case interpreter.PrimitiveStaticTypeWord16: + case sema.Word16Type: return interpreter.NewWord16Value( inter, func() uint16 { return binary.BigEndian.Uint16(getRandomBytes(generator, 2)) }, ) - case interpreter.PrimitiveStaticTypeWord32: + case sema.Word32Type: return interpreter.NewWord32Value( inter, func() uint32 { return binary.BigEndian.Uint32(getRandomBytes(generator, 4)) }, ) - case interpreter.PrimitiveStaticTypeWord64: + case sema.Word64Type: return interpreter.NewWord64Value( inter, func() uint64 { return binary.BigEndian.Uint64(getRandomBytes(generator, 8)) }, ) - case interpreter.PrimitiveStaticTypeWord128: + case sema.Word128Type: return interpreter.NewWord128ValueFromBigInt( inter, func() *big.Int { @@ -180,7 +179,7 @@ func NewRevertibleRandomFunction(generator RandomGenerator) StandardLibraryValue return interpreter.BigEndianBytesToUnsignedBigInt(buffer) }, ) - case interpreter.PrimitiveStaticTypeWord256: + case sema.Word256Type: return interpreter.NewWord256ValueFromBigInt( inter, func() *big.Int {