diff --git a/core/src/main/java/com/bloxbean/cardano/client/account/Account.java b/core/src/main/java/com/bloxbean/cardano/client/account/Account.java index f6ed7c7a..a2743b61 100644 --- a/core/src/main/java/com/bloxbean/cardano/client/account/Account.java +++ b/core/src/main/java/com/bloxbean/cardano/client/account/Account.java @@ -343,6 +343,10 @@ public HdKeyPair drepHdKeyPair() { return getDRepKeyPair(); } + /** + * CIP-129 compatible drep id + * @return bech32 encoded drep id (CIP-129) + */ public String drepId() { if (drepId == null || drepId.isEmpty()) { drepId = DRepKey.from(drepHdKeyPair()).dRepId(); @@ -351,6 +355,16 @@ public String drepId() { return drepId; } + /** + * Generates and returns the legacy drep id (CIP-105 Deprecated version). + * The identifier is derived from the DRep HD key pair. + * + * @return the legacy DRep id (CIP 105 Deprecated version) in string format. + */ + public String legacyDRepId() { + return DRepKey.from(drepHdKeyPair()).legacyDRepId(); + } + /** * Get {@link DRepKey} from DRep Hd key pair {@link HdKeyPair} * @return DRepKey diff --git a/core/src/test/java/com/bloxbean/cardano/client/account/AccountCIP105KeysTest.java b/core/src/test/java/com/bloxbean/cardano/client/account/AccountCIP105KeysTest.java index 9975619a..1fa9eb69 100644 --- a/core/src/test/java/com/bloxbean/cardano/client/account/AccountCIP105KeysTest.java +++ b/core/src/test/java/com/bloxbean/cardano/client/account/AccountCIP105KeysTest.java @@ -63,23 +63,22 @@ void testDRepVerificationKeyHash(CIP105TestVector testVector) { DRepKey drepKey = account.drepKey(); assertThat(HexUtil.encodeHexString(drepKey.verificationKeyHash())).isEqualTo(testVector.getDrepVerificationKeyHash()); - assertThat(drepKey.dRepId()).isEqualTo(testVector.getDrepId()); - assertThat(account.drepId()).isEqualTo(testVector.getDrepId()); + assertThat(drepKey.bech32VerificationKeyHash()).isEqualTo(testVector.getDrepVkhBech32()); } //The following two tests are not Account api specific. But it's here for completeness of TestVector @ParameterizedTest @MethodSource("testVectorsProvider") void testDrepIdScriptHash1(CIP105TestVector testVector) { - var drepId = DRepKey.dRepScriptId(testVector.getDrepScriptHash1()); - assertThat(drepId).isEqualTo(testVector.getDrepScriptHash1Bech32()); + var drepScriptHash = DRepKey.bech32ScriptHash(HexUtil.decodeHexString(testVector.getDrepScriptHash1())); + assertThat(drepScriptHash).isEqualTo(testVector.getDrepScriptHash1Bech32()); } @ParameterizedTest @MethodSource("testVectorsProvider") void testDrepIdScriptHash2(CIP105TestVector testVector) { - var drepId = DRepKey.dRepScriptId(testVector.getDrepScriptHash2()); - assertThat(drepId).isEqualTo(testVector.getDrepScriptHash2Bech32()); + var drepScriptHash = DRepKey.bech32ScriptHash(HexUtil.decodeHexString(testVector.getDrepScriptHash2())); + assertThat(drepScriptHash).isEqualTo(testVector.getDrepScriptHash2Bech32()); } //-- Constitutional Committee Cold Tests @@ -126,7 +125,7 @@ void testConstitutionalCommitteeColdVerificationKeyHash(CIP105TestVector testVec var committeeColdKey = deriveAccount(testVector).committeeColdKey(); assertThat(HexUtil.encodeHexString(committeeColdKey.verificationKeyHash())).isEqualTo(testVector.getCommitteeColdVerificationKeyHash()); - assertThat(committeeColdKey.bech32VerificationKeyHash()).isEqualTo(testVector.getCommitteeColdId()); + assertThat(committeeColdKey.bech32VerificationKeyHash()).isEqualTo(testVector.getCommitteeColdVkhBech32()); } @ParameterizedTest @@ -187,7 +186,7 @@ void testConstitutionalCommitteeHotVerificationKeyHash(CIP105TestVector testVect var committeeHotKey = deriveAccount(testVector).committeeHotKey(); assertThat(HexUtil.encodeHexString(committeeHotKey.verificationKeyHash())).isEqualTo(testVector.getCommitteeHotVerificationKeyHash()); - assertThat(committeeHotKey.bech32VerificationKeyHash()).isEqualTo(testVector.getCommitteeHotId()); + assertThat(committeeHotKey.bech32VerificationKeyHash()).isEqualTo(testVector.getCommitteeHotVkhBech32()); } @ParameterizedTest diff --git a/core/src/test/java/com/bloxbean/cardano/client/account/AccountTest.java b/core/src/test/java/com/bloxbean/cardano/client/account/AccountTest.java index 7de3d76f..e4388fd0 100644 --- a/core/src/test/java/com/bloxbean/cardano/client/account/AccountTest.java +++ b/core/src/test/java/com/bloxbean/cardano/client/account/AccountTest.java @@ -427,6 +427,9 @@ void testDRepId() { Account account = new Account(Networks.testnet(), mnemonicPhrase); String drepId = account.drepId(); - assertThat(drepId).isEqualTo("drep18hf6wcv9aaq426duj8kcc5kp9pauz9ac8znh8jmckm80sf7fetw"); + assertThat(drepId).isEqualTo("drep1yg7a8fmpshh5z4tfhjg7mrzjcy58hsghhqu2wu7t0zmva7qhqjauh"); + + String legacyDRepId = account.legacyDRepId(); + assertThat(legacyDRepId).isEqualTo("drep18hf6wcv9aaq426duj8kcc5kp9pauz9ac8znh8jmckm80sf7fetw"); } } diff --git a/core/src/test/java/com/bloxbean/cardano/client/account/CIP105TestVector.java b/core/src/test/java/com/bloxbean/cardano/client/account/CIP105TestVector.java index 4a89196c..36a3a724 100644 --- a/core/src/test/java/com/bloxbean/cardano/client/account/CIP105TestVector.java +++ b/core/src/test/java/com/bloxbean/cardano/client/account/CIP105TestVector.java @@ -23,8 +23,9 @@ public class CIP105TestVector { private String drepExtendedSigningKeyBech32; private String drepExtendedVerificationKey; private String drepExtendedVerificationKeyBech32; + private String legacyDRepId; private String drepVerificationKeyHash; - private String drepId; + private String drepVkhBech32; private String drepScriptHash1; private String drepScriptHash1Bech32; private String drepScriptHash2; @@ -39,7 +40,8 @@ public class CIP105TestVector { private String committeeColdExtendedVerificationKey; private String committeeColdExtendedVerificationKeyBech32; private String committeeColdVerificationKeyHash; - private String committeeColdId; + private String legacyCommitteeColdId; + private String committeeColdVkhBech32; private String coldScriptHash1; private String coldScriptHash1Bech32; private String coldScriptHash2; @@ -55,7 +57,8 @@ public class CIP105TestVector { private String committeeHotExtendedVerificationKey; private String committeeHotExtendedVerificationKeyBech32; private String committeeHotVerificationKeyHash; - private String committeeHotId; + private String legacyCommitteeHotId; + private String committeeHotVkhBech32; private String ccHotScriptHash1; private String ccHotScriptHash1Bech32; private String ccHotScriptHash2; @@ -79,7 +82,8 @@ public static CIP105TestVector testVector1() { .drepExtendedVerificationKey("f74d7ac30513ac1825715fd0196769761fca6e7f69de33d04ef09a0c417a752b1d8411029969123371cde99fb075730f1da4fd41ee7acefba7e211f0e20c91ca") .drepExtendedVerificationKeyBech32("drep_xvk17axh4sc9zwkpsft3tlgpjemfwc0u5mnld80r85zw7zdqcst6w543mpq3q2vkjy3nw8x7n8asw4es78dyl4q7u7kwlwn7yy0sugxfrjs6z25qe") .drepVerificationKeyHash("a5b45515a3ff8cb7c02ce351834da324eb6dfc41b5779cb5e6b832aa") - .drepId("drep15k6929drl7xt0spvudgcxndryn4kmlzpk4meed0xhqe25nle07s") + .drepVkhBech32("drep_vkh15k6929drl7xt0spvudgcxndryn4kmlzpk4meed0xhqe254czjh2") + .legacyDRepId("drep15k6929drl7xt0spvudgcxndryn4kmlzpk4meed0xhqe25nle07s") .drepScriptHash1("d0657126dbf0c135a7224d91ca068f5bf769af6d1f1df0bce5170ec5") .drepScriptHash1Bech32("drep_script16pjhzfkm7rqntfezfkgu5p50t0mkntmdruwlp089zu8v29l95rg") .drepScriptHash2("ae5acf0511255d647c84b3184a2d522bf5f6c5b76b989f49bd383bdd") @@ -93,7 +97,8 @@ public static CIP105TestVector testVector1() { .committeeColdExtendedVerificationKey("a9781abfc1604a18ebff6fc35062c000a7a66fdca1323710ed38c1dfc3315beac601968e75ff3052ffa675aedaaea49ff36cb23036df105e28e1d32b4527e6cf") .committeeColdExtendedVerificationKeyBech32("cc_cold_xvk149up407pvp9p36lldlp4qckqqzn6vm7u5yerwy8d8rqalse3t04vvqvk3e6l7vzjl7n8ttk646jflumvkgcrdhcstc5wr5etg5n7dnc8nqv5d") .committeeColdVerificationKeyHash("fefb9596ed670ad2c9978d78fe4eb36ba24cbba0a62fa4cdd0c2dcf5") - .committeeColdId("cc_cold1lmaet9hdvu9d9jvh34u0un4ndw3yewaq5ch6fnwsctw02xxwylj") + .legacyCommitteeColdId("cc_cold1lmaet9hdvu9d9jvh34u0un4ndw3yewaq5ch6fnwsctw02xxwylj") + .committeeColdVkhBech32("cc_cold_vkh1lmaet9hdvu9d9jvh34u0un4ndw3yewaq5ch6fnwsctw0243cw47") .coldScriptHash1("ae6f2a27554d5e6971ef3e933e4f0be7ed7aeb60f6f93dfb81cd6e1c") .coldScriptHash1Bech32("cc_cold_script14ehj5f64f40xju0086fnunctulkh46mq7munm7upe4hpcwpcatv") .coldScriptHash2("119c20cecfedfdba057292f76bb110afa3ab472f9c35a85daf492316") @@ -107,7 +112,8 @@ public static CIP105TestVector testVector1() { .committeeHotExtendedVerificationKey("792a7f83cab90261f72ef57ee94a65ca9b0c71c1be2c8fdd5318c3643b20b52f5487e846e9a708b27681d6835fa2dac968108b3c845e379597491e6b476aa0b2") .committeeHotExtendedVerificationKeyBech32("cc_hot_xvk10y48lq72hypxraew74lwjjn9e2dscuwphckglh2nrrpkgweqk5h4fplggm56wz9jw6qadq6l5tdvj6qs3v7ggh3hjkt5j8ntga42pvs5rvh0a") .committeeHotVerificationKeyHash("f6d29c0f7164d37610cbf67b126a993beb24a076d0653f1fa069588f") - .committeeHotId("cc_hot17mffcrm3vnfhvyxt7ea3y65e804jfgrk6pjn78aqd9vg7xpq8dv") + .legacyCommitteeHotId("cc_hot17mffcrm3vnfhvyxt7ea3y65e804jfgrk6pjn78aqd9vg7xpq8dv") + .committeeHotVkhBech32("cc_hot_vkh17mffcrm3vnfhvyxt7ea3y65e804jfgrk6pjn78aqd9vg7vk5akz") .ccHotScriptHash1("d27a4229c92ec8961b6bfd32a87380dcee4a08c77b0d6c8b33f180e8") .ccHotScriptHash1Bech32("cc_hot_script16fayy2wf9myfvxmtl5e2suuqmnhy5zx80vxkezen7xqwskncf40") .ccHotScriptHash2("62e0798c7036ff35862cf42f4e7ada06f7fb5b6465390082a691be14") @@ -129,7 +135,8 @@ public static CIP105TestVector testVector2() { .drepExtendedVerificationKey("70344fe0329bbacbb33921e945daed181bd66889333eb73f3bb10ad8e4669976a523761cec4182672a9592638e7017aa82ae6c1508377f4068d000a8cef56a30") .drepExtendedVerificationKeyBech32("drep_xvk1wq6ylcpjnwavhveey855tkhdrqdav6yfxvltw0emky9d3erxn9m22gmkrnkyrqn8922eycuwwqt64q4wds2ssdmlgp5dqq9gem6k5vq23ph3c") .drepVerificationKeyHash("1ed314af7d3ff8fcd320c73eb58524d774ca38733ee00ebca81bd63a") - .drepId("drep1rmf3ftma8lu0e5eqculttpfy6a6v5wrn8msqa09gr0tr5rgcuy9") + .drepVkhBech32("drep_vkh1rmf3ftma8lu0e5eqculttpfy6a6v5wrn8msqa09gr0tr590rpdl") + .legacyDRepId("drep1rmf3ftma8lu0e5eqculttpfy6a6v5wrn8msqa09gr0tr5rgcuy9") .drepScriptHash1("3e11f3d9b39639fbb9d59c6efec7b7c1e9dbcb104523c7a4b194c45c") .drepScriptHash1Bech32("drep_script18cgl8kdnjculhww4n3h0a3ahc85ahjcsg53u0f93jnz9c0339av") .drepScriptHash2("bba45271823634a8ba9fdb981ad76df02cd2384a4e1b43c41b2734a9") @@ -143,7 +150,8 @@ public static CIP105TestVector testVector2() { .committeeColdExtendedVerificationKey("cab60e3b880ba64b252b942bb645d5e58ef4d6f243542fc28ce4051170171f913ee1839d84124acdea81c69ee7e6e828387e51067878f30cab414ec5f2e36b42") .committeeColdExtendedVerificationKeyBech32("cc_cold_xvk1e2mquwugpwnykfftjs4mv3w4uk80f4hjgd2zls5vusz3zuqhr7gnacvrnkzpyjkda2qud8h8um5zswr72yr8s78npj45znk97t3kkssryhkyv") .committeeColdVerificationKeyHash("e93734fae718e91bbf45c86f8cd81e7f9687e6cffe4c910dd1a4c360") - .committeeColdId("cc_cold1aymnf7h8rr53h069ephcekq707tg0ek0lexfzrw35npkq02wke0") + .legacyCommitteeColdId("cc_cold1aymnf7h8rr53h069ephcekq707tg0ek0lexfzrw35npkq02wke0") + .committeeColdVkhBech32("cc_cold_vkh1aymnf7h8rr53h069ephcekq707tg0ek0lexfzrw35npkquacunr") .coldScriptHash1("08d78337fcf51a2a9fe93dee7d21679a3c28948cd90184155040b3e4") .coldScriptHash1Bech32("cc_cold_script1prtcxdlu75dz48lf8hh86gt8ng7z39yvmyqcg92sgze7g6m8dtq") .coldScriptHash2("2e8b77ecaa9f003978dea86515cee6b97df4dff52298e60198d5b387") @@ -157,7 +165,8 @@ public static CIP105TestVector testVector2() { .committeeHotExtendedVerificationKey("783ae09be2f648b59483a9bee5cace8d68c7e6e2819bfb5a1a00fbf204bea06e31609b9d64a7103fa9ab1bcdadfdea2d2366b3be0268df7f68edc9b36f8d300e") .committeeHotExtendedVerificationKeyBech32("cc_hot_xvk10qawpxlz7eytt9yr4xlwtjkw345v0ehzsxdlkks6qralyp975phrzcymn4j2wypl4x43hnddlh4z6gmxkwlqy6xl0a5wmjdnd7xnqrsvak8ry") .committeeHotVerificationKeyHash("d1d4ebdb19689e95e097919bd8712441e89b41ec36de47bf40344f85") - .committeeHotId("cc_hot1682whkcedz0ftcyhjxdasufyg85fks0vxm0y006qx38c2jz0ae0") + .legacyCommitteeHotId("cc_hot1682whkcedz0ftcyhjxdasufyg85fks0vxm0y006qx38c2jz0ae0") + .committeeHotVkhBech32("cc_hot_vkh1682whkcedz0ftcyhjxdasufyg85fks0vxm0y006qx38c2c4m8zp") .ccHotScriptHash1("bdf295c04cac9c78a69bca06cb8f2cffbee76d739759e80ec09a0655") .ccHotScriptHash1Bech32("cc_hot_script1hheftszv4jw83f5megrvhrevl7lwwmtnjav7srkqngr92gna52t") .ccHotScriptHash2("6a0b26bbf030bb6c2c8e62b0ef77c84494d771e81517ccf1434d5e26") @@ -179,7 +188,8 @@ public static CIP105TestVector testVector3() { .drepExtendedVerificationKey("a4a2f459fcc98e7fe0acbea096f4b1fb342cb73aa6c41f62d4d6ca1464179dd65fd61ed957d6d0b2dfd6c8e2279e3eb2d5538a7399e908ddf12d1b7bfcb4b6a8") .drepExtendedVerificationKeyBech32("drep_xvk15j30gk0uex88lc9vh6sfda93lv6zede65mzp7ck56m9pgeqhnht9l4s7m9tad59jmltv3c38nclt942n3feen6ggmhcj6xmmlj6td2qu4ce82") .drepVerificationKeyHash("33e587eb1f44e51f4307eeed7ede619008bc4d1c32c18099d6367329") - .drepId("drep1x0jc06clgnj37sc8amkhahnpjqytcnguxtqcpxwkxeejj4y6sqm") + .drepVkhBech32("drep_vkh1x0jc06clgnj37sc8amkhahnpjqytcnguxtqcpxwkxeejjnrpdfp") + .legacyDRepId("drep1x0jc06clgnj37sc8amkhahnpjqytcnguxtqcpxwkxeejj4y6sqm") .drepScriptHash1("f241fd096625b515f464b2b35ddebe93a2e6e2ec2e7dcac8c8ae5a33") .drepScriptHash1Bech32("drep_script17fql6ztxyk63taryk2e4mh47jw3wdchv9e7u4jxg4edrx89ym9g") .drepScriptHash2("7802a8b9e80878cc7b17c451e8778dfeef22cb7b2c2031885b881d68") @@ -193,7 +203,8 @@ public static CIP105TestVector testVector3() { .committeeColdExtendedVerificationKey("8bb15c318356b4ba8cdb2b899fd5b9c80c427d92149b6a3bd5fb3aa36dedb997a24968bef7b0cdba5393b6e494fa9e1f9f33672940dd0fbec967efef0ac4f9ce") .committeeColdExtendedVerificationKeyBech32("cc_cold_xvk13wc4cvvr266t4rxm9wyel4deeqxyylvjzjdk5w74lva2xm0dhxt6yjtghmmmpnd62wfmdey5l20pl8envu55phg0hmyk0ml0ptz0nns9cqjlk") .committeeColdVerificationKeyHash("f0ab03c6ebd8d1b4515a3dcda3caac0737689dc3c50c5c0dfbc791f2") - .committeeColdId("cc_cold17z4s83htmrgmg5268hx68j4vqumk38wrc5x9cr0mc7glyntw6cl") + .legacyCommitteeColdId("cc_cold17z4s83htmrgmg5268hx68j4vqumk38wrc5x9cr0mc7glyntw6cl") + .committeeColdVkhBech32("cc_cold_vkh17z4s83htmrgmg5268hx68j4vqumk38wrc5x9cr0mc7glyqucsjn") .coldScriptHash1("a0bc49cfc9e0394a5ee7a3cba53063479786cf1f3c03392c6694b6fd") .coldScriptHash1Bech32("cc_cold_script15z7ynn7fuqu55hh850962vrrg7tcdncl8spnjtrxjjm06y3avt9") .coldScriptHash2("eddd105e3fcb6e60bd23474bdeb9363078f0416bc967bcede1b80194") @@ -207,7 +218,8 @@ public static CIP105TestVector testVector3() { .committeeHotExtendedVerificationKey("5f44dd7d934ab0591f743df462535ce12f6ce68ad49069289fee4cbfbcdddb6b34c92fcf2646fe96132f62bfb2a4af92a811beba1bc7fd0066133e5e1ddcbe14") .committeeHotExtendedVerificationKeyBech32("cc_hot_xvk1tazd6lvnf2c9j8m58h6xy56uuyhkee526jgxj2ylaextl0xamd4nfjf0eunydl5kzvhk90aj5jhe92q3h6aph3laqpnpx0j7rhwtu9qe7dhsc") .committeeHotVerificationKeyHash("c2a74e9bca6240d947f29beb7ded9604974016da2d48e3a7c3644cc4") - .committeeHotId("cc_hot1c2n5ax72vfqdj3ljn04hmmvkqjt5q9k694yw8f7rv3xvgxas90x") + .legacyCommitteeHotId("cc_hot1c2n5ax72vfqdj3ljn04hmmvkqjt5q9k694yw8f7rv3xvgxas90x") + .committeeHotVkhBech32("cc_hot_vkh1c2n5ax72vfqdj3ljn04hmmvkqjt5q9k694yw8f7rv3xvgv2yl5g") .ccHotScriptHash1("5eddfce1eb7399f516fa0a19975369a8f38819765e58543fc6dc7c96") .ccHotScriptHash1Bech32("cc_hot_script1tmwlec0twwvl29h6pgvew5mf4recsxtktev9g07xm37fv46mta9") .ccHotScriptHash2("c7bcbba29f1f6e47df350691f858ec44035a217ea5a2103cad7ab874") @@ -229,7 +241,8 @@ public static CIP105TestVector testVector4() { .drepExtendedVerificationKey("ab5d2187f2f4419421b0457f7ac8ab0d4b4ec0802af5de21dde64f603248a381571a0b4d927777b6b1c2e61d361b72ac39b5f0edf498a630665e7f1e9ffd09b7") .drepExtendedVerificationKeyBech32("drep_xvk14dwjrplj73qeggdsg4lh4j9tp495asyq9t6augwaue8kqvjg5wq4wxstfkf8waakk8pwv8fkrde2cwd47rklfx9xxpn9ulc7nl7sndcvdjh2m") .drepVerificationKeyHash("c1a342f0dfb82b93ca2e6b406bacb04802f7d56a99d8f95a80a8b6c5") - .drepId("drep1cx359uxlhq4e8j3wddqxht9sfqp004t2n8v0jk5q4zmv27sh0h5") + .drepVkhBech32("drep_vkh1cx359uxlhq4e8j3wddqxht9sfqp004t2n8v0jk5q4zmv2chvj7w") + .legacyDRepId("drep1cx359uxlhq4e8j3wddqxht9sfqp004t2n8v0jk5q4zmv27sh0h5") .drepScriptHash1("c5875315458ec9c20a91f15d36debd43df8f1fd75cc4e118db0a6691") .drepScriptHash1Bech32("drep_script1ckr4x9293myuyz5379wndh4ag00c787htnzwzxxmpfnfzjzk4cq") .drepScriptHash2("723e4a09b4897bddf8861f963312a76df8183b6ee438bdd4157b5d6c") @@ -243,7 +256,8 @@ public static CIP105TestVector testVector4() { .committeeColdExtendedVerificationKey("fec199631209a0d2e3f5e758693e4324be9b5067767637b4f0ef7f52fd6b0aaa7566bf28da60f674137792214fdb4e9935d16ad52b1f321b2f2fbb77eab5a716") .committeeColdExtendedVerificationKeyBech32("cc_cold_xvk1lmqejccjpxsd9cl4uavxj0jryjlfk5r8wemr0d8saal49lttp2482e4l9rdxpan5zdmeyg20md8fjdw3dt2jk8ejrvhjlwmha266w9syf55nr") .committeeColdVerificationKeyHash("4cb32ae705fb3bba3cac9742356880c912a36a4a7cca74d4956c7f41") - .committeeColdId("cc_cold1fjej4ec9lvam509vjapr26yqeyf2x6j20n98f4y4d3l5zygwxt4") + .legacyCommitteeColdId("cc_cold1fjej4ec9lvam509vjapr26yqeyf2x6j20n98f4y4d3l5zygwxt4") + .committeeColdVkhBech32("cc_cold_vkh1fjej4ec9lvam509vjapr26yqeyf2x6j20n98f4y4d3l5zhlcvpe") .coldScriptHash1("07ede1a2cda4f48e9f33759e76397bfdbf71267b92e5f17dd96e94be") .coldScriptHash1Bech32("cc_cold_script1qlk7rgkd5n6ga8enwk08vwtmlklhzfnmjtjlzlwed62tuycmmh5") .coldScriptHash2("ed41b6d1b16802132c147639cef6264e4fa3b093aeba965962a73061") @@ -257,7 +271,8 @@ public static CIP105TestVector testVector4() { .committeeHotExtendedVerificationKey("428aaa4d7c9ed7776b5019d7e64419f27f0ad3d47078b8963ac2382b7b7a755366f8e9d1c694e53ae02d57b6dbc1b2a066ab8d85112880aede4605b333b2da50") .committeeHotExtendedVerificationKeyBech32("cc_hot_xvk1g2925ntunmthw66sr8t7v3qe7fls4575wput3936cguzk7m6w4fkd78f68rffef6uqk40dkmcxe2qe4t3kz3z2yq4m0yvpdnxwed55q798msd") .committeeHotVerificationKeyHash("a9eb44d0aa1ce5559b7c22270ac23d1e61bf2e114dd8e5a44ed3a529") - .committeeHotId("cc_hot14845f592rnj4txmuygns4s3aresm7ts3fhvwtfzw6wjjj3l0520") + .legacyCommitteeHotId("cc_hot14845f592rnj4txmuygns4s3aresm7ts3fhvwtfzw6wjjj3l0520") + .committeeHotVkhBech32("cc_hot_vkh14845f592rnj4txmuygns4s3aresm7ts3fhvwtfzw6wjjjmgmw3p") .ccHotScriptHash1("9d55b1aab952b24807bedbc9af8283b1d798023432f484a2d9160dfe") .ccHotScriptHash1Bech32("cc_hot_script1n42mr24e22eyspa7m0y6lq5rk8tesq35xt6gfgkezcxluqysk4n") .ccHotScriptHash2("4241b3550fc0aca9895b50d3d722bbca8f197fce155c9843817c7ac5") diff --git a/crypto/src/main/java/com/bloxbean/cardano/client/crypto/cip1852/CIP1852.java b/crypto/src/main/java/com/bloxbean/cardano/client/crypto/cip1852/CIP1852.java index 28e5265a..1251b970 100644 --- a/crypto/src/main/java/com/bloxbean/cardano/client/crypto/cip1852/CIP1852.java +++ b/crypto/src/main/java/com/bloxbean/cardano/client/crypto/cip1852/CIP1852.java @@ -71,11 +71,39 @@ public HdKeyPair getKeyPairFromAccountKey(byte[] accountKey, DerivationPath deri public HdPublicKey getPublicKeyFromAccountPubKey(byte[] accountPubKey, DerivationPath derivationPath) { HdPublicKey accountHdPubKey = HdPublicKey.fromBytes(accountPubKey); + return getPublicKeyFromAccountPubKey(accountHdPubKey, derivationPath.getRole().getValue(), derivationPath.getIndex().getValue()); + } + + /** + * Derives a hierarchical deterministic (HD) public key for a specific role and index + * from the given account-level public key. + * + * @param accountPubKey the account-level public key as a byte array + * @param role the specific role in the derivation path for the key + * @param index the index number in the derivation path for the key + * @return the derived HD public key for the specified role and index + * @throws CryptoException if the account-level public key is invalid + */ + public HdPublicKey getPublicKeyFromAccountPubKey(byte[] accountPubKey, int role, int index) { + HdPublicKey accountHdPubKey = HdPublicKey.fromBytes(accountPubKey); + + return getPublicKeyFromAccountPubKey(accountHdPubKey, role, index); + } + + /** + * Derives a hierarchical deterministic (HD) public key for a specific role and index + * from the given account-level HD public key. + * + * @param accountHdPubKey the account-level HD public key + * @param role the specific role in the derivation path for the key + * @param index the index number in the derivation path for the key + * @return the derived HD public key for the specified role and index + */ + public static HdPublicKey getPublicKeyFromAccountPubKey(HdPublicKey accountHdPubKey, int role, int index) { HdKeyGenerator hdKeyGenerator = new HdKeyGenerator(); - HdPublicKey roleHdPubKey = hdKeyGenerator.getChildPublicKey(accountHdPubKey, derivationPath.getRole().getValue()); - HdPublicKey indexHdPubKey = hdKeyGenerator.getChildPublicKey(roleHdPubKey, derivationPath.getIndex().getValue()); + HdPublicKey roleHdPubKey = hdKeyGenerator.getChildPublicKey(accountHdPubKey, role); - return indexHdPubKey; + return hdKeyGenerator.getChildPublicKey(roleHdPubKey, index); } } diff --git a/governance/src/main/java/com/bloxbean/cardano/client/governance/GovId.java b/governance/src/main/java/com/bloxbean/cardano/client/governance/GovId.java new file mode 100644 index 00000000..b5b5c300 --- /dev/null +++ b/governance/src/main/java/com/bloxbean/cardano/client/governance/GovId.java @@ -0,0 +1,112 @@ +package com.bloxbean.cardano.client.governance; + +import com.bloxbean.cardano.client.address.CredentialType; +import com.bloxbean.cardano.client.crypto.Bech32; +import com.bloxbean.cardano.client.util.HexUtil; + +/** + * The GovId class provides methods for generating governance related ids. + * It implements CIP-129 + */ +public class GovId { + private static final byte CC_HOT_KEY_TYPE = 0b0000_0000; + private static final byte CC_COLD_KEY_TYPE = 0b0001_0000; + private static final byte DREP_KEY_TYPE = 0b0010_0000; + + private static final byte KEY_HASH_CRED_TYPE = 0b0000_0010; + private static final byte SCRIPT_HASH_CRED_TYPE = 0b0000_0011; + + private static final String CC_COLD_PREFIX = "cc_cold"; + private static final String CC_HOT_PREFIX = "cc_hot"; + private static final String DREP_PREFIX = "drep"; + private static final String GOV_ACTION_PREFIX = "gov_action"; + + private GovId() { + + } + + public static String ccColdFromKeyHash(byte[] keyHash) { + byte[] idBytes = getIdentifierBytes(CC_COLD_KEY_TYPE, KEY_HASH_CRED_TYPE, keyHash); + return Bech32.encode(idBytes, CC_COLD_PREFIX); + } + + public static String ccColdFromScriptHash(byte[] scriptHash) { + byte[] idBytes = getIdentifierBytes(CC_COLD_KEY_TYPE, SCRIPT_HASH_CRED_TYPE, scriptHash); + return Bech32.encode(idBytes, CC_COLD_PREFIX); + } + + public static String ccHotFromKeyHash(byte[] keyHash) { + byte[] idBytes = getIdentifierBytes(CC_HOT_KEY_TYPE, KEY_HASH_CRED_TYPE, keyHash); + return Bech32.encode(idBytes, CC_HOT_PREFIX); + } + + public static String ccHotFromScriptHash(byte[] scriptHash) { + byte[] idBytes = getIdentifierBytes(CC_HOT_KEY_TYPE, SCRIPT_HASH_CRED_TYPE, scriptHash); + return Bech32.encode(idBytes, CC_HOT_PREFIX); + } + + public static String drepFromKeyHash(byte[] keyHash) { + byte[] idBytes = getIdentifierBytes(DREP_KEY_TYPE, KEY_HASH_CRED_TYPE, keyHash); + return Bech32.encode(idBytes, DREP_PREFIX); + } + + public static String drepFromScriptHash(byte[] scriptHash) { + byte[] idBytes = getIdentifierBytes(DREP_KEY_TYPE, SCRIPT_HASH_CRED_TYPE, scriptHash); + return Bech32.encode(idBytes, DREP_PREFIX); + } + + public static CredentialType credType(String bech32GovId) { + byte[] govIdBytes = Bech32.decode(bech32GovId).data; + byte header = govIdBytes[0]; + + var credType = header & 0b0000_1111; + + switch (credType) { + case KEY_HASH_CRED_TYPE: + return CredentialType.Key; + case SCRIPT_HASH_CRED_TYPE: + return CredentialType.Script; + default: + throw new IllegalArgumentException("Invalid credential type : " + credType); + } + } + + public static CredentialType credTypeFromIdBytes(String govIdBytes) { + return credTypeFromIdBytes(HexUtil.decodeHexString(govIdBytes)); + } + + public static CredentialType credTypeFromIdBytes(byte[] govIdBytes) { + byte header = govIdBytes[0]; + var credType = header & 0b0000_1111; + + switch (credType) { + case KEY_HASH_CRED_TYPE: + return CredentialType.Key; + case SCRIPT_HASH_CRED_TYPE: + return CredentialType.Script; + default: + throw new IllegalArgumentException("Invalid credential type : " + credType); + } + } + + public static String govAction(String txHash, int index) { + String indexHex = String.format("%02x", index); + + byte[] mergedBytes = HexUtil.decodeHexString(txHash + indexHex); + return Bech32.encode(mergedBytes, GOV_ACTION_PREFIX); + } + + private static byte[] getIdentifierBytes(byte keyType, byte credType, byte[] keyHash) { + byte header = getHeader(keyType, credType); + + byte[] idBytes = new byte[1 + keyHash.length]; + idBytes[0] = header; + + System.arraycopy(keyHash, 0, idBytes, 1, keyHash.length); + return idBytes; + } + + private static byte getHeader(byte keyType, byte credType) { + return (byte) (keyType | credType & 0xF); + } +} diff --git a/governance/src/main/java/com/bloxbean/cardano/client/governance/DRepId.java b/governance/src/main/java/com/bloxbean/cardano/client/governance/LegacyDRepId.java similarity index 78% rename from governance/src/main/java/com/bloxbean/cardano/client/governance/DRepId.java rename to governance/src/main/java/com/bloxbean/cardano/client/governance/LegacyDRepId.java index 4899f67b..9a5900ac 100644 --- a/governance/src/main/java/com/bloxbean/cardano/client/governance/DRepId.java +++ b/governance/src/main/java/com/bloxbean/cardano/client/governance/LegacyDRepId.java @@ -7,20 +7,25 @@ import com.bloxbean.cardano.client.transaction.spec.governance.DRepType; import com.bloxbean.cardano.client.util.HexUtil; -public class DRepId { +/** + * DEPRECATED: CIP 105 DRep Id implementation. + * This class is deprecated. + * + * @deprecated Use {@link com.bloxbean.cardano.client.governance.GovId} for CIP-129 implementation + */ +@Deprecated(since = "0.6.3") +public class LegacyDRepId { public static final String DREP_ID_PREFIX = "drep"; public static final String DREP_ID_SCRIPT_PREFIX = "drep_script"; public static String fromVerificationKey(VerificationKey verificationKey) { byte[] keyHash = Blake2bUtil.blake2bHash224(verificationKey.getBytes()); - String drepId = Bech32.encode(keyHash, DREP_ID_PREFIX); - return drepId; + return Bech32.encode(keyHash, DREP_ID_PREFIX); } public static String fromVerificationKeyBytes(byte[] bytes) { byte[] keyHash = Blake2bUtil.blake2bHash224(bytes); - String drepId = Bech32.encode(keyHash, DREP_ID_PREFIX); - return drepId; + return Bech32.encode(keyHash, DREP_ID_PREFIX); } public static String fromKeyHash(String keyHash) { @@ -28,8 +33,7 @@ public static String fromKeyHash(String keyHash) { } public static String fromKeyHash(byte[] keyHash) { - String drepId = Bech32.encode(keyHash, DREP_ID_PREFIX); - return drepId; + return Bech32.encode(keyHash, DREP_ID_PREFIX); } public static String fromScriptHash(String scriptHash) { @@ -37,8 +41,7 @@ public static String fromScriptHash(String scriptHash) { } public static String fromScriptHash(byte[] scriptHash) { - String drepId = Bech32.encode(scriptHash, DREP_ID_SCRIPT_PREFIX); - return drepId; + return Bech32.encode(scriptHash, DREP_ID_SCRIPT_PREFIX); } public static DRep toDrep(String drepId, DRepType drepType) { diff --git a/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKey.java b/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKey.java index d757ded8..7493eccd 100644 --- a/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKey.java +++ b/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKey.java @@ -5,6 +5,7 @@ import com.bloxbean.cardano.client.crypto.bip32.HdKeyPair; import com.bloxbean.cardano.client.crypto.bip32.key.HdPrivateKey; import com.bloxbean.cardano.client.crypto.bip32.key.HdPublicKey; +import com.bloxbean.cardano.client.governance.GovId; import com.bloxbean.cardano.client.util.HexUtil; import lombok.NonNull; @@ -17,7 +18,8 @@ public class CommitteeColdKey { private static final String CC_COLD_VK = "cc_cold_vk"; private static final String CC_COLD_XSK = "cc_cold_xsk"; private static final String CC_COLD_XVK = "cc_cold_xvk"; - private static final String CC_COLD = "cc_cold"; + + private static final String CC_COLD_VKH = "cc_cold_vkh"; private static final String CC_COLD_SCRIPT = "cc_cold_script"; private byte[] signingKey; @@ -155,8 +157,37 @@ public String bech32VerificationKeyHash() { return bech32VerificationKeyHash(verificationKeyHash()); } + /** + * Generates a CIP-129 Committee Cold ID by utilizing the verification key hash. + * + * @return A bech32 encoded string representing the Committee Cold ID derived from the verification key hash. + */ + public String id() { + return GovId.ccColdFromKeyHash(verificationKeyHash()); + } + //-- static methods to get bech32 encoded keys from key bytes + /** + * Converts a script hash to bech32 committee cold key id + * + * @param scriptHash the hex string representation of the script hash + * @return the script ID derived from the given script hash + */ + public static String scriptId(String scriptHash) { + return scriptId(HexUtil.decodeHexString(scriptHash)); + } + + /** + * Converts a script hash to bech32 committee cold key id + * + * @param scriptHash the script hash represented as a byte array + * @return the script ID derived from the given script hash + */ + public static String scriptId(byte[] scriptHash) { + return GovId.ccColdFromScriptHash(scriptHash); + } + /** * Get the bech32 encoded script hash * @param scriptHash script hash @@ -190,9 +221,10 @@ public static String bech32VerificationKeyHash(String verificationKeyHash) { * @return String bech32 encoded verification key hash */ public static String bech32VerificationKeyHash(byte[] verificationKeyHash) { - return Bech32.encode(verificationKeyHash, CC_COLD); + return Bech32.encode(verificationKeyHash, CC_COLD_VKH); } + /** * Get the bech32 encoded signing key * @param signingKey signing key diff --git a/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKey.java b/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKey.java index 6ded07f9..c9d1ad34 100644 --- a/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKey.java +++ b/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKey.java @@ -5,6 +5,7 @@ import com.bloxbean.cardano.client.crypto.bip32.HdKeyPair; import com.bloxbean.cardano.client.crypto.bip32.key.HdPrivateKey; import com.bloxbean.cardano.client.crypto.bip32.key.HdPublicKey; +import com.bloxbean.cardano.client.governance.GovId; import com.bloxbean.cardano.client.util.HexUtil; import lombok.NonNull; @@ -17,7 +18,7 @@ public class CommitteeHotKey { private static final String CC_HOT_VK = "cc_hot_vk"; private static final String CC_HOT_XSK = "cc_hot_xsk"; private static final String CC_HOT_XVK = "cc_hot_xvk"; - private static final String CC_HOT = "cc_hot"; + private static final String CC_HOT_VKH = "cc_hot_vkh"; private static final String CC_HOT_SCRIPT = "cc_hot_script"; private byte[] signingKey; @@ -154,8 +155,25 @@ public String bech32VerificationKeyHash() { return bech32VerificationKeyHash(verificationKeyHash()); } + /** + * Retrieves the bech32 encoded CIP-129 hot credential committee identifier derived from the verification key hash. + * + * @return the bech32 encoded hot credential committee identifier. + */ + public String id() { + return GovId.ccHotFromKeyHash(verificationKeyHash()); + } + //-- static methods to get bech32 encoded keys from key bytes + public static String scriptId(String scriptHash) { + return scriptId(HexUtil.decodeHexString(scriptHash)); + } + + public static String scriptId(byte[] scriptHash) { + return GovId.ccHotFromScriptHash(scriptHash); + } + /** * Get the bech32 encoded script hash * @param scriptHash script hash @@ -189,7 +207,7 @@ public static String bech32VerificationKeyHash(String verificationKeyHash) { * @return bech32 encoded verification key hash */ public static String bech32VerificationKeyHash(byte[] verificationKeyHash) { - return Bech32.encode(verificationKeyHash, CC_HOT); + return Bech32.encode(verificationKeyHash, CC_HOT_VKH); } /** diff --git a/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/DRepKey.java b/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/DRepKey.java index 6a9fb9f6..13d75b31 100644 --- a/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/DRepKey.java +++ b/governance/src/main/java/com/bloxbean/cardano/client/governance/keys/DRepKey.java @@ -2,21 +2,28 @@ import com.bloxbean.cardano.client.crypto.Bech32; import com.bloxbean.cardano.client.crypto.Blake2bUtil; +import com.bloxbean.cardano.client.crypto.VerificationKey; import com.bloxbean.cardano.client.crypto.bip32.HdKeyPair; import com.bloxbean.cardano.client.crypto.bip32.key.HdPrivateKey; import com.bloxbean.cardano.client.crypto.bip32.key.HdPublicKey; -import com.bloxbean.cardano.client.governance.DRepId; +import com.bloxbean.cardano.client.governance.GovId; +import com.bloxbean.cardano.client.governance.LegacyDRepId; +import com.bloxbean.cardano.client.util.HexUtil; import lombok.NonNull; /** * DRep key Bech32 encoding * CIP 105 - https://github.com/cardano-foundation/CIPs/tree/master/CIP-0105 + * + * This class also returns DRep Ids in CIP-129 format. */ public class DRepKey { - public static final String DREP_SK = "drep_sk"; + public static final String DREP_SK = "drep_sk"; private static final String DREP_VK = "drep_vk"; private static final String DREP_XSK = "drep_xsk"; private static final String DREP_XVK = "drep_xvk"; + private static final String DREP_VKH = "drep_vkh"; + private static final String DREP_SCRIPT = "drep_script"; private byte[] signingKey; private byte[] verificationKey; @@ -145,7 +152,19 @@ public byte[] verificationKeyHash() { } /** - * Get the DRepId + * Get the Bech32 encoded verification key hash + * If the verification key is not set, the method returns null. + * + * @return bech32 encoded verification key hash + */ + public String bech32VerificationKeyHash() { + if (verificationKey == null) return null; + + return bech32VerificationKeyHash(verificationKeyHash()); + } + + /** + * Get the DRepId (CIP-129) * @return DRepId */ public String dRepId() { @@ -153,33 +172,46 @@ public String dRepId() { return drepId(verificationKeyHash()); } + /** + * Get CIP 105 (deprecated) compatible drep id + * + * @deprecated Use drepId() instead + * + * @return bech32 encoded drep id (CIP 105 deprecatd version) + */ + @Deprecated(since = "0.6.3") + public String legacyDRepId() { + if (verificationKey == null) return null; + return LegacyDRepId.fromKeyHash(verificationKeyHash()); + } + //-- static methods to generate bech32 encoding directly from key bytes /** - * Get DRep Script Id from script hash + * Get DRep Script Id from script hash (CIP-129) * @param scriptHash script hash * @return bech32 encoded script hash */ public static String dRepScriptId(String scriptHash) { - return DRepId.fromScriptHash(scriptHash); + return GovId.drepFromScriptHash(HexUtil.decodeHexString(scriptHash)); } /** - * Get DRep Script Id from script hash + * Get DRep Script Id from script hash (CIP-129) * @param scriptHash script hash * @return bech32 encoded script hash */ public static String dRepScriptId(byte[] scriptHash) { - return DRepId.fromScriptHash(scriptHash); + return GovId.drepFromScriptHash(scriptHash); } /** - * Get drepId from key hash + * Get drepId from key hash (CIP-129) * @param keyHash key hash * @return drepId */ public static String drepId(byte[] keyHash) { - return DRepId.fromKeyHash(keyHash); + return GovId.drepFromKeyHash(keyHash); } /** @@ -217,4 +249,36 @@ public static String bech32ExtendedSigningKey(byte[] extendedSigningKey) { public static String bech32ExtendedVerificationKey(byte[] extendedVerificationKey) { return Bech32.encode(extendedVerificationKey, DREP_XVK); } + + /** + * Get the bech32 encoded verification key hash + * + * @param keyHash the byte array representing the verification key hash to encode + * @return a Bech32 encoded string of the verification key hash + */ + public static String bech32VerificationKeyHash(byte[] keyHash) { + return Bech32.encode(keyHash, DREP_VKH); + } + + /** + * Get the bech32 encoded script hash + * + * @param scriptHash the byte array representing the script hash to encode + * @return a Bech32 encoded string of the script hash + */ + public static String bech32ScriptHash(byte[] scriptHash) { + return Bech32.encode(scriptHash, DREP_SCRIPT); + } + + /** + * Encodes the verification key hash in Bech32 format. + * + * @param verificationKey the verification key from which the hash is computed + * @return a Bech32 encoded string representation of the verification key hash + */ + public static String bech32VerificationKeyHash(VerificationKey verificationKey) { + byte[] keyHash = Blake2bUtil.blake2bHash224(verificationKey.getBytes()); + return Bech32.encode(keyHash, DREP_VKH); + } + } diff --git a/governance/src/test/java/com/bloxbean/cardano/client/governance/GovIdTest.java b/governance/src/test/java/com/bloxbean/cardano/client/governance/GovIdTest.java new file mode 100644 index 00000000..6e57a42c --- /dev/null +++ b/governance/src/test/java/com/bloxbean/cardano/client/governance/GovIdTest.java @@ -0,0 +1,102 @@ +package com.bloxbean.cardano.client.governance; + +import com.bloxbean.cardano.client.address.CredentialType; +import com.bloxbean.cardano.client.util.HexUtil; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class GovIdTest { + + @Test + void ccColdFromScriptHash() { + String scriptHash ="00000000000000000000000000000000000000000000000000000000"; + String ccColdId = GovId.ccColdFromScriptHash(HexUtil.decodeHexString(scriptHash)); + + assertThat(ccColdId).isEqualTo("cc_cold1zvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6kflvs"); + } + + @Test + void ccHotFromKeyHashBytes() { + String keyHash ="00000000000000000000000000000000000000000000000000000000"; + String ccHotId = GovId.ccHotFromKeyHash(HexUtil.decodeHexString(keyHash)); + + assertThat(ccHotId).isEqualTo("cc_hot1qgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvcdjk7"); + } + + @Test + void drepFromKeyHash() { + String keyHash = "00000000000000000000000000000000000000000000000000000000"; + String drepId = GovId.drepFromKeyHash(HexUtil.decodeHexString(keyHash)); + + assertThat(drepId).isEqualTo("drep1ygqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq7vlc9n"); + } + + @Test + void keyType() { + var credType = GovId.credType("drep1ygqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq7vlc9n"); + assertThat(credType).isEqualTo(CredentialType.Key); + } + + @Test + void keyType2() { + var credType = GovId.credType("cc_hot1qgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvcdjk7"); + assertThat(credType).isEqualTo(CredentialType.Key); + } + + @Test + void scriptType() { + var credType = GovId.credType("cc_cold1zvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6kflvs"); + assertThat(credType).isEqualTo(CredentialType.Script); + } + + @Test + void keyTypeFromIdBytes() { + var credType = GovId.credTypeFromIdBytes("0200000000000000000000000000000000000000000000000000000000"); + assertThat(credType).isEqualTo(CredentialType.Key); + } + + @Test + void scriptTypeFromIdBytes() { + var credType = GovId.credTypeFromIdBytes("1300000000000000000000000000000000000000000000000000000000"); + assertThat(credType).isEqualTo(CredentialType.Script); + } + + @Test + void govActionId() { + String txHash = "0000000000000000000000000000000000000000000000000000000000000000"; + int index = 17; + + String govActionId = GovId.govAction(txHash, index); + assertThat(govActionId).isEqualTo("gov_action1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqpzklpgpf"); + } + + @Test + void govActionId2() { + String txHash = "1111111111111111111111111111111111111111111111111111111111111111"; + int index = 0; + + String govActionId = GovId.govAction(txHash, index); + assertThat(govActionId).isEqualTo("gov_action1zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsq6dmejn"); + } + + /**. TODO : Add tests for commented test cases + @Test + void ccHotFromKeyHash() { + String keyHash = "00000000000000000000000000000000000000000000000000000000"; + String ccHotId = GovId.ccHotFromKeyHash(keyHash); + + assertThat(ccHotId).isEqualTo("cc_hot1qgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvcdjk7"); + } + + @Test + void ccColdFromKeyHash() { + + } + + @Test + void drepFromScriptHash() { + + } + **/ +} diff --git a/governance/src/test/java/com/bloxbean/cardano/client/governance/DRepIdTest.java b/governance/src/test/java/com/bloxbean/cardano/client/governance/LegacyDRepIdTest.java similarity index 69% rename from governance/src/test/java/com/bloxbean/cardano/client/governance/DRepIdTest.java rename to governance/src/test/java/com/bloxbean/cardano/client/governance/LegacyDRepIdTest.java index 6c7c0977..c453785a 100644 --- a/governance/src/test/java/com/bloxbean/cardano/client/governance/DRepIdTest.java +++ b/governance/src/test/java/com/bloxbean/cardano/client/governance/LegacyDRepIdTest.java @@ -7,12 +7,12 @@ import static org.assertj.core.api.Assertions.assertThat; -class DRepIdTest { +class LegacyDRepIdTest { @Test void fromVerificationKey() { VerificationKey verificationKey = new VerificationKey("5820fbed0bbb5ec02297af05bc76979ef3228787d3db095092f67d867f4d5ce79944"); - String drepId = DRepId.fromVerificationKey(verificationKey); + String drepId = LegacyDRepId.fromVerificationKey(verificationKey); assertThat(drepId).isEqualTo("drep1vlmeg4vu96detgkf5srw427363svqemth2xde2e2xp5ywfsx2gn"); } @@ -20,55 +20,50 @@ void fromVerificationKey() { @SneakyThrows void fromVerificationKeyBytes() { byte[] vkBytes = HexUtil.decodeHexString("fbed0bbb5ec02297af05bc76979ef3228787d3db095092f67d867f4d5ce79944"); - String drepId = DRepId.fromVerificationKeyBytes(vkBytes); + String drepId = LegacyDRepId.fromVerificationKeyBytes(vkBytes); assertThat(drepId).isEqualTo("drep1vlmeg4vu96detgkf5srw427363svqemth2xde2e2xp5ywfsx2gn"); } @Test void fromKeyHash() { - String drepId = DRepId.fromKeyHash("74984fae4ca1715fa1f8759f9d871015ac87f449a85dea6cf9956da1"); + String drepId = LegacyDRepId.fromKeyHash("74984fae4ca1715fa1f8759f9d871015ac87f449a85dea6cf9956da1"); assertThat(drepId).isEqualTo("drep1wjvyltjv59c4lg0cwk0empcszkkg0azf4pw75m8ej4k6zuqfvt5"); } @Test void fromKeyHashBytes() { - String drepId = DRepId.fromKeyHash(HexUtil.decodeHexString("74984fae4ca1715fa1f8759f9d871015ac87f449a85dea6cf9956da1")); + String drepId = LegacyDRepId.fromKeyHash(HexUtil.decodeHexString("74984fae4ca1715fa1f8759f9d871015ac87f449a85dea6cf9956da1")); assertThat(drepId).isEqualTo("drep1wjvyltjv59c4lg0cwk0empcszkkg0azf4pw75m8ej4k6zuqfvt5"); } @Test void fromScriptHash() { - String drepId = DRepId.fromScriptHash("41868c2b4e5289022a3a1f6f47f86823bc605c609d2c47a2db58e04a"); + String drepId = LegacyDRepId.fromScriptHash("41868c2b4e5289022a3a1f6f47f86823bc605c609d2c47a2db58e04a"); assertThat(drepId).isEqualTo("drep_script1gxrgc26w22ysy236rah507rgyw7xqhrqn5ky0gkmtrsy553rrq7"); } @Test void fromScriptHashBytes() { - String drepId = DRepId.fromScriptHash(HexUtil.decodeHexString("41868c2b4e5289022a3a1f6f47f86823bc605c609d2c47a2db58e04a")); + String drepId = LegacyDRepId.fromScriptHash(HexUtil.decodeHexString("41868c2b4e5289022a3a1f6f47f86823bc605c609d2c47a2db58e04a")); assertThat(drepId).isEqualTo("drep_script1gxrgc26w22ysy236rah507rgyw7xqhrqn5ky0gkmtrsy553rrq7"); } @Test - public void testDRepScriptId1() { + void testDRepScriptId1() { String scriptHash = "d0657126dbf0c135a7224d91ca068f5bf769af6d1f1df0bce5170ec5"; String expectedDRepId = "drep_script16pjhzfkm7rqntfezfkgu5p50t0mkntmdruwlp089zu8v29l95rg"; - String drepId = DRepId.fromScriptHash(scriptHash); + String drepId = LegacyDRepId.fromScriptHash(scriptHash); assertThat(drepId).isEqualTo(expectedDRepId); } @Test - public void testDRepScriptId2() { + void testDRepScriptId2() { String scriptHash = "ae5acf0511255d647c84b3184a2d522bf5f6c5b76b989f49bd383bdd"; String expectedDRepId = "drep_script14edv7pg3y4wkglyykvvy5t2j906ld3dhdwvf7jda8qaa63d5kf4"; - String drepId = DRepId.fromScriptHash(scriptHash); + String drepId = LegacyDRepId.fromScriptHash(scriptHash); assertThat(drepId).isEqualTo(expectedDRepId); } - //TODO: Implement this - @Test - void toDrep() { - - } } diff --git a/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKeyTest.java b/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKeyTest.java index cccadaa3..70c54e17 100644 --- a/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKeyTest.java +++ b/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeColdKeyTest.java @@ -1,6 +1,8 @@ package com.bloxbean.cardano.client.governance.keys; +import com.bloxbean.cardano.client.crypto.Bech32; import com.bloxbean.cardano.client.crypto.bip32.HdKeyPair; +import com.bloxbean.cardano.client.crypto.bip32.key.HdPublicKey; import com.bloxbean.cardano.client.crypto.cip1852.CIP1852; import com.bloxbean.cardano.client.crypto.cip1852.DerivationPath; import com.bloxbean.cardano.client.util.HexUtil; @@ -170,7 +172,7 @@ void bech32VerificationKeyHash() { var hdKeyPair = getCommitteeColdKeyPair(); var committeeColdKey = CommitteeColdKey.from(hdKeyPair); - var expectedCommitteeColdVerificationKeyHash = "cc_cold1lmaet9hdvu9d9jvh34u0un4ndw3yewaq5ch6fnwsctw02xxwylj"; + var expectedCommitteeColdVerificationKeyHash = "cc_cold_vkh1lmaet9hdvu9d9jvh34u0un4ndw3yewaq5ch6fnwsctw0243cw47"; var bech32VerificationKeyHash = committeeColdKey.bech32VerificationKeyHash(); assertThat(bech32VerificationKeyHash).isEqualTo(expectedCommitteeColdVerificationKeyHash); @@ -196,6 +198,27 @@ void bech32ScriptHash2() { assertThat(bech32ScriptHash).isEqualTo(expectedCommitteeColdScriptHashBech32); } + @Test + void testCcCold_fromAccPubKeyXvk() { + String accountXvk = "acct_xvk1kxenc045r0l2u5ethalm89pej406fu3ltk3csy37x9jrx56f8yqquzpltg7ydf7qvxl9kw53q3qzp30799u69yvlvgl0s4pdtpux4yc8mgmff"; + var accountVKBytes = Bech32.decode(accountXvk).data; + + var ccColdDerivationPath = DerivationPath.createCommitteeColdKeyDerivationPathForAccount(0); + + HdPublicKey hdPublicKey = new CIP1852().getPublicKeyFromAccountPubKey(accountVKBytes, ccColdDerivationPath.getRole().getValue(), 0); //role = 4 + + CommitteeColdKey committeeColdKey = CommitteeColdKey.from(hdPublicKey); + assertThat(committeeColdKey.id()).isEqualTo("cc_cold1zgvh8vc489udnv2jrzez80hkn6ggre38kpng0tk5vw8rd7gu9rgs9"); + } + + @Test + void testScriptId() { + String scriptHash = "00000000000000000000000000000000000000000000000000000000"; + String ccColdId = CommitteeColdKey.scriptId(scriptHash); + + assertThat(ccColdId).isEqualTo("cc_cold1zvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6kflvs"); + } + private HdKeyPair getCommitteeColdKeyPair() { DerivationPath committeeColdKeyDerivationPath = DerivationPath.createCommitteeColdKeyDerivationPathForAccount(0); diff --git a/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKeyTest.java b/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKeyTest.java index eac99590..6eaedf07 100644 --- a/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKeyTest.java +++ b/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/CommitteeHotKeyTest.java @@ -1,6 +1,8 @@ package com.bloxbean.cardano.client.governance.keys; +import com.bloxbean.cardano.client.crypto.Bech32; import com.bloxbean.cardano.client.crypto.bip32.HdKeyPair; +import com.bloxbean.cardano.client.crypto.bip32.key.HdPublicKey; import com.bloxbean.cardano.client.crypto.cip1852.CIP1852; import com.bloxbean.cardano.client.crypto.cip1852.DerivationPath; import com.bloxbean.cardano.client.util.HexUtil; @@ -169,7 +171,7 @@ void bech32erificationKeyHash() { var hdKeyPair = getCommitteeHotKeyPair(); var committeeHotKey = CommitteeHotKey.from(hdKeyPair); - var expectedCommitteeHotVerificationKeyHash = "cc_hot17mffcrm3vnfhvyxt7ea3y65e804jfgrk6pjn78aqd9vg7xpq8dv"; + var expectedCommitteeHotVerificationKeyHash = "cc_hot_vkh17mffcrm3vnfhvyxt7ea3y65e804jfgrk6pjn78aqd9vg7vk5akz"; var bech32erificationKeyHash = committeeHotKey.bech32VerificationKeyHash(); assertThat(bech32erificationKeyHash).isEqualTo(expectedCommitteeHotVerificationKeyHash); @@ -195,6 +197,20 @@ void bech32ScriptHash2() { assertThat(bech32ScriptHash).isEqualTo(expectedCommitteeHotScriptHashBech32); } + + @Test + void testCcHot_fromAccPubKeyXvk() { + String accountXvk = "acct_xvk1kxenc045r0l2u5ethalm89pej406fu3ltk3csy37x9jrx56f8yqquzpltg7ydf7qvxl9kw53q3qzp30799u69yvlvgl0s4pdtpux4yc8mgmff"; + var accountVKBytes = Bech32.decode(accountXvk).data; + + var ccHotDerivationPath = DerivationPath.createCommitteeHotKeyDerivationPathForAccount(0); + + HdPublicKey hdPublicKey = new CIP1852().getPublicKeyFromAccountPubKey(accountVKBytes, ccHotDerivationPath.getRole().getValue(), 0); //role = 5 + + CommitteeHotKey committeeHotKey = CommitteeHotKey.from(hdPublicKey); + assertThat(committeeHotKey.id()).isEqualTo("cc_hot1qgxf280zt5yznyq6u9t57rqy3c6v5qj03cvy200cm66cgnsc9z9ht"); + } + private HdKeyPair getCommitteeHotKeyPair() { DerivationPath committeeHotKeyDerivationPath = DerivationPath.createCommitteeHotKeyDerivationPathForAccount(0); diff --git a/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/DRepKeyTest.java b/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/DRepKeyTest.java index 88337e2b..46ae6357 100644 --- a/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/DRepKeyTest.java +++ b/governance/src/test/java/com/bloxbean/cardano/client/governance/keys/DRepKeyTest.java @@ -1,8 +1,12 @@ package com.bloxbean.cardano.client.governance.keys; +import com.bloxbean.cardano.client.crypto.Bech32; +import com.bloxbean.cardano.client.crypto.VerificationKey; import com.bloxbean.cardano.client.crypto.bip32.HdKeyPair; +import com.bloxbean.cardano.client.crypto.bip32.key.HdPublicKey; import com.bloxbean.cardano.client.crypto.cip1852.CIP1852; import com.bloxbean.cardano.client.crypto.cip1852.DerivationPath; +import com.bloxbean.cardano.client.exception.CborSerializationException; import com.bloxbean.cardano.client.util.HexUtil; import org.junit.jupiter.api.Test; @@ -12,12 +16,8 @@ public class DRepKeyTest { private String mnemonic1 = "test walk nut penalty hip pave soap entry language right filter choice"; - public DRepKeyTest() { - - } - @Test - public void testDRepSigningAndVerificationKeys() { + void testDRepSigningAndVerificationKeys() { HdKeyPair drepKeyPair = getDRepKeyPair(); DRepKey dRepKey = DRepKey.from(drepKeyPair); @@ -42,7 +42,7 @@ public void testDRepSigningAndVerificationKeys() { @Test - public void testDRepExtendedSigningAndVerificationKeys() { + void testDRepExtendedSigningAndVerificationKeys() { HdKeyPair drepKeyPair = getDRepKeyPair(); DRepKey dRepKey = DRepKey.from(drepKeyPair); @@ -66,7 +66,7 @@ public void testDRepExtendedSigningAndVerificationKeys() { } @Test - public void testDRepSigningKeys_hdPrivateKey() { + void testDRepSigningKeys_hdPrivateKey() { HdKeyPair drepKeyPair = getDRepKeyPair(); DRepKey dRepKey = DRepKey.from(drepKeyPair.getPrivateKey()); @@ -90,7 +90,7 @@ public void testDRepSigningKeys_hdPrivateKey() { } @Test - public void testDRepVerificationKeys_hdPublicKey() { + void testDRepVerificationKeys_hdPublicKey() { HdKeyPair drepKeyPair = getDRepKeyPair(); DRepKey dRepKey = DRepKey.from(drepKeyPair.getPublicKey()); @@ -114,46 +114,81 @@ public void testDRepVerificationKeys_hdPublicKey() { } @Test - public void testDRepIdAndVKeyHash() { + void testBech32VkhAndVKeyHash() { HdKeyPair drepKeyPair = getDRepKeyPair(); DRepKey dRepKey = DRepKey.from(drepKeyPair); String expectedVKeyHash = "a5b45515a3ff8cb7c02ce351834da324eb6dfc41b5779cb5e6b832aa"; - String expectedDRepId = "drep15k6929drl7xt0spvudgcxndryn4kmlzpk4meed0xhqe25nle07s"; + String expectedDRepId = "drep_vkh15k6929drl7xt0spvudgcxndryn4kmlzpk4meed0xhqe254czjh2"; byte[] vKeyHash = dRepKey.verificationKeyHash(); - String drepId = dRepKey.dRepId(); + String bech32Vkh = dRepKey.bech32VerificationKeyHash(); assertThat(HexUtil.encodeHexString(vKeyHash)).isEqualTo(expectedVKeyHash); - assertThat(drepId).isEqualTo(expectedDRepId); + assertThat(bech32Vkh).isEqualTo(expectedDRepId); } @Test - public void testDRepScriptHash1() { - String dRepScriptId = DRepKey.dRepScriptId("d0657126dbf0c135a7224d91ca068f5bf769af6d1f1df0bce5170ec5"); + void testDRepScriptHashBytes1() { + String dRepScriptId = DRepKey.bech32ScriptHash(HexUtil.decodeHexString("d0657126dbf0c135a7224d91ca068f5bf769af6d1f1df0bce5170ec5")); String expectedDrepScriptId = "drep_script16pjhzfkm7rqntfezfkgu5p50t0mkntmdruwlp089zu8v29l95rg"; assertThat(dRepScriptId).isEqualTo(expectedDrepScriptId); } @Test - public void testDRepScriptHashBytes1() { - String dRepScriptId = DRepKey.dRepScriptId(HexUtil.decodeHexString("d0657126dbf0c135a7224d91ca068f5bf769af6d1f1df0bce5170ec5")); + void testDRepScriptHash2() { + String dRepScriptId = DRepKey.bech32ScriptHash(HexUtil.decodeHexString("ae5acf0511255d647c84b3184a2d522bf5f6c5b76b989f49bd383bdd")); - String expectedDrepScriptId = "drep_script16pjhzfkm7rqntfezfkgu5p50t0mkntmdruwlp089zu8v29l95rg"; + String expectedDrepScriptId = "drep_script14edv7pg3y4wkglyykvvy5t2j906ld3dhdwvf7jda8qaa63d5kf4"; assertThat(dRepScriptId).isEqualTo(expectedDrepScriptId); } @Test - public void testDRepScriptHash2() { - String dRepScriptId = DRepKey.dRepScriptId("ae5acf0511255d647c84b3184a2d522bf5f6c5b76b989f49bd383bdd"); + void testDRepId_fromAccPubKeyXvk() { + String accountXvk = "acct_xvk1kxenc045r0l2u5ethalm89pej406fu3ltk3csy37x9jrx56f8yqquzpltg7ydf7qvxl9kw53q3qzp30799u69yvlvgl0s4pdtpux4yc8mgmff"; + var accountVKBytes = Bech32.decode(accountXvk).data; - String expectedDrepScriptId = "drep_script14edv7pg3y4wkglyykvvy5t2j906ld3dhdwvf7jda8qaa63d5kf4"; - assertThat(dRepScriptId).isEqualTo(expectedDrepScriptId); + HdPublicKey hdPublicKey = new CIP1852().getPublicKeyFromAccountPubKey(accountVKBytes, 3, 0); + + var drepKey = DRepKey.from(hdPublicKey); + assertThat(drepKey.dRepId()).isEqualTo("drep1ytf29wgf5llmd22ankjewqrdcjvsx9zvyru2qlpwjyr042gajpq70"); + } + + @Test + void testDRepId_fromAccPubKeyXpub() { + String accountXvk = "xpub16nuts3mqurnek523dk35j37hwscsj90a098f7t77v4htwh5ana3ced0tv948hucq537c7l5ypd9d7vvgmtn6wy28xyj9wnp9ftkzqqqxe7kkj"; + var accountVKBytes = Bech32.decode(accountXvk).data; + + var drepDerivationPath = DerivationPath.createDRepKeyDerivationPathForAccount(0); + + HdPublicKey hdPublicKey = new CIP1852().getPublicKeyFromAccountPubKey(accountVKBytes, drepDerivationPath.getRole().getValue(), drepDerivationPath.getIndex().getValue()); + + var drepKey = DRepKey.from(hdPublicKey); + assertThat(drepKey.dRepId()).isEqualTo("drep1ytmnsfv8axjemak2jt26p5h9580csq0c3q5mfm26anr2zugd75lws"); + } + + + @Test + void testDRepId() { + String accountXvk = "acct_xvk1kxenc045r0l2u5ethalm89pej406fu3ltk3csy37x9jrx56f8yqquzpltg7ydf7qvxl9kw53q3qzp30799u69yvlvgl0s4pdtpux4yc8mgmff"; + var accountVKBytes = Bech32.decode(accountXvk).data; + + HdPublicKey hdPublicKey = new CIP1852().getPublicKeyFromAccountPubKey(accountVKBytes, 3, 0); + + var drepKey = DRepKey.from(hdPublicKey); + assertThat(drepKey.dRepId()).isEqualTo("drep1ytf29wgf5llmd22ankjewqrdcjvsx9zvyru2qlpwjyr042gajpq70"); + } + + @Test + void fromVerificationKey() throws CborSerializationException { + //https://github.com/cardano-foundation/CIPs/blob/master/CIP-0105/test-vectors/test-vector-2.md + VerificationKey verificationKey = VerificationKey.create(HexUtil.decodeHexString("70344fe0329bbacbb33921e945daed181bd66889333eb73f3bb10ad8e4669976")); + String bech32Vkh = DRepKey.bech32VerificationKeyHash(verificationKey); + assertThat(bech32Vkh).isEqualTo("drep_vkh1rmf3ftma8lu0e5eqculttpfy6a6v5wrn8msqa09gr0tr590rpdl"); } private HdKeyPair getDRepKeyPair() { - HdKeyPair hdKeyPair; DerivationPath drepDerivationPath = DerivationPath.createDRepKeyDerivationPathForAccount(0); return new CIP1852().getKeyPairFromMnemonic(mnemonic1, drepDerivationPath); diff --git a/quicktx/src/it/java/com/bloxbean/cardano/client/quicktx/GovernanceTxIT.java b/quicktx/src/it/java/com/bloxbean/cardano/client/quicktx/GovernanceTxIT.java index 35d6ddac..58dc476b 100644 --- a/quicktx/src/it/java/com/bloxbean/cardano/client/quicktx/GovernanceTxIT.java +++ b/quicktx/src/it/java/com/bloxbean/cardano/client/quicktx/GovernanceTxIT.java @@ -8,7 +8,7 @@ import com.bloxbean.cardano.client.common.model.Networks; import com.bloxbean.cardano.client.crypto.cip1852.DerivationPath; import com.bloxbean.cardano.client.function.helper.SignerProviders; -import com.bloxbean.cardano.client.governance.DRepId; +import com.bloxbean.cardano.client.governance.LegacyDRepId; import com.bloxbean.cardano.client.spec.UnitInterval; import com.bloxbean.cardano.client.transaction.spec.ProtocolParamUpdate; import com.bloxbean.cardano.client.transaction.spec.ProtocolVersion; @@ -366,7 +366,7 @@ void voteDelegation() { // stakeAddressRegistration(sender2Addr); QuickTxBuilder quickTxBuilder = new QuickTxBuilder(backendService); - DRep drep = DRepId.toDrep(sender1.drepId(), DRepType.ADDR_KEYHASH); + DRep drep = LegacyDRepId.toDrep(sender1.drepId(), DRepType.ADDR_KEYHASH); System.out.println("Drep : " + sender1.drepId()); Tx tx = new Tx()