From de0a197b2ffcec7af804936d96e82f63344798a7 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Thu, 20 Nov 2025 11:24:26 +0000 Subject: [PATCH 01/17] wip: Add ed25519 signature validation --- src/ar_bundles.erl | 16 ++++++++++++---- src/ar_wallet.erl | 14 +++++++++++++- src/dev_codec_tx.erl | 2 +- src/hb_gateway_client.erl | 1 + 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index 3f070b54a..b29c59221 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -97,6 +97,10 @@ verify_item(DataItem) -> ValidID = verify_data_item_id(DataItem), ValidSignature = verify_data_item_signature(DataItem), ValidTags = verify_data_item_tags(DataItem), + ?event({verify_item, + {id, ValidID}, + {signature, ValidSignature}, + {tags, ValidTags}}), ValidID andalso ValidSignature andalso ValidTags. %%%=================================================================== @@ -129,7 +133,7 @@ enforce_valid_tx(TX) -> {invalid_field, anchor, TX#tx.anchor} ), hb_util:ok_or_throw(TX, - hb_util:check_size(TX#tx.owner, [0, byte_size(?DEFAULT_OWNER)]), + hb_util:check_size(TX#tx.owner, [0, 32, byte_size(?DEFAULT_OWNER)]), {invalid_field, owner, TX#tx.owner} ), hb_util:ok_or_throw(TX, @@ -137,7 +141,7 @@ enforce_valid_tx(TX) -> {invalid_field, target, TX#tx.target} ), hb_util:ok_or_throw(TX, - hb_util:check_size(TX#tx.signature, [0, 65, byte_size(?DEFAULT_SIG)]), + hb_util:check_size(TX#tx.signature, [0, 64, 65, byte_size(?DEFAULT_SIG)]), {invalid_field, signature, TX#tx.signature} ), hb_util:ok_or_throw(TX, @@ -184,8 +188,7 @@ data_item_signature_data(RawItem) -> ar_deep_hash:hash([ utf8_encoded("dataitem"), utf8_encoded("1"), - %% Only SignatureType 1 is supported for now (RSA 4096) - utf8_encoded("1"), + utf8_encoded(get_signature_type(Item#tx.signature_type)), <<(Item#tx.owner)/binary>>, <<(Item#tx.target)/binary>>, <<(Item#tx.anchor)/binary>>, @@ -193,6 +196,11 @@ data_item_signature_data(RawItem) -> <<(Item#tx.data)/binary>> ]). +get_signature_type({rsa, 65537}) -> <<"1">>; +get_signature_type(ed25519) -> <<"2">>; +get_signature_type(solana) -> <<"4">>; +get_signature_type(injected_aptos) -> <<"5">>. + %% @doc Verify the data item's ID matches the signature. verify_data_item_id(DataItem) -> ExpectedID = crypto:hash(sha256, DataItem#tx.signature), diff --git a/src/ar_wallet.erl b/src/ar_wallet.erl index 4bff3d6f7..2fbe622fb 100644 --- a/src/ar_wallet.erl +++ b/src/ar_wallet.erl @@ -57,7 +57,19 @@ verify({{rsa, PublicExpnt}, Pub}, Data, Sig, DigestType) when PublicExpnt =:= 65 publicExponent = PublicExpnt, modulus = binary:decode_unsigned(Pub) } - ). + ); +verify({ed25519, PubKey}, Data, Sig, _DigestType) when + byte_size(PubKey) == 32 andalso byte_size(Sig) == 64 -> + public_key:verify(Data, ignored, Sig, {ed_pub, ed25519, PubKey}); +verify({solana, PubKey}, Data, Sig, _DigestType) when + byte_size(PubKey) == 32 andalso byte_size(Sig) == 64 -> + public_key:verify(Data, ignored, Sig, {ed_pub, ed25519, PubKey}); +verify({injected_aptos, PubKey}, Data, Sig, _DigestType) when + byte_size(PubKey) == 32 andalso byte_size(Sig) == 64 -> + Nonce = <<"bundlr">>, + DataHex = binary:encode_hex(Data, lowercase), + Message = <<"APTOS", 0, "message: ", 0, DataHex/binary, 0, "nonce: ", Nonce/binary>>, + public_key:verify(Message, ignored, Sig, {ed_pub, ed25519, PubKey}). %% @doc Find a public key from a wallet. to_pubkey(Pubkey) -> diff --git a/src/dev_codec_tx.erl b/src/dev_codec_tx.erl index 3363969d2..8e07ec376 100644 --- a/src/dev_codec_tx.erl +++ b/src/dev_codec_tx.erl @@ -218,7 +218,7 @@ enforce_valid_tx(TX) -> {invalid_field, data_root, TX#tx.data_root} ), hb_util:ok_or_throw(TX, - hb_util:check_size(TX#tx.signature, [65, byte_size(?DEFAULT_SIG)]), + hb_util:check_size(TX#tx.signature, [64, 65, byte_size(?DEFAULT_SIG)]), {invalid_field, signature, TX#tx.signature} ), hb_util:ok_or_throw(TX, diff --git a/src/hb_gateway_client.erl b/src/hb_gateway_client.erl index 7f4edf061..7434c0738 100644 --- a/src/hb_gateway_client.erl +++ b/src/hb_gateway_client.erl @@ -257,6 +257,7 @@ result_to_message(ExpectedID, Item, Opts) -> ), SignatureType = case byte_size(Signature) of + 64 -> ed25519; 65 -> {ecdsa, 256}; 512 -> {rsa, 65537}; _ -> unsupported_tx_signature_type From 12059a2f6023fc9146af23e4b57edcbe2b533b52 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Wed, 26 Nov 2025 18:22:36 +0000 Subject: [PATCH 02/17] fix: Remove solana and injected_aptos --- src/ar_bundles.erl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index b29c59221..191ee3178 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -196,10 +196,8 @@ data_item_signature_data(RawItem) -> <<(Item#tx.data)/binary>> ]). -get_signature_type({rsa, 65537}) -> <<"1">>; -get_signature_type(ed25519) -> <<"2">>; -get_signature_type(solana) -> <<"4">>; -get_signature_type(injected_aptos) -> <<"5">>. +get_signature_type({rsa, 65537}) -> "1"; +get_signature_type(ed25519) -> "2". %% @doc Verify the data item's ID matches the signature. verify_data_item_id(DataItem) -> From cadd5dbc3734149a36bf463bad23a08c2a8958c2 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Wed, 26 Nov 2025 21:18:26 +0000 Subject: [PATCH 03/17] fix: Add sign capability, add test to data item --- src/ar_bundles.erl | 6 +----- src/ar_tx.erl | 24 ++++++++++++++++++++++++ src/ar_wallet.erl | 33 ++++++++++++++++++--------------- src/hb_gateway_client.erl | 2 +- 4 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index 191ee3178..ab5f87b89 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -97,10 +97,6 @@ verify_item(DataItem) -> ValidID = verify_data_item_id(DataItem), ValidSignature = verify_data_item_signature(DataItem), ValidTags = verify_data_item_tags(DataItem), - ?event({verify_item, - {id, ValidID}, - {signature, ValidSignature}, - {tags, ValidTags}}), ValidID andalso ValidSignature andalso ValidTags. %%%=================================================================== @@ -197,7 +193,7 @@ data_item_signature_data(RawItem) -> ]). get_signature_type({rsa, 65537}) -> "1"; -get_signature_type(ed25519) -> "2". +get_signature_type({eddsa, ed25519}) -> "2". %% @doc Verify the data item's ID matches the signature. verify_data_item_id(DataItem) -> diff --git a/src/ar_tx.erl b/src/ar_tx.erl index 205bb85a8..ae4de9874 100644 --- a/src/ar_tx.erl +++ b/src/ar_tx.erl @@ -836,3 +836,27 @@ tx_to_json_struct_failure_test() -> end, FailureCases ). + +%% TODO: Move to the proper place +ed25519_verify_valid_test() -> + application:ensure_all_started(hb), + ID = <<"1rTy7gQuK9lJydlKqCEhtGLp2WWG-GOrVo5JdiCmaxs">>, + {ok, Data} = hb_gateway_client:data(ID, #{}), + PublicKey = <<42,183,56,140,176,233,209,5,127,163,72,53,49,236,186,130,211,130,140,225,211,232,192,141,45,12,157,249,161,137,243,82>>, + Anchor = <<"ZbExyvGrJKOJTJcHMtKzoOZVCQBkjZ+5">>, + Signature = <<195,61,110,250,0,176,46,214,165,148,100,201,169,114,248,103,197,128,202,114,63,81,94,116,107,255,65,7,68,173,199,26,58,68,236,61,193,62,61,52,131,1,254,201,159,40,41,69,220,171,220,63,189,140,40,102,164,20,75,145,199,246,231,8>>, + TX = dev_arweave_common:reset_ids(#tx{ + format = 1, + signature_type = {eddsa, ed25519}, + signature = Signature, + owner = PublicKey, + target = <<>>, + anchor = Anchor, + data = Data, + data_size = byte_size(Data), + tags = [{<<"Content-Type">>,<<"image/png">>}] + }), + ?assert(ar_bundles:verify_item(TX), TX#tx.format). + %% verifysignature does work becasue it is for a proper TX not an Data Item + %?assert(verify_signature(TX), TX#tx.format), + %%?assert(verify(TX), TX#tx.format), diff --git a/src/ar_wallet.erl b/src/ar_wallet.erl index 2fbe622fb..a92cd925c 100644 --- a/src/ar_wallet.erl +++ b/src/ar_wallet.erl @@ -17,8 +17,10 @@ new() -> new(KeyType = {KeyAlg, PublicExpnt}) when KeyType =:= {rsa, 65537} -> {[_, Pub], [_, Pub, Priv|_]} = {[_, Pub], [_, Pub, Priv|_]} = crypto:generate_key(KeyAlg, {4096, PublicExpnt}), - {{KeyType, Priv, Pub}, {KeyType, Pub}}. - + {{KeyType, Priv, Pub}, {KeyType, Pub}}; +new(KeyType = {KeyAlg, Curve}) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> + {Priv, Pub} = crypto:generate_key(KeyAlg, Curve), + {{KeyType, Priv, Pub},{KeyType, Pub}}. %% @doc Sign some data with a private key. sign(Key, Data) -> @@ -36,6 +38,8 @@ sign({{rsa, PublicExpnt}, Priv, Pub}, Data, DigestType) when PublicExpnt =:= 655 privateExponent = binary:decode_unsigned(Priv) } ); +sign({KeyType = {_KeyAlg, Curve}, Priv, _Pub}, Data, DigestType) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> + crypto:sign(Curve, DigestType, Data, Priv); sign({{KeyType, Priv, Pub}, {KeyType, Pub}}, Data, DigestType) -> sign({KeyType, Priv, Pub}, Data, DigestType). @@ -58,18 +62,11 @@ verify({{rsa, PublicExpnt}, Pub}, Data, Sig, DigestType) when PublicExpnt =:= 65 modulus = binary:decode_unsigned(Pub) } ); -verify({ed25519, PubKey}, Data, Sig, _DigestType) when - byte_size(PubKey) == 32 andalso byte_size(Sig) == 64 -> - public_key:verify(Data, ignored, Sig, {ed_pub, ed25519, PubKey}); -verify({solana, PubKey}, Data, Sig, _DigestType) when - byte_size(PubKey) == 32 andalso byte_size(Sig) == 64 -> - public_key:verify(Data, ignored, Sig, {ed_pub, ed25519, PubKey}); -verify({injected_aptos, PubKey}, Data, Sig, _DigestType) when - byte_size(PubKey) == 32 andalso byte_size(Sig) == 64 -> - Nonce = <<"bundlr">>, - DataHex = binary:encode_hex(Data, lowercase), - Message = <<"APTOS", 0, "message: ", 0, DataHex/binary, 0, "nonce: ", Nonce/binary>>, - public_key:verify(Message, ignored, Sig, {ed_pub, ed25519, PubKey}). +verify({{eddsa, ed25519}, Pub}, Data, Sig, _DigestType) when + byte_size(Pub) == 32 andalso byte_size(Sig) == 64 -> + %public_key:verify(Data, DigestType, Sig, {ed_pub, ed25519, Pub}). + crypto:verify(eddsa, none, Data, Sig, [Pub, ed25519]). + %% @doc Find a public key from a wallet. to_pubkey(Pubkey) -> @@ -93,7 +90,9 @@ to_address({{_, _, PubKey}, {_, PubKey}}, _) -> to_address(PubKey, {rsa, 65537}) -> to_rsa_address(PubKey); to_address(PubKey, {ecdsa, 256}) -> - to_ecdsa_address(PubKey). + to_ecdsa_address(PubKey); +to_address(PubKey, {eddsa, ed25519}) -> + arweave_ao_address(PubKey). %% @doc Generate a new wallet public and private key, with a corresponding keyfile. %% The provided key is used as part of the file name. @@ -242,6 +241,10 @@ hash_address(PubKey) -> to_ecdsa_address(PubKey) -> hb_keccak:key_to_ethereum_address(PubKey). +arweave_ao_address(PubKey) -> + Hash = crypto:hash(sha256, PubKey), + base64:encode(Hash, #{padding => false, mode => urlsafe}). + %%%=================================================================== %%% Private functions. %%%=================================================================== diff --git a/src/hb_gateway_client.erl b/src/hb_gateway_client.erl index 7434c0738..1ec57645d 100644 --- a/src/hb_gateway_client.erl +++ b/src/hb_gateway_client.erl @@ -257,7 +257,7 @@ result_to_message(ExpectedID, Item, Opts) -> ), SignatureType = case byte_size(Signature) of - 64 -> ed25519; + 64 -> {eddsa, ed25519}; 65 -> {ecdsa, 256}; 512 -> {rsa, 65537}; _ -> unsupported_tx_signature_type From 3240eeda9b380d7568175ac92e5c70d4fe46fa5b Mon Sep 17 00:00:00 2001 From: speeddragon Date: Thu, 27 Nov 2025 13:39:39 +0000 Subject: [PATCH 04/17] fix: ed25519 sign and verify --- src/ar_bundles.erl | 21 +++++++++++++++++++++ src/ar_wallet.erl | 16 ++++++++-------- src/include/ar.hrl | 3 ++- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index ab5f87b89..ab7847d24 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -318,6 +318,8 @@ to_serialized_pair(Item, false, Signed) -> %% little-endian format which is why we encode to `<<1, 0>>'. encode_signature_type({rsa, 65537}) -> <<1, 0>>; +encode_signature_type({eddsa, ed25519}) -> + <<2, 0>>; encode_signature_type(_) -> unsupported_tx_format. @@ -500,6 +502,8 @@ decode_bundle_header(Count, <>'. decode_signature(<<1, 0, Signature:512/binary, Owner:512/binary, Rest/binary>>) -> {{rsa, 65537}, Signature, Owner, Rest}; +decode_signature(<<2, 0, Signature:64/binary, Owner:32/binary, Rest/binary>>) -> + {{eddsa, ed25519}, Signature, Owner, Rest}; decode_signature(Other) -> ?event({error_decoding_signature, {sig_type, {explicit, binary:part(Other, 0, 2)}}, @@ -751,6 +755,23 @@ bundle_map_test() -> ?assertEqual(Item1#tx.data, (maps:get(<<"key1">>, BundleItem#tx.data))#tx.data), ?assert(verify_item(BundleItem)). +bundle_map_with_eddsa_test() -> + W = ar_wallet:new(?EDDSA_KEY_TYPE), + Item1 = sign_item(#tx{ + format = ans104, + data = <<"item1_data">> + }, W), + Item2 = sign_item(#tx{ + format = ans104, + anchor = crypto:strong_rand_bytes(32), + data = #{<<"key1">> => Item1} + }, W), + Bundle = serialize(dev_arweave_common:normalize(Item2)), + BundleItem = deserialize(Bundle), + ?assertEqual(Item1#tx.data, (maps:get(<<"key1">>, BundleItem#tx.data))#tx.data), + ?assert(verify_item(BundleItem)). + + extremely_large_bundle_test() -> W = ar_wallet:new(), Data = crypto:strong_rand_bytes(100_000_000), diff --git a/src/ar_wallet.erl b/src/ar_wallet.erl index a92cd925c..a7f072060 100644 --- a/src/ar_wallet.erl +++ b/src/ar_wallet.erl @@ -19,8 +19,9 @@ new(KeyType = {KeyAlg, PublicExpnt}) when KeyType =:= {rsa, 65537} -> = crypto:generate_key(KeyAlg, {4096, PublicExpnt}), {{KeyType, Priv, Pub}, {KeyType, Pub}}; new(KeyType = {KeyAlg, Curve}) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> - {Priv, Pub} = crypto:generate_key(KeyAlg, Curve), - {{KeyType, Priv, Pub},{KeyType, Pub}}. + {Pub, Priv} = crypto:generate_key(KeyAlg, Curve), + {{KeyType, Priv, Pub}, {KeyType, Pub}}. + %{{ed_pri, Curve, Pub, Priv}, {ed_pub, Curve, Pub}}. %% @doc Sign some data with a private key. sign(Key, Data) -> @@ -38,8 +39,8 @@ sign({{rsa, PublicExpnt}, Priv, Pub}, Data, DigestType) when PublicExpnt =:= 655 privateExponent = binary:decode_unsigned(Priv) } ); -sign({KeyType = {_KeyAlg, Curve}, Priv, _Pub}, Data, DigestType) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> - crypto:sign(Curve, DigestType, Data, Priv); +sign({KeyType = {KeyAlg, Curve}, Priv, _Pub}, Data, DigestType) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> + crypto:sign(KeyAlg, DigestType, Data, [Priv, Curve]); sign({{KeyType, Priv, Pub}, {KeyType, Pub}}, Data, DigestType) -> sign({KeyType, Priv, Pub}, Data, DigestType). @@ -62,10 +63,9 @@ verify({{rsa, PublicExpnt}, Pub}, Data, Sig, DigestType) when PublicExpnt =:= 65 modulus = binary:decode_unsigned(Pub) } ); -verify({{eddsa, ed25519}, Pub}, Data, Sig, _DigestType) when - byte_size(Pub) == 32 andalso byte_size(Sig) == 64 -> - %public_key:verify(Data, DigestType, Sig, {ed_pub, ed25519, Pub}). - crypto:verify(eddsa, none, Data, Sig, [Pub, ed25519]). +verify({{eddsa, Curve}, Pub}, Data, Sig, _DigestType) when + byte_size(Pub) == 32 andalso byte_size(Sig) == 64 andalso Curve =:= ed25519 -> + crypto:verify(eddsa, none, Data, Sig, [Pub, Curve]). %% @doc Find a public key from a wallet. diff --git a/src/include/ar.hrl b/src/include/ar.hrl index 751acef95..636479292 100644 --- a/src/include/ar.hrl +++ b/src/include/ar.hrl @@ -97,10 +97,11 @@ -define(ECDSA_SIGN_ALG, ecdsa). -define(ECDSA_TYPE_BYTE, <<2>>). +-define(ECDSA_KEY_TYPE, {?ECDSA_SIGN_ALG, secp256k1}). -define(EDDSA_SIGN_ALG, eddsa). -define(EDDSA_TYPE_BYTE, <<3>>). --define(ECDSA_KEY_TYPE, {?ECDSA_SIGN_ALG, secp256k1}). +-define(EDDSA_KEY_TYPE, {?EDDSA_SIGN_ALG, ed25519}). %% The default key type used by transactions that do not specify a signature type. -define(DEFAULT_KEY_TYPE, ?RSA_KEY_TYPE). From 0021a2b0b063dbfdf32d79f0495508ef4c90a19c Mon Sep 17 00:00:00 2001 From: speeddragon Date: Thu, 27 Nov 2025 14:15:29 +0000 Subject: [PATCH 05/17] test: Remove test --- src/ar_tx.erl | 32 +++++--------------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/src/ar_tx.erl b/src/ar_tx.erl index ae4de9874..07eba967f 100644 --- a/src/ar_tx.erl +++ b/src/ar_tx.erl @@ -313,8 +313,10 @@ tx_to_json_struct( data_root = DataRoot, denomination = Denomination }) -> - %% Only RSA supported for now - ?RSA_KEY_TYPE = SigType, + hb_util:ok_or_throw(SigType, + lists:member(SigType, [?RSA_KEY_TYPE, ?EDDSA_KEY_TYPE]), + {invalid_signature_type, SigType} + ), Fields = [ {<<"format">>, case Format of @@ -709,7 +711,7 @@ tx_to_json_struct_happy_test() -> id = crypto:strong_rand_bytes(32), anchor = crypto:strong_rand_bytes(32), owner = Owner, - signature_type = ?RSA_KEY_TYPE, + signature_type = ?EDDSA_KEY_TYPE, owner_address = ar_wallet:to_address(Owner, ?RSA_KEY_TYPE), %% Not in JSON tags = [], target = <<>>, @@ -836,27 +838,3 @@ tx_to_json_struct_failure_test() -> end, FailureCases ). - -%% TODO: Move to the proper place -ed25519_verify_valid_test() -> - application:ensure_all_started(hb), - ID = <<"1rTy7gQuK9lJydlKqCEhtGLp2WWG-GOrVo5JdiCmaxs">>, - {ok, Data} = hb_gateway_client:data(ID, #{}), - PublicKey = <<42,183,56,140,176,233,209,5,127,163,72,53,49,236,186,130,211,130,140,225,211,232,192,141,45,12,157,249,161,137,243,82>>, - Anchor = <<"ZbExyvGrJKOJTJcHMtKzoOZVCQBkjZ+5">>, - Signature = <<195,61,110,250,0,176,46,214,165,148,100,201,169,114,248,103,197,128,202,114,63,81,94,116,107,255,65,7,68,173,199,26,58,68,236,61,193,62,61,52,131,1,254,201,159,40,41,69,220,171,220,63,189,140,40,102,164,20,75,145,199,246,231,8>>, - TX = dev_arweave_common:reset_ids(#tx{ - format = 1, - signature_type = {eddsa, ed25519}, - signature = Signature, - owner = PublicKey, - target = <<>>, - anchor = Anchor, - data = Data, - data_size = byte_size(Data), - tags = [{<<"Content-Type">>,<<"image/png">>}] - }), - ?assert(ar_bundles:verify_item(TX), TX#tx.format). - %% verifysignature does work becasue it is for a proper TX not an Data Item - %?assert(verify_signature(TX), TX#tx.format), - %%?assert(verify(TX), TX#tx.format), From c7e20bd3df9065dcd12793587d727f41aced6a26 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Thu, 27 Nov 2025 18:03:08 +0000 Subject: [PATCH 06/17] test: Add test where some fields are removed --- src/ar_bundles.erl | 25 +++++++++++++++++++++++++ src/ar_tx.erl | 2 +- src/ar_wallet.erl | 1 - 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index ab7847d24..db5592f68 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -771,6 +771,31 @@ bundle_map_with_eddsa_test() -> ?assertEqual(Item1#tx.data, (maps:get(<<"key1">>, BundleItem#tx.data))#tx.data), ?assert(verify_item(BundleItem)). +eddsa_cases_test() -> + Key = ar_wallet:new(?EDDSA_KEY_TYPE), + %% Owner and SignatureType defined during signing process. + Item1 = sign_item(#tx{ + format = ans104, + target = crypto:strong_rand_bytes(32), + anchor = crypto:strong_rand_bytes(32), + tags = [{<<"tag1">>, <<"value1">>}, {<<"tag2">>, <<"value2">>}], + data = <<"item1_data">> + }, Key), + Bundle = serialize(dev_arweave_common:normalize(Item1)), + BundleItem = deserialize(Bundle), + %% Sign a valid transaction and then do not provide + ?assert(verify_item(BundleItem)), + %% Missing Anchor should fail + ?assertNot(verify_item(BundleItem#tx{anchor = <<>>})), + %% Tags + ?assertNot(verify_item(BundleItem#tx{tags = []})), + %% Owner + ?assertNot(verify_item(BundleItem#tx{owner = crypto:strong_rand_bytes(32)})), + %% Target + ?assertNot(verify_item(BundleItem#tx{target = <<>>})), + %% Data + ?assertNot(verify_item(BundleItem#tx{data = <<>>})), + ok. extremely_large_bundle_test() -> W = ar_wallet:new(), diff --git a/src/ar_tx.erl b/src/ar_tx.erl index 07eba967f..0b2d52189 100644 --- a/src/ar_tx.erl +++ b/src/ar_tx.erl @@ -711,7 +711,7 @@ tx_to_json_struct_happy_test() -> id = crypto:strong_rand_bytes(32), anchor = crypto:strong_rand_bytes(32), owner = Owner, - signature_type = ?EDDSA_KEY_TYPE, + signature_type = ?RSA_KEY_TYPE, owner_address = ar_wallet:to_address(Owner, ?RSA_KEY_TYPE), %% Not in JSON tags = [], target = <<>>, diff --git a/src/ar_wallet.erl b/src/ar_wallet.erl index a7f072060..85107bf69 100644 --- a/src/ar_wallet.erl +++ b/src/ar_wallet.erl @@ -21,7 +21,6 @@ new(KeyType = {KeyAlg, PublicExpnt}) when KeyType =:= {rsa, 65537} -> new(KeyType = {KeyAlg, Curve}) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> {Pub, Priv} = crypto:generate_key(KeyAlg, Curve), {{KeyType, Priv, Pub}, {KeyType, Pub}}. - %{{ed_pri, Curve, Pub, Priv}, {ed_pub, Curve, Pub}}. %% @doc Sign some data with a private key. sign(Key, Data) -> From ef9256821aa3ad433d9510f9e0d3493e43e5492b Mon Sep 17 00:00:00 2001 From: speeddragon Date: Fri, 28 Nov 2025 12:08:57 +0000 Subject: [PATCH 07/17] test: Remove check for unsuported 64 bytes signature --- src/ar_tx.erl | 6 ++---- src/dev_codec_tx.erl | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ar_tx.erl b/src/ar_tx.erl index 0b2d52189..205bb85a8 100644 --- a/src/ar_tx.erl +++ b/src/ar_tx.erl @@ -313,10 +313,8 @@ tx_to_json_struct( data_root = DataRoot, denomination = Denomination }) -> - hb_util:ok_or_throw(SigType, - lists:member(SigType, [?RSA_KEY_TYPE, ?EDDSA_KEY_TYPE]), - {invalid_signature_type, SigType} - ), + %% Only RSA supported for now + ?RSA_KEY_TYPE = SigType, Fields = [ {<<"format">>, case Format of diff --git a/src/dev_codec_tx.erl b/src/dev_codec_tx.erl index 8e07ec376..369d9597d 100644 --- a/src/dev_codec_tx.erl +++ b/src/dev_codec_tx.erl @@ -326,7 +326,6 @@ enforce_valid_tx_test() -> {data_root_too_short_31, BaseTX#tx{data_root = BadID31}, {invalid_field, data_root, BadID31}}, {data_root_too_long_33, BaseTX#tx{data_root = BadID33}, {invalid_field, data_root, BadID33}}, {signature_invalid_size_1, BaseTX#tx{signature = SigInvalidSize1}, {invalid_field, signature, SigInvalidSize1}}, - {signature_invalid_size_64, BaseTX#tx{signature = SigInvalidSize64}, {invalid_field, signature, SigInvalidSize64}}, {signature_invalid_size_66, BaseTX#tx{signature = SigInvalidSize66}, {invalid_field, signature, SigInvalidSize66}}, {signature_invalid_size_511, BaseTX#tx{signature = SigInvalidSize511}, {invalid_field, signature, SigInvalidSize511}}, {signature_too_long_513, BaseTX#tx{signature = SigTooLong513}, {invalid_field, signature, SigTooLong513}}, From 8423d541729d30ad4ea6bf7a9b1c05e65cfa42ff Mon Sep 17 00:00:00 2001 From: speeddragon Date: Fri, 28 Nov 2025 18:19:47 +0000 Subject: [PATCH 08/17] fix: Improvements --- src/ar_bundles.erl | 18 +----------------- src/dev_codec_ans104_from.erl | 8 ++++++-- src/dev_codec_tx.erl | 4 ++-- src/hb_gateway_client.erl | 17 ++++++++++++++++- 4 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index db5592f68..b7a8c6cd3 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -755,22 +755,6 @@ bundle_map_test() -> ?assertEqual(Item1#tx.data, (maps:get(<<"key1">>, BundleItem#tx.data))#tx.data), ?assert(verify_item(BundleItem)). -bundle_map_with_eddsa_test() -> - W = ar_wallet:new(?EDDSA_KEY_TYPE), - Item1 = sign_item(#tx{ - format = ans104, - data = <<"item1_data">> - }, W), - Item2 = sign_item(#tx{ - format = ans104, - anchor = crypto:strong_rand_bytes(32), - data = #{<<"key1">> => Item1} - }, W), - Bundle = serialize(dev_arweave_common:normalize(Item2)), - BundleItem = deserialize(Bundle), - ?assertEqual(Item1#tx.data, (maps:get(<<"key1">>, BundleItem#tx.data))#tx.data), - ?assert(verify_item(BundleItem)). - eddsa_cases_test() -> Key = ar_wallet:new(?EDDSA_KEY_TYPE), %% Owner and SignatureType defined during signing process. @@ -783,7 +767,7 @@ eddsa_cases_test() -> }, Key), Bundle = serialize(dev_arweave_common:normalize(Item1)), BundleItem = deserialize(Bundle), - %% Sign a valid transaction and then do not provide + %% Sign a valid transaction and verify it ?assert(verify_item(BundleItem)), %% Missing Anchor should fail ?assertNot(verify_item(BundleItem#tx{anchor = <<>>})), diff --git a/src/dev_codec_ans104_from.erl b/src/dev_codec_ans104_from.erl index a60e90505..973745104 100644 --- a/src/dev_codec_ans104_from.erl +++ b/src/dev_codec_ans104_from.erl @@ -203,13 +203,17 @@ with_unsigned_commitment( with_signed_commitment( Item, Device, FieldCommitments, Tags, UncommittedMessage, CommittedKeys, Opts) -> - Address = hb_util:human_id(ar_wallet:to_address(Item#tx.owner)), + Address = hb_util:human_id(ar_wallet:to_address(Item#tx.owner, Item#tx.signature_type)), ID = hb_util:human_id(Item#tx.id), ExtraCommitments = hb_maps:merge( FieldCommitments, hb_maps:with(?BUNDLE_KEYS, Tags), Opts ), + Type = case Item#tx.signature_type of + ?RSA_KEY_TYPE -> <<"rsa-pss-sha256">>; + ?EDDSA_KEY_TYPE -> <<"ed25519">> + end, Commitment = filter_unset( hb_maps:merge( @@ -221,7 +225,7 @@ with_signed_commitment( <<"signature">> => hb_util:encode(Item#tx.signature), <<"keyid">> => <<"publickey:", (hb_util:encode(Item#tx.owner))/binary>>, - <<"type">> => <<"rsa-pss-sha256">>, + <<"type">> => Type, <<"bundle">> => bundle_commitment_key(Tags, Opts), <<"original-tags">> => original_tags(Item, Opts) }, diff --git a/src/dev_codec_tx.erl b/src/dev_codec_tx.erl index 369d9597d..7f9ee2f9a 100644 --- a/src/dev_codec_tx.erl +++ b/src/dev_codec_tx.erl @@ -218,7 +218,7 @@ enforce_valid_tx(TX) -> {invalid_field, data_root, TX#tx.data_root} ), hb_util:ok_or_throw(TX, - hb_util:check_size(TX#tx.signature, [64, 65, byte_size(?DEFAULT_SIG)]), + hb_util:check_size(TX#tx.signature, [65, byte_size(?DEFAULT_SIG)]), {invalid_field, signature, TX#tx.signature} ), hb_util:ok_or_throw(TX, @@ -305,7 +305,6 @@ enforce_valid_tx_test() -> SigInvalidSize66 = crypto:strong_rand_bytes(66), SigInvalidSize511 = crypto:strong_rand_bytes(511), SigTooLong513 = crypto:strong_rand_bytes(byte_size(?DEFAULT_SIG)+1), - FailureCases = [ {not_a_tx_record, not_a_tx_record_atom, {invalid_tx, not_a_tx_record_atom}}, @@ -326,6 +325,7 @@ enforce_valid_tx_test() -> {data_root_too_short_31, BaseTX#tx{data_root = BadID31}, {invalid_field, data_root, BadID31}}, {data_root_too_long_33, BaseTX#tx{data_root = BadID33}, {invalid_field, data_root, BadID33}}, {signature_invalid_size_1, BaseTX#tx{signature = SigInvalidSize1}, {invalid_field, signature, SigInvalidSize1}}, + {signature_invalid_size_64, BaseTX#tx{signature = SigInvalidSize64}, {invalid_field, signature, SigInvalidSize64}}, {signature_invalid_size_66, BaseTX#tx{signature = SigInvalidSize66}, {invalid_field, signature, SigInvalidSize66}}, {signature_invalid_size_511, BaseTX#tx{signature = SigInvalidSize511}, {invalid_field, signature, SigInvalidSize511}}, {signature_too_long_513, BaseTX#tx{signature = SigTooLong513}, {invalid_field, signature, SigTooLong513}}, diff --git a/src/hb_gateway_client.erl b/src/hb_gateway_client.erl index 1ec57645d..9d20c72a0 100644 --- a/src/hb_gateway_client.erl +++ b/src/hb_gateway_client.erl @@ -425,11 +425,26 @@ l1_transaction_test() -> %% @doc Test l2 message from graphql l2_dataitem_test() -> _Node = hb_http_server:start_node(#{}), - {ok, Res} = read(<<"oyo3_hCczcU7uYhfByFZ3h0ELfeMMzNacT-KpRoJK6g">>, #{}), + ID = <<"oyo3_hCczcU7uYhfByFZ3h0ELfeMMzNacT-KpRoJK6g">>, + {ok, Res} = read(ID, #{}), ?event(gateway, {l2_dataitem, Res}), + CommitmentType = hb_util:deep_get([<<"commitments">>, ID, <<"type">>], Res, not_found), + ?assertEqual(<<"rsa-pss-sha256">>, CommitmentType), Data = maps:get(<<"data">>, Res), ?assertEqual(<<"Hello World">>, Data). +%% @doc ed25519 L2 Transaction test +l2_dataitem_ed25519_test() -> + _Node = hb_http_server:start_node(#{}), + ID = <<"AwrAs-HaBlc8xeI8sw6Wpbi7A0weQWeXYwW20CpX5oM">>, + {ok, Res} = read(ID, #{}), + ?event(gateway, {l2_dataitem, Res}), + Data = maps:get(<<"data">>, Res), + CommitmentType = hb_util:deep_get([<<"commitments">>, ID, <<"type">>], Res, not_found), + ?assertEqual(<<"ed25519">>, CommitmentType), + erlang:display(Res), + ?assertEqual(<<"{\"displayName\":\"Test Hub\",\"description\":\"This is a test hub created in the test suite\",\"externalurl\":\"\",\"image\":\"\"}">>, Data). + %% @doc Test optimistic index ao_dataitem_test() -> _Node = hb_http_server:start_node(#{}), From 85b8a4306d7736c3526a0a89c164c601ccc0bbc9 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Fri, 28 Nov 2025 19:59:10 +0000 Subject: [PATCH 09/17] fix: Cleanup --- src/ar_bundles.erl | 8 ++++---- src/ar_wallet.erl | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index b7a8c6cd3..6cf700f4e 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -771,13 +771,13 @@ eddsa_cases_test() -> ?assert(verify_item(BundleItem)), %% Missing Anchor should fail ?assertNot(verify_item(BundleItem#tx{anchor = <<>>})), - %% Tags + %% Missing Tags should fail ?assertNot(verify_item(BundleItem#tx{tags = []})), - %% Owner + %% Missing Owner should fail ?assertNot(verify_item(BundleItem#tx{owner = crypto:strong_rand_bytes(32)})), - %% Target + %% Missing Target should fail ?assertNot(verify_item(BundleItem#tx{target = <<>>})), - %% Data + %% Missing Data should fail ?assertNot(verify_item(BundleItem#tx{data = <<>>})), ok. diff --git a/src/ar_wallet.erl b/src/ar_wallet.erl index 85107bf69..ad6921fd0 100644 --- a/src/ar_wallet.erl +++ b/src/ar_wallet.erl @@ -91,7 +91,7 @@ to_address(PubKey, {rsa, 65537}) -> to_address(PubKey, {ecdsa, 256}) -> to_ecdsa_address(PubKey); to_address(PubKey, {eddsa, ed25519}) -> - arweave_ao_address(PubKey). + to_eddsa_address(PubKey). %% @doc Generate a new wallet public and private key, with a corresponding keyfile. %% The provided key is used as part of the file name. @@ -240,7 +240,7 @@ hash_address(PubKey) -> to_ecdsa_address(PubKey) -> hb_keccak:key_to_ethereum_address(PubKey). -arweave_ao_address(PubKey) -> +to_eddsa_address(PubKey) -> Hash = crypto:hash(sha256, PubKey), base64:encode(Hash, #{padding => false, mode => urlsafe}). From 13a15568ac28ee1b485f45be56fa7bbb075d675c Mon Sep 17 00:00:00 2001 From: speeddragon Date: Fri, 28 Nov 2025 20:16:12 +0000 Subject: [PATCH 10/17] fix: Ignore digest type on ed25519 --- src/ar_wallet.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ar_wallet.erl b/src/ar_wallet.erl index ad6921fd0..e9e04002c 100644 --- a/src/ar_wallet.erl +++ b/src/ar_wallet.erl @@ -38,8 +38,8 @@ sign({{rsa, PublicExpnt}, Priv, Pub}, Data, DigestType) when PublicExpnt =:= 655 privateExponent = binary:decode_unsigned(Priv) } ); -sign({KeyType = {KeyAlg, Curve}, Priv, _Pub}, Data, DigestType) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> - crypto:sign(KeyAlg, DigestType, Data, [Priv, Curve]); +sign({KeyType = {KeyAlg, Curve}, Priv, _Pub}, Data, _DigestType) when KeyType =:= {?EDDSA_SIGN_ALG, ed25519} -> + crypto:sign(KeyAlg, none, Data, [Priv, Curve]); sign({{KeyType, Priv, Pub}, {KeyType, Pub}}, Data, DigestType) -> sign({KeyType, Priv, Pub}, Data, DigestType). From b3f0235cd3ea7f6e07197ef0fa9c2e0b0b59ff4a Mon Sep 17 00:00:00 2001 From: speeddragon Date: Fri, 28 Nov 2025 20:21:25 +0000 Subject: [PATCH 11/17] impr: Add test to committer value for ed25519 --- src/hb_gateway_client.erl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hb_gateway_client.erl b/src/hb_gateway_client.erl index 9d20c72a0..89497553d 100644 --- a/src/hb_gateway_client.erl +++ b/src/hb_gateway_client.erl @@ -442,7 +442,9 @@ l2_dataitem_ed25519_test() -> Data = maps:get(<<"data">>, Res), CommitmentType = hb_util:deep_get([<<"commitments">>, ID, <<"type">>], Res, not_found), ?assertEqual(<<"ed25519">>, CommitmentType), - erlang:display(Res), + CommitmentCommitter = hb_util:deep_get([<<"commitments">>, ID, <<"committer">>], Res, not_found), + ?assertEqual(<<"ejhYD9Cw9VCsVik6yGLoclo3CLRvAITHTZamLY_6ro4">>, CommitmentCommitter), + %% Check Data ?assertEqual(<<"{\"displayName\":\"Test Hub\",\"description\":\"This is a test hub created in the test suite\",\"externalurl\":\"\",\"image\":\"\"}">>, Data). %% @doc Test optimistic index From e91e62ab8b2b194aa8098aaa760698ca28e41376 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Fri, 28 Nov 2025 22:07:20 +0000 Subject: [PATCH 12/17] fix: Add opts to deep_get call --- src/hb_gateway_client.erl | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/hb_gateway_client.erl b/src/hb_gateway_client.erl index 89497553d..15d3dbebb 100644 --- a/src/hb_gateway_client.erl +++ b/src/hb_gateway_client.erl @@ -428,7 +428,13 @@ l2_dataitem_test() -> ID = <<"oyo3_hCczcU7uYhfByFZ3h0ELfeMMzNacT-KpRoJK6g">>, {ok, Res} = read(ID, #{}), ?event(gateway, {l2_dataitem, Res}), - CommitmentType = hb_util:deep_get([<<"commitments">>, ID, <<"type">>], Res, not_found), + Opts = #{}, + CommitmentType = hb_util:deep_get( + [<<"commitments">>, ID, <<"type">>], + Res, + not_found, + Opts + ), ?assertEqual(<<"rsa-pss-sha256">>, CommitmentType), Data = maps:get(<<"data">>, Res), ?assertEqual(<<"Hello World">>, Data). @@ -439,12 +445,23 @@ l2_dataitem_ed25519_test() -> ID = <<"AwrAs-HaBlc8xeI8sw6Wpbi7A0weQWeXYwW20CpX5oM">>, {ok, Res} = read(ID, #{}), ?event(gateway, {l2_dataitem, Res}), - Data = maps:get(<<"data">>, Res), - CommitmentType = hb_util:deep_get([<<"commitments">>, ID, <<"type">>], Res, not_found), + Opts = #{}, + CommitmentType = hb_util:deep_get( + [<<"commitments">>, ID, <<"type">>], + Res, + not_found, + Opts + ), ?assertEqual(<<"ed25519">>, CommitmentType), - CommitmentCommitter = hb_util:deep_get([<<"commitments">>, ID, <<"committer">>], Res, not_found), + CommitmentCommitter = hb_util:deep_get( + [<<"commitments">>, ID, <<"committer">>], + Res, + not_found, + Opts + ), ?assertEqual(<<"ejhYD9Cw9VCsVik6yGLoclo3CLRvAITHTZamLY_6ro4">>, CommitmentCommitter), %% Check Data + Data = maps:get(<<"data">>, Res), ?assertEqual(<<"{\"displayName\":\"Test Hub\",\"description\":\"This is a test hub created in the test suite\",\"externalurl\":\"\",\"image\":\"\"}">>, Data). %% @doc Test optimistic index From 8b022c2874a0fc9474a7130c2720e2ebbcdbdaad Mon Sep 17 00:00:00 2001 From: speeddragon Date: Fri, 28 Nov 2025 23:57:57 +0000 Subject: [PATCH 13/17] fix: Add test to verify message with ed25519 --- src/dev_message.erl | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/dev_message.erl b/src/dev_message.erl index 239307147..ddd3d9705 100644 --- a/src/dev_message.erl +++ b/src/dev_message.erl @@ -937,9 +937,16 @@ set_ignore_undefined_test() -> ?assertEqual(#{ <<"test-key">> => <<"Value1">> }, hb_private:reset(hb_util:ok(set(Base, Req, #{ hashpath => ignore })))). -verify_test() -> +verify_test_() -> + {foreach, fun () -> ok end, fun (_) -> ok end, [ + {"RSA", fun () -> test_verify(?RSA_KEY_TYPE) end}, + {"EDSSA", fun () -> test_verify(?EDDSA_KEY_TYPE) end} + ]}. + +test_verify(KeyType) -> Unsigned = #{ <<"a">> => <<"b">> }, - Signed = hb_message:commit(Unsigned, #{ priv_wallet => hb:wallet() }), + Wallet = ar_wallet:new(KeyType), + Signed = hb_message:commit(Unsigned, #{ priv_wallet => Wallet }), ?event({signed, Signed}), BadSigned = Signed#{ <<"a">> => <<"c">> }, ?event({bad_signed, BadSigned}), From 09789a0c0b05c77e0a5b2315dfbc3acdbbd36042 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Tue, 2 Dec 2025 10:40:18 +0000 Subject: [PATCH 14/17] test: Improve test code style --- src/hb_gateway_client.erl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hb_gateway_client.erl b/src/hb_gateway_client.erl index 15d3dbebb..b5eb78b1e 100644 --- a/src/hb_gateway_client.erl +++ b/src/hb_gateway_client.erl @@ -425,8 +425,7 @@ l1_transaction_test() -> %% @doc Test l2 message from graphql l2_dataitem_test() -> _Node = hb_http_server:start_node(#{}), - ID = <<"oyo3_hCczcU7uYhfByFZ3h0ELfeMMzNacT-KpRoJK6g">>, - {ok, Res} = read(ID, #{}), + {ok, Res} = read(ID = <<"oyo3_hCczcU7uYhfByFZ3h0ELfeMMzNacT-KpRoJK6g">>, #{}), ?event(gateway, {l2_dataitem, Res}), Opts = #{}, CommitmentType = hb_util:deep_get( From acd918b5b8aecad27d14eae12f1e9e25370c27b3 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Tue, 2 Dec 2025 10:41:21 +0000 Subject: [PATCH 15/17] test: Add ed25519 real data item --- src/ar_bundles.erl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index 6cf700f4e..a5ad028c4 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -1023,4 +1023,11 @@ generate_and_write_map_bundle_test_disabled() -> ?event(debug_test, {deserialized, {explicit, Deserialized}}), ?assert(verify_item(Deserialized)), ok = file:write_file( - <<"test/arbundles.js/ans104-map-bundle-erlang.bundle">>, Serialized). \ No newline at end of file + <<"test/arbundles.js/ans104-map-bundle-erlang.bundle">>, Serialized). + +deserialize_ed25519_transaction_test() -> + {ok, Serialized} = file:read_file(<<"test/arbundles.js/ans104-item-ed25519.bin">>), + Deserialized = deserialize(Serialized), + ?assertEqual({<<"Content-Type">>,<<"image/png">>}, Deserialized#tx.tags), + ?assertEqual(<<"ZbExyvGrJKOJTJcHMtKzoOZVCQBkjZ+5">>, Deserialized#tx.anchor), + ?assert(verify_item(Deserialized)). \ No newline at end of file From d118eaa2eac5c1b61b6433a95205060a3156281c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Magalh=C3=A3es?= Date: Tue, 2 Dec 2025 14:19:28 +0000 Subject: [PATCH 16/17] Update src/ar_bundles.erl Co-authored-by: JamesPiechota --- src/ar_bundles.erl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index a5ad028c4..0a8054072 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -1026,6 +1026,7 @@ generate_and_write_map_bundle_test_disabled() -> <<"test/arbundles.js/ans104-map-bundle-erlang.bundle">>, Serialized). deserialize_ed25519_transaction_test() -> + % ans104-item-ed25519.bin is dataitem 1rTy7gQuK9lJydlKqCEhtGLp2WWG-GOrVo5JdiCmaxs {ok, Serialized} = file:read_file(<<"test/arbundles.js/ans104-item-ed25519.bin">>), Deserialized = deserialize(Serialized), ?assertEqual({<<"Content-Type">>,<<"image/png">>}, Deserialized#tx.tags), From 21936fcedf908df17cf5ac0e6de4552556c52bb5 Mon Sep 17 00:00:00 2001 From: speeddragon Date: Tue, 2 Dec 2025 17:13:39 +0000 Subject: [PATCH 17/17] fix: Test and address encoding --- src/ar_bundles.erl | 4 +++- src/ar_wallet.erl | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ar_bundles.erl b/src/ar_bundles.erl index 0a8054072..94f25cae3 100644 --- a/src/ar_bundles.erl +++ b/src/ar_bundles.erl @@ -1029,6 +1029,8 @@ deserialize_ed25519_transaction_test() -> % ans104-item-ed25519.bin is dataitem 1rTy7gQuK9lJydlKqCEhtGLp2WWG-GOrVo5JdiCmaxs {ok, Serialized} = file:read_file(<<"test/arbundles.js/ans104-item-ed25519.bin">>), Deserialized = deserialize(Serialized), - ?assertEqual({<<"Content-Type">>,<<"image/png">>}, Deserialized#tx.tags), + ?assertEqual([{<<"Content-Type">>,<<"image/png">>}], Deserialized#tx.tags), ?assertEqual(<<"ZbExyvGrJKOJTJcHMtKzoOZVCQBkjZ+5">>, Deserialized#tx.anchor), + ?assertEqual(<<"ejhYD9Cw9VCsVik6yGLoclo3CLRvAITHTZamLY_6ro4">>, + hb_util:human_id(ar_wallet:to_address(Deserialized#tx.owner, Deserialized#tx.signature_type))), ?assert(verify_item(Deserialized)). \ No newline at end of file diff --git a/src/ar_wallet.erl b/src/ar_wallet.erl index e9e04002c..d5670e9b9 100644 --- a/src/ar_wallet.erl +++ b/src/ar_wallet.erl @@ -89,7 +89,7 @@ to_address({{_, _, PubKey}, {_, PubKey}}, _) -> to_address(PubKey, {rsa, 65537}) -> to_rsa_address(PubKey); to_address(PubKey, {ecdsa, 256}) -> - to_ecdsa_address(PubKey); + to_ecdsa_address(PubKey); to_address(PubKey, {eddsa, ed25519}) -> to_eddsa_address(PubKey). @@ -241,8 +241,7 @@ to_ecdsa_address(PubKey) -> hb_keccak:key_to_ethereum_address(PubKey). to_eddsa_address(PubKey) -> - Hash = crypto:hash(sha256, PubKey), - base64:encode(Hash, #{padding => false, mode => urlsafe}). + hash_address(PubKey). %%%=================================================================== %%% Private functions.