RGB-WG / rgb

RGB smart contracts: command-line tool & wallet runtime library for desktop and mobile integration
https://rgb.tech
Apache License 2.0
140 stars 36 forks source link

make ContractText optional or improve error message #9

Closed zoedberg closed 1 year ago

zoedberg commented 1 year ago

I've tried issuing an asset without the ContractText and I received this error:

thread 'main' panicked at 'internal error: failed validating self-issued contract: Consignment { validation_status: Some(Status { unresolved_txids: [], unmined_terminals: [], failures: [SchemaGlobalStateOccurrences(OpId(Array<32>(e67cc09d8f17f2c60a7d7c0e3fa05f36c833fc27c6078cb031bac8cdab922ec2)), 1, OccurrencesMismatch { min: 1, max: 1, found: 0 })], warnings: [], info: [] }), version: V1, transfer: false, schema: Schema { ffv: Ffv(0), subset_of: None, global_types: Confined({0: GlobalStateSchema { sem_id: SemId(Array<32>(2ab484b50de3237b6d9c7ffe119cac7ec4f08d6aac5f16abd61a1a5034f3aba4)), max_items: 1 }, 1: GlobalStateSchema { sem_id: SemId(Array<32>(f0d3a8af463a63cefc4a3a212d49f49137076a787e6f88f986303d0863ddca30)), max_items: 1 }}), owned_types: Confined({0: Fungible(Unsigned64Bit)}), valency_types: Confined({}), genesis: GenesisSchema { metadata: SemId(Array<32>(c6bdee62481531f0f5e0758cda686053c050c4fc4ad1219a5c5b8e5bfdc1b6b1)), globals: Confined({0: Once, 1: Once}), assignments: Confined({0: OnceOrMore}), valencies: Confined({}) }, extensions: Confined({}), transitions: Confined({0: TransitionSchema { metadata: SemId(Array<32>(c6bdee62481531f0f5e0758cda686053c050c4fc4ad1219a5c5b8e5bfdc1b6b1)), globals: Confined({}), inputs: Confined({0: OnceOrMore}), assignments: Confined({0: OnceOrMore}), valencies: Confined({}) }}), type_system: TypeSystem(Confined({SemId(Array<32>(228336739c9b08ca2bf3ac42343d91b1e7b0882c5995ce3daf9d6bf47fd30345)): TypeInfo { fqn: Some(TypeFqn { lib: LibName("RGBContract"), name: TypeName("ContractName") }), ty: Tuple(UnnamedFields(Confined([SemId(Array<32>(e580dccf6f4e623f25eb4378b4d99705736ca36b66661a2c00f8a489e472b7ab))]))) }, SemId(Array<32>(2ab484b50de3237b6d9c7ffe119cac7ec4f08d6aac5f16abd61a1a5034f3aba4)): TypeInfo { fqn: Some(TypeFqn { lib: LibName("RGBContract"), name: TypeName("Nominal") }), ty: Struct(NamedFields(Confined([Field { name: FieldName("ticker"), ty: SemId(Array<32>(92e75ca87a0d45ef319dd973902d8da2d2682e4c7e23df479bfe7be842983506)) }, Field { name: FieldName("name"), ty: SemId(Array<32>(228336739c9b08ca2bf3ac42343d91b1e7b0882c5995ce3daf9d6bf47fd30345)) }, Field { name: FieldName("details"), ty: SemId(Array<32>(365613c0314392f9736b10b036646ff96cea7885a19c19f20dfbd4b664034e4a)) }, Field { name: FieldName("precision"), ty: SemId(Array<32>(ca4347dfc005310a1ae5592b7dd6f3e93645e5231305fbe992ef33ce2cdae31e)) }]))) }, SemId(Array<32>(365613c0314392f9736b10b036646ff96cea7885a19c19f20dfbd4b664034e4a)): TypeInfo { fqn: None, ty: Union(UnionVariants(Confined({Variant { name: FieldName("none"), tag: 0 }: SemId(Array<32>(c6bdee62481531f0f5e0758cda686053c050c4fc4ad1219a5c5b8e5bfdc1b6b1)), Variant { name: FieldName("some"), tag: 1 }: SemId(Array<32>(d0a0bacb5647452dc535ab3a9535a699a55fa86ff239129719bf2e5004639414))}))) }, SemId(Array<32>(3e558ffa0f0c38c22b61be4d110b893694d51c534c706f348af313251ec90336)): TypeInfo { fqn: None, ty: List(SemId(Array<32>(61cd903df3b4fbb4d828d35c53f976e3f81dc9e11820b2aa76661e4d28a25510)), Sizing { min: 0, max: 65535 }) }, SemId(Array<32>(446fbb71b827037e6df7f81d838288365e152ba4dc406d6a43920dc98a6c6f25)): TypeInfo { fqn: None, ty: List(SemId(Array<32>(61cd903df3b4fbb4d828d35c53f976e3f81dc9e11820b2aa76661e4d28a25510)), Sizing { min: 40, max: 255 }) }, SemId(Array<32>(5577ee213895eed3a4a4e822db7cf6078f4b5e20d77270ba3c10bf8973c6cd4b)): TypeInfo { fqn: None, ty: Enum(EnumVariants(Confined({Variant { name: FieldName("_32"), tag: 32 }, Variant { name: FieldName("_33"), tag: 33 }, Variant { name: FieldName("_34"), tag: 34 }, Variant { name: FieldName("_35"), tag: 35 }, Variant { name: FieldName("_36"), tag: 36 }, Variant { name: FieldName("_37"), tag: 37 }, Variant { name: FieldName("_38"), tag: 38 }, Variant { name: FieldName("_39"), tag: 39 }, Variant { name: FieldName("_40"), tag: 40 }, Variant { name: FieldName("_41"), tag: 41 }, Variant { name: FieldName("_42"), tag: 42 }, Variant { name: FieldName("_43"), tag: 43 }, Variant { name: FieldName("_44"), tag: 44 }, Variant { name: FieldName("_45"), tag: 45 }, Variant { name: FieldName("_46"), tag: 46 }, Variant { name: FieldName("_47"), tag: 47 }, Variant { name: FieldName("_48"), tag: 48 }, Variant { name: FieldName("_49"), tag: 49 }, Variant { name: FieldName("_50"), tag: 50 }, Variant { name: FieldName("_51"), tag: 51 }, Variant { name: FieldName("_52"), tag: 52 }, Variant { name: FieldName("_53"), tag: 53 }, Variant { name: FieldName("_54"), tag: 54 }, Variant { name: FieldName("_55"), tag: 55 }, Variant { name: FieldName("_56"), tag: 56 }, Variant { name: FieldName("_57"), tag: 57 }, Variant { name: FieldName("_58"), tag: 58 }, Variant { name: FieldName("_59"), tag: 59 }, Variant { name: FieldName("_60"), tag: 60 }, Variant { name: FieldName("_61"), tag: 61 }, Variant { name: FieldName("_62"), tag: 62 }, Variant { name: FieldName("_63"), tag: 63 }, Variant { name: FieldName("_64"), tag: 64 }, Variant { name: FieldName("_65"), tag: 65 }, Variant { name: FieldName("_66"), tag: 66 }, Variant { name: FieldName("_67"), tag: 67 }, Variant { name: FieldName("_68"), tag: 68 }, Variant { name: FieldName("_69"), tag: 69 }, Variant { name: FieldName("_70"), tag: 70 }, Variant { name: FieldName("_71"), tag: 71 }, Variant { name: FieldName("_72"), tag: 72 }, Variant { name: FieldName("_73"), tag: 73 }, Variant { name: FieldName("_74"), tag: 74 }, Variant { name: FieldName("_75"), tag: 75 }, Variant { name: FieldName("_76"), tag: 76 }, Variant { name: FieldName("_77"), tag: 77 }, Variant { name: FieldName("_78"), tag: 78 }, Variant { name: FieldName("_79"), tag: 79 }, Variant { name: FieldName("_80"), tag: 80 }, Variant { name: FieldName("_81"), tag: 81 }, Variant { name: FieldName("_82"), tag: 82 }, Variant { name: FieldName("_83"), tag: 83 }, Variant { name: FieldName("_84"), tag: 84 }, Variant { name: FieldName("_85"), tag: 85 }, Variant { name: FieldName("_86"), tag: 86 }, Variant { name: FieldName("_87"), tag: 87 }, Variant { name: FieldName("_88"), tag: 88 }, Variant { name: FieldName("_89"), tag: 89 }, Variant { name: FieldName("_90"), tag: 90 }, Variant { name: FieldName("_91"), tag: 91 }, Variant { name: FieldName("_92"), tag: 92 }, Variant { name: FieldName("_93"), tag: 93 }, Variant { name: FieldName("_94"), tag: 94 }, Variant { name: FieldName("_95"), tag: 95 }, Variant { name: FieldName("_96"), tag: 96 }, Variant { name: FieldName("_97"), tag: 97 }, Variant { name: FieldName("_98"), tag: 98 }, Variant { name: FieldName("_99"), tag: 99 }, Variant { name: FieldName("_100"), tag: 100 }, Variant { name: FieldName("_101"), tag: 101 }, Variant { name: FieldName("_102"), tag: 102 }, Variant { name: FieldName("_103"), tag: 103 }, Variant { name: FieldName("_104"), tag: 104 }, Variant { name: FieldName("_105"), tag: 105 }, Variant { name: FieldName("_106"), tag: 106 }, Variant { name: FieldName("_107"), tag: 107 }, Variant { name: FieldName("_108"), tag: 108 }, Variant { name: FieldName("_109"), tag: 109 }, Variant { name: FieldName("_110"), tag: 110 }, Variant { name: FieldName("_111"), tag: 111 }, Variant { name: FieldName("_112"), tag: 112 }, Variant { name: FieldName("_113"), tag: 113 }, Variant { name: FieldName("_114"), tag: 114 }, Variant { name: FieldName("_115"), tag: 115 }, Variant { name: FieldName("_116"), tag: 116 }, Variant { name: FieldName("_117"), tag: 117 }, Variant { name: FieldName("_118"), tag: 118 }, Variant { name: FieldName("_119"), tag: 119 }, Variant { name: FieldName("_120"), tag: 120 }, Variant { name: FieldName("_121"), tag: 121 }, Variant { name: FieldName("_122"), tag: 122 }, Variant { name: FieldName("_123"), tag: 123 }, Variant { name: FieldName("_124"), tag: 124 }, Variant { name: FieldName("_125"), tag: 125 }, Variant { name: FieldName("_126"), tag: 126 }, Variant { name: FieldName("_127"), tag: 127 }}))) }, SemId(Array<32>(5cd0c3c0db677e225d50c0cd55a38fd2a79d3a29d625e34f78dfd6166c3cb806)): TypeInfo { fqn: None, ty: List(SemId(Array<32>(5577ee213895eed3a4a4e822db7cf6078f4b5e20d77270ba3c10bf8973c6cd4b)), Sizing { min: 1, max: 8 }) }, SemId(Array<32>(61cd903df3b4fbb4d828d35c53f976e3f81dc9e11820b2aa76661e4d28a25510)): TypeInfo { fqn: None, ty: UnicodeChar }, SemId(Array<32>(6fc6963706a108342019e8f169da7ef48a8f43c8a818832446f3ee17a8b539bc)): TypeInfo { fqn: Some(TypeFqn { lib: LibName("RGBContract"), name: TypeName("ContractDetails") }), ty: Tuple(UnnamedFields(Confined([SemId(Array<32>(446fbb71b827037e6df7f81d838288365e152ba4dc406d6a43920dc98a6c6f25))]))) }, SemId(Array<32>(92e75ca87a0d45ef319dd973902d8da2d2682e4c7e23df479bfe7be842983506)): TypeInfo { fqn: Some(TypeFqn { lib: LibName("RGBContract"), name: TypeName("Ticker") }), ty: Tuple(UnnamedFields(Confined([SemId(Array<32>(5cd0c3c0db677e225d50c0cd55a38fd2a79d3a29d625e34f78dfd6166c3cb806))]))) }, SemId(Array<32>(c6bdee62481531f0f5e0758cda686053c050c4fc4ad1219a5c5b8e5bfdc1b6b1)): TypeInfo { fqn: None, ty: Primitive(Primitive(0)) }, SemId(Array<32>(ca4347dfc005310a1ae5592b7dd6f3e93645e5231305fbe992ef33ce2cdae31e)): TypeInfo { fqn: Some(TypeFqn { lib: LibName("RGBContract"), name: TypeName("Precision") }), ty: Enum(EnumVariants(Confined({Variant { name: FieldName("indivisible"), tag: 0 }, Variant { name: FieldName("deci"), tag: 1 }, Variant { name: FieldName("centi"), tag: 2 }, Variant { name: FieldName("milli"), tag: 3 }, Variant { name: FieldName("micro"), tag: 6 }, Variant { name: FieldName("deciMicro"), tag: 7 }, Variant { name: FieldName("centiMicro"), tag: 8 }, Variant { name: FieldName("nano"), tag: 9 }, Variant { name: FieldName("deciNano"), tag: 10 }, Variant { name: FieldName("centiNano"), tag: 11 }, Variant { name: FieldName("pico"), tag: 12 }, Variant { name: FieldName("deciPico"), tag: 13 }, Variant { name: FieldName("centiPico"), tag: 14 }, Variant { name: FieldName("femto"), tag: 15 }, Variant { name: FieldName("deciFemto"), tag: 16 }, Variant { name: FieldName("centiFemto"), tag: 17 }, Variant { name: FieldName("atto"), tag: 18 }}))) }, SemId(Array<32>(d0a0bacb5647452dc535ab3a9535a699a55fa86ff239129719bf2e5004639414)): TypeInfo { fqn: None, ty: Tuple(UnnamedFields(Confined([SemId(Array<32>(6fc6963706a108342019e8f169da7ef48a8f43c8a818832446f3ee17a8b539bc))]))) }, SemId(Array<32>(e580dccf6f4e623f25eb4378b4d99705736ca36b66661a2c00f8a489e472b7ab)): TypeInfo { fqn: None, ty: List(SemId(Array<32>(61cd903df3b4fbb4d828d35c53f976e3f81dc9e11820b2aa76661e4d28a25510)), Sizing { min: 5, max: 40 }) }, SemId(Array<32>(f0d3a8af463a63cefc4a3a212d49f49137076a787e6f88f986303d0863ddca30)): TypeInfo { fqn: Some(TypeFqn { lib: LibName("RGBContract"), name: TypeName("ContractText") }), ty: Tuple(UnnamedFields(Confined([SemId(Array<32>(3e558ffa0f0c38c22b61be4d110b893694d51c534c706f348af313251ec90336))]))) }})), script: AluVM(AluScript { libs: Confined({LibId(Array<32>(0e27a1ddfa53b021015034df8a038caa840d9d651fd22b6aa6f892966adf567e)): Lib { isae: IsaSeg({"RGB"}), code: ByteStr("d00000"), data: ByteStr(""), libs: LibSeg { set: {}, table: {} } }}), entry_points: Confined({ValidateOwnedState(0): LibSite { lib: LibId(Array<32>(0e27a1ddfa53b021015034df8a038caa840d9d651fd22b6aa6f892966adf567e)), pos: 0 }}) }) }, ifaces: Confined({IfaceId(Array<32>(96b4abb5794e7ef3bed670977356daf1260412e229bdb041eace77f1d88614bf)): IfacePair { iface: Iface { version: V1, name: TypeName("RGB20"), global_state: Confined({TypeName("ContractText"): Req { info: Typed(SemId(Array<32>(f0d3a8af463a63cefc4a3a212d49f49137076a787e6f88f986303d0863ddca30))), required: true }, TypeName("Nominal"): Req { info: Typed(SemId(Array<32>(2ab484b50de3237b6d9c7ffe119cac7ec4f08d6aac5f16abd61a1a5034f3aba4))), required: true }}), assignments: Confined({TypeName("Assets"): AssignIface { public: false, owned_state: Amount }}), valencies: Confined({}), genesis: GenesisIface { metadata: None, global: Confined({TypeName("ContractText"): Once, TypeName("Nominal"): Once}), assignments: Confined({TypeName("Assets"): OnceOrMore}), valencies: Confined({}) }, transitions: Confined({TypeName("Transfer"): TransitionIface { metadata: None, globals: Confined({}), inputs: Confined({TypeName("Assets"): OnceOrMore}), assignments: Confined({TypeName("Assets"): OnceOrMore}), valencies: Confined({}), default_assignment: Some(TypeName("Assets")) }}), extensions: Confined({}), default_operation: Some(TypeName("Transfer")) }, iimpl: IfaceImpl { version: V1, schema_id: SchemaId(Array<32>(36d5a42aca71a4032167d37384a5e89bc314991a46f8a69381b4887dbcc8684f)), iface_id: IfaceId(Array<32>(96b4abb5794e7ef3bed670977356daf1260412e229bdb041eace77f1d88614bf)), global_state: Confined({NamedType { id: 0, name: TypeName("Nominal") }, NamedType { id: 1, name: TypeName("ContractText") }}), assignments: Confined({NamedType { id: 0, name: TypeName("Assets") }}), valencies: Confined({}), transitions: Confined({NamedType { id: 0, name: TypeName("Transfer") }}), extensions: Confined({}) } }}), supplements: Confined({}), genesis: Genesis { ffv: Ffv(0), schema_id: SchemaId(Array<32>(36d5a42aca71a4032167d37384a5e89bc314991a46f8a69381b4887dbcc8684f)), chain: Regtest, metadata: Confined([]), globals: GlobalState(Confined({0: GlobalValues(Confined([RevealedData("\u{4}USDT\nUSD Tether\0\0")]))})), assignments: Assignments(Confined({0: Fungible(Confined([Revealed { seal: BlindSeal { method: OpretFirst, txid: Txid("8d455eb2147a3bd3c6c30390d76653b025ff599b1b5c64afbfa19d9e0271759e"), vout: Vout(0), blinding: 18219531870053859832 }, state: RevealedValue { value: Bits64(2000), blinding: BlindingFactor(Array<32>(d20a0500378b1d37f55d56369d7890fc5e40143d257cc13169f5c6f2ad87bac6)) } }]))})), valencies: Confined({}) }, terminals: Confined({}), bundles: Confined([]), extensions: Confined([]), attachments: Confined({}), signatures: Confined({}) }', src/bin/rgb/command.rs:490:22

I'm wondering what's the reason to make ContractText mandatory. @dr-orlovsky can it be made optional?

Anyway, if it stays mandatory I think that the error message could be improved.

dr-orlovsky commented 1 year ago

It is mandatory since there is no difference between empty contract and absent contract. Just do contract text zero-length.

If we make it non-mandatory, than we need to put minimum length requirement of 1 character, which is less straighforward.

The error should be improved anyway, yes